From 8bf1cc141ecd5426393cde3c714525f133757a99 Mon Sep 17 00:00:00 2001 From: Saeed Vaziry Date: Mon, 7 Oct 2024 00:18:11 +0200 Subject: [PATCH] fixing routes --- app/Actions/User/UpdateProjects.php | 2 + app/Facades/Toast.php | 19 --- app/Helpers/Toast.php | 32 ---- app/Models/User.php | 9 +- app/Policies/UserPolicy.php | 2 +- app/Providers/AppServiceProvider.php | 11 +- app/Providers/FortifyServiceProvider.php | 63 -------- app/Providers/RouteServiceProvider.php | 2 +- app/Providers/WebServiceProvider.php | 2 +- app/Web/Pages/Settings/Users/Index.php | 2 +- .../Settings/Users/Widgets/UsersList.php | 18 +-- config/app.php | 1 - config/filament.php | 1 + config/fortify.php | 147 ------------------ routes/web.php | 4 - scripts/install.sh | 5 +- scripts/update.sh | 2 +- tests/Feature/Auth/AuthenticationTest.php | 47 ------ tests/Feature/Auth/LogoutTest.php | 29 ---- .../Feature/Auth/PasswordConfirmationTest.php | 43 ----- tests/Feature/Auth/PasswordResetTest.php | 64 -------- tests/Feature/UserTest.php | 87 +++++------ 22 files changed, 70 insertions(+), 522 deletions(-) delete mode 100644 app/Facades/Toast.php delete mode 100644 app/Helpers/Toast.php delete mode 100644 app/Providers/FortifyServiceProvider.php delete mode 100644 config/fortify.php delete mode 100644 tests/Feature/Auth/AuthenticationTest.php delete mode 100644 tests/Feature/Auth/LogoutTest.php delete mode 100644 tests/Feature/Auth/PasswordConfirmationTest.php delete mode 100644 tests/Feature/Auth/PasswordResetTest.php diff --git a/app/Actions/User/UpdateProjects.php b/app/Actions/User/UpdateProjects.php index b1cc1bc..c8bdc14 100644 --- a/app/Actions/User/UpdateProjects.php +++ b/app/Actions/User/UpdateProjects.php @@ -18,6 +18,8 @@ public function update(User $user, array $input): void $user->save(); } + $user->refresh(); + /** @var Project $firstProject */ $firstProject = $user->projects->first(); if (! $user->currentProject && $firstProject) { diff --git a/app/Facades/Toast.php b/app/Facades/Toast.php deleted file mode 100644 index 94d642f..0000000 --- a/app/Facades/Toast.php +++ /dev/null @@ -1,19 +0,0 @@ -toast('success', $message); - } - - public function error(string $message): void - { - $this->toast('error', $message); - } - - public function warning(string $message): void - { - $this->toast('warning', $message); - } - - public function info(string $message): void - { - $this->toast('info', $message); - } - - private function toast(string $type, string $message): void - { - session()->flash('toast.type', $type); - session()->flash('toast.message', $message); - } -} diff --git a/app/Models/User.php b/app/Models/User.php index 7b6205f..4e6aa83 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -5,6 +5,8 @@ use App\Enums\UserRole; use App\Traits\HasTimezoneTimestamps; use Carbon\Carbon; +use Filament\Models\Contracts\FilamentUser; +use Filament\Panel; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -39,7 +41,7 @@ * @property Carbon $created_at * @property Carbon $updated_at */ -class User extends Authenticatable +class User extends Authenticatable implements FilamentUser { use HasFactory; use HasTimezoneTimestamps; @@ -157,4 +159,9 @@ public function allServers(): Builder }); }); } + + public function canAccessPanel(Panel $panel): bool + { + return true; + } } diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index cc037f5..4e00ec1 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -31,6 +31,6 @@ public function update(User $user, User $model): bool public function delete(User $user, User $model): bool { - return $user->isAdmin(); + return $user->isAdmin() && $user->id !== $model->id; } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index f1da6b6..ed71e71 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -5,10 +5,9 @@ use App\Helpers\FTP; use App\Helpers\Notifier; use App\Helpers\SSH; -use App\Helpers\Toast; -use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Http\Resources\Json\ResourceCollection; use Illuminate\Support\ServiceProvider; +use Laravel\Fortify\Fortify; class AppServiceProvider extends ServiceProvider { @@ -17,12 +16,9 @@ class AppServiceProvider extends ServiceProvider */ public function register(): void { - // + Fortify::ignoreRoutes(); } - /** - * @throws BindingResolutionException - */ public function boot(): void { ResourceCollection::withoutWrapping(); @@ -34,9 +30,6 @@ public function boot(): void $this->app->bind('notifier', function () { return new Notifier; }); - $this->app->bind('toast', function () { - return new Toast; - }); $this->app->bind('ftp', function () { return new FTP; }); diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php deleted file mode 100644 index 5264c91..0000000 --- a/app/Providers/FortifyServiceProvider.php +++ /dev/null @@ -1,63 +0,0 @@ -input(Fortify::username())).'|'.$request->ip()); - - return Limit::perMinute(5)->by($throttleKey); - }); - - RateLimiter::for('two-factor', function (Request $request) { - return Limit::perMinute(5)->by($request->session()->get('login.id')); - }); - - Fortify::loginView(function () { - return view('auth.login'); - }); - - Fortify::requestPasswordResetLinkView(function () { - return view('auth.forgot-password'); - }); - - Fortify::resetPasswordView(function (Request $request) { - return view('auth.reset-password', [ - 'token' => $request->route('token'), - 'email' => $request->query('email'), - ]); - }); - - Fortify::confirmPasswordView(function () { - return view('auth.confirm-password'); - }); - - Fortify::twoFactorChallengeView(function () { - return view('auth.two-factor-challenge'); - }); - } -} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 9b27b0d..4c26a19 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider * * @var string */ - public const HOME = '/app'; + public const HOME = '/'; /** * Define your route model bindings, pattern filters, and other route configuration. diff --git a/app/Providers/WebServiceProvider.php b/app/Providers/WebServiceProvider.php index 64d7f5a..7581d83 100644 --- a/app/Providers/WebServiceProvider.php +++ b/app/Providers/WebServiceProvider.php @@ -80,7 +80,7 @@ public function panel(Panel $panel): Panel return $panel ->default() ->id('app') - ->path('app') + ->path('') ->passwordReset() ->colors([ 'primary' => Color::Indigo, diff --git a/app/Web/Pages/Settings/Users/Index.php b/app/Web/Pages/Settings/Users/Index.php index 90910b4..bee935e 100644 --- a/app/Web/Pages/Settings/Users/Index.php +++ b/app/Web/Pages/Settings/Users/Index.php @@ -38,7 +38,7 @@ public function getWidgets(): array protected function getHeaderActions(): array { return [ - CreateAction::make() + CreateAction::make('create') ->label('Create User') ->icon('heroicon-o-plus') ->authorize('create', User::class) diff --git a/app/Web/Pages/Settings/Users/Widgets/UsersList.php b/app/Web/Pages/Settings/Users/Widgets/UsersList.php index 1b7f100..59e8758 100644 --- a/app/Web/Pages/Settings/Users/Widgets/UsersList.php +++ b/app/Web/Pages/Settings/Users/Widgets/UsersList.php @@ -87,13 +87,6 @@ public function getTable(): Table ->label('Projects') ->icon('heroicon-o-rectangle-stack') ->authorize(fn ($record) => auth()->user()->can('update', $record)) - ->action(function ($record, array $data) { - app(UpdateProjects::class)->update($record, $data); - Notification::make() - ->title('Projects Updated') - ->success() - ->send(); - }) ->form(function (Form $form, $record) { return $form ->schema([ @@ -105,10 +98,17 @@ public function getTable(): Table ]) ->columns(1); }) + ->action(function ($record, array $data) { + app(UpdateProjects::class)->update($record, $data); + Notification::make() + ->title('Projects Updated') + ->success() + ->send(); + }) ->modalSubmitActionLabel('Save') ->modalWidth(MaxWidth::Large), - DeleteAction::make() - ->authorize(fn ($record) => auth()->user()->can('delete', $record)), + DeleteAction::make('delete') + ->authorize(fn (User $record) => auth()->user()->can('delete', $record)), ]); } } diff --git a/config/app.php b/config/app.php index e99d892..560e364 100644 --- a/config/app.php +++ b/config/app.php @@ -185,7 +185,6 @@ /* * Package Service Providers... */ - App\Providers\FortifyServiceProvider::class, /* * Application Service Providers... diff --git a/config/filament.php b/config/filament.php index 65b4bf0..87dafe1 100644 --- a/config/filament.php +++ b/config/filament.php @@ -2,6 +2,7 @@ return [ + 'path' => '/', /* |-------------------------------------------------------------------------- | Broadcasting diff --git a/config/fortify.php b/config/fortify.php deleted file mode 100644 index e8212db..0000000 --- a/config/fortify.php +++ /dev/null @@ -1,147 +0,0 @@ - 'web', - - /* - |-------------------------------------------------------------------------- - | Fortify Password Broker - |-------------------------------------------------------------------------- - | - | Here you may specify which password broker Fortify can use when a user - | is resetting their password. This configured value should match one - | of your password brokers setup in your "auth" configuration file. - | - */ - - 'passwords' => 'users', - - /* - |-------------------------------------------------------------------------- - | Username / Email - |-------------------------------------------------------------------------- - | - | This value defines which model attribute should be considered as your - | application's "username" field. Typically, this might be the email - | address of the users but you are free to change this value here. - | - | Out of the box, Fortify expects forgot password and reset password - | requests to have a field named 'email'. If the application uses - | another name for the field you may define it below as needed. - | - */ - - 'username' => 'email', - - 'email' => 'email', - - /* - |-------------------------------------------------------------------------- - | Home Path - |-------------------------------------------------------------------------- - | - | Here you may configure the path where users will get redirected during - | authentication or password reset when the operations are successful - | and the user is authenticated. You are free to change this value. - | - */ - - 'home' => RouteServiceProvider::HOME, - - /* - |-------------------------------------------------------------------------- - | Fortify Routes Prefix / Subdomain - |-------------------------------------------------------------------------- - | - | Here you may specify which prefix Fortify will assign to all the routes - | that it registers with the application. If necessary, you may change - | subdomain under which all of the Fortify routes will be available. - | - */ - - 'prefix' => '', - - 'domain' => null, - - /* - |-------------------------------------------------------------------------- - | Fortify Routes Middleware - |-------------------------------------------------------------------------- - | - | Here you may specify which middleware Fortify will assign to the routes - | that it registers with the application. If necessary, you may change - | these middleware but typically this provided default is preferred. - | - */ - - 'middleware' => ['web'], - - /* - |-------------------------------------------------------------------------- - | Rate Limiting - |-------------------------------------------------------------------------- - | - | By default, Fortify will throttle logins to five requests per minute for - | every email and IP address combination. However, if you would like to - | specify a custom rate limiter to call then you may specify it here. - | - */ - - 'limiters' => [ - 'login' => 'login', - 'two-factor' => 'two-factor', - ], - - /* - |-------------------------------------------------------------------------- - | Register View Routes - |-------------------------------------------------------------------------- - | - | Here you may specify if the routes returning views should be disabled as - | you may not need them when building your own application. This may be - | especially true if you're writing a custom single-page application. - | - */ - - 'views' => true, - - /* - |-------------------------------------------------------------------------- - | Features - |-------------------------------------------------------------------------- - | - | Some of the Fortify features are optional. You may disable the features - | by removing them from this array. You're free to only remove some of - | these features or you can even remove all of these if you need to. - | - */ - - 'features' => [ - // Features::registration(), - Features::resetPasswords(), - // Features::emailVerification(), - Features::updateProfileInformation(), - Features::updatePasswords(), - Features::twoFactorAuthentication([ - // 'confirm' => true, - // 'confirmPassword' => true, - // 'window' => 0, - ]), - ], - -]; diff --git a/routes/web.php b/routes/web.php index 3e320ea..1a7c3e0 100644 --- a/routes/web.php +++ b/routes/web.php @@ -3,10 +3,6 @@ use App\Http\Controllers\ConsoleController; use Illuminate\Support\Facades\Route; -Route::get('/', function () { - return redirect()->route('login'); -}); - Route::middleware('auth')->group(function () { Route::post('/{server}/console', [ConsoleController::class, 'run'])->name('servers.console.run'); }); diff --git a/scripts/install.sh b/scripts/install.sh index f900d07..686dff0 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -200,8 +200,9 @@ echo "* * * * * cd /home/${V_USERNAME}/vito && php artisan schedule:run >> /dev/ # cleanup chown -R ${V_USERNAME}:${V_USERNAME} /home/${V_USERNAME} -# cache -php artisan config:cache +# optimize +php artisan optimize +php artisan icons:cache # start worker supervisorctl start worker:* diff --git a/scripts/update.sh b/scripts/update.sh index abb5a06..dbe3e00 100755 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -6,7 +6,7 @@ echo "Pulling changes..." git fetch --all echo "Checking out the latest tag..." -NEW_RELEASE=$(git tag -l "1.*" --sort=-v:refname | head -n 1) +NEW_RELEASE=$(git tag -l "2.*" --sort=-v:refname | head -n 1) git checkout "$NEW_RELEASE" git pull origin "$NEW_RELEASE" diff --git a/tests/Feature/Auth/AuthenticationTest.php b/tests/Feature/Auth/AuthenticationTest.php deleted file mode 100644 index d9b5d09..0000000 --- a/tests/Feature/Auth/AuthenticationTest.php +++ /dev/null @@ -1,47 +0,0 @@ -get('/login'); - - $response->assertStatus(200); - } - - public function test_users_can_authenticate_using_the_login_screen(): void - { - $response = $this->post('/login', [ - 'email' => $this->user->email, - 'password' => 'password', - ]); - - $this->assertAuthenticated(); - $response->assertRedirect(RouteServiceProvider::HOME); - } - - public function test_users_can_not_authenticate_with_invalid_password(): void - { - $this->post('/login', [ - 'email' => $this->user->email, - 'password' => 'wrong-password', - ]); - - $this->assertGuest(); - } - - public function test_redirect_if_not_authenticated(): void - { - $response = $this->get('/servers'); - - $response->assertRedirect('/login'); - } -} diff --git a/tests/Feature/Auth/LogoutTest.php b/tests/Feature/Auth/LogoutTest.php deleted file mode 100644 index ad5871f..0000000 --- a/tests/Feature/Auth/LogoutTest.php +++ /dev/null @@ -1,29 +0,0 @@ -actingAs($this->user); - - $this->post(route('logout'))->assertRedirect('/'); - - $this->assertFalse(auth()->check()); - } - - public function test_user_still_logged_in(): void - { - $this->actingAs($this->user); - - $this->get(route('login'))->assertRedirect(route('servers')); - - $this->assertTrue(auth()->check()); - } -} diff --git a/tests/Feature/Auth/PasswordConfirmationTest.php b/tests/Feature/Auth/PasswordConfirmationTest.php deleted file mode 100644 index e0ed330..0000000 --- a/tests/Feature/Auth/PasswordConfirmationTest.php +++ /dev/null @@ -1,43 +0,0 @@ -actingAs($this->user); - - $response = $this->get(route('password.confirm')); - - $response->assertStatus(200); - } - - public function test_password_can_be_confirmed(): void - { - $this->actingAs($this->user); - - $response = $this->post(route('password.confirm'), [ - 'password' => 'password', - ]); - - $response->assertRedirect(); - $response->assertSessionDoesntHaveErrors(); - } - - public function test_password_is_not_confirmed_with_invalid_password(): void - { - $this->actingAs($this->user); - - $response = $this->post(route('password.confirm'), [ - 'password' => 'wrong-password', - ]); - - $response->assertSessionHasErrors(); - } -} diff --git a/tests/Feature/Auth/PasswordResetTest.php b/tests/Feature/Auth/PasswordResetTest.php deleted file mode 100644 index be3e1f2..0000000 --- a/tests/Feature/Auth/PasswordResetTest.php +++ /dev/null @@ -1,64 +0,0 @@ -get('/forgot-password'); - - $response->assertStatus(200); - } - - public function test_reset_password_link_can_be_requested(): void - { - Notification::fake(); - - $this->post('/forgot-password', ['email' => $this->user->email]); - - Notification::assertSentTo($this->user, ResetPassword::class); - } - - public function test_reset_password_screen_can_be_rendered(): void - { - Notification::fake(); - - $this->post('/forgot-password', ['email' => $this->user->email]); - - Notification::assertSentTo($this->user, ResetPassword::class, function ($notification) { - $response = $this->get('/reset-password/'.$notification->token); - - $response->assertStatus(200); - - return true; - }); - } - - public function test_password_can_be_reset_with_valid_token(): void - { - Notification::fake(); - - $this->post('/forgot-password', ['email' => $this->user->email]); - - Notification::assertSentTo($this->user, ResetPassword::class, function ($notification) { - $response = $this->post('/reset-password', [ - 'token' => $notification->token, - 'email' => $this->user->email, - 'password' => 'password', - 'password_confirmation' => 'password', - ]); - - $response->assertSessionDoesntHaveErrors(); - - return true; - }); - } -} diff --git a/tests/Feature/UserTest.php b/tests/Feature/UserTest.php index 64b9aac..00088d9 100644 --- a/tests/Feature/UserTest.php +++ b/tests/Feature/UserTest.php @@ -5,7 +5,10 @@ use App\Enums\UserRole; use App\Models\Project; use App\Models\User; +use App\Web\Pages\Settings\Users\Index; +use App\Web\Pages\Settings\Users\Widgets\UsersList; use Illuminate\Foundation\Testing\RefreshDatabase; +use Livewire\Livewire; use Tests\TestCase; class UserTest extends TestCase @@ -16,12 +19,13 @@ public function test_create_user(): void { $this->actingAs($this->user); - $this->post(route('settings.users.store'), [ - 'name' => 'new user', - 'email' => 'newuser@example.com', - 'password' => 'password', - 'role' => UserRole::USER, - ])->assertSessionDoesntHaveErrors(); + Livewire::test(Index::class) + ->callAction('create', [ + 'name' => 'new user', + 'email' => 'newuser@example.com', + 'password' => 'password', + 'role' => UserRole::USER, + ]); $this->assertDatabaseHas('users', [ 'name' => 'new user', @@ -36,9 +40,11 @@ public function test_see_users_list(): void $user = User::factory()->create(); - $this->get(route('settings.users.index')) - ->assertSuccessful() - ->assertSee($user->name); + $this->get(Index::getUrl()) + ->assertSuccessful(); + + Livewire::test(UsersList::class) + ->assertCanSeeTableRecords([$user]); } public function test_must_be_admin_to_see_users_list(): void @@ -48,9 +54,7 @@ public function test_must_be_admin_to_see_users_list(): void $this->actingAs($this->user); - $user = User::factory()->create(); - - $this->get(route('settings.users.index')) + $this->get(Index::getUrl()) ->assertForbidden(); } @@ -60,8 +64,8 @@ public function test_delete_user(): void $user = User::factory()->create(); - $this->delete(route('settings.users.delete', $user)) - ->assertSessionDoesntHaveErrors(); + Livewire::test(UsersList::class) + ->callTableAction('delete', $user); $this->assertDatabaseMissing('users', [ 'id' => $user->id, @@ -72,24 +76,8 @@ public function test_cannot_delete_yourself(): void { $this->actingAs($this->user); - $this->delete(route('settings.users.delete', $this->user)) - ->assertSessionDoesntHaveErrors() - ->assertSessionHas('toast.type', 'error'); - - $this->assertDatabaseHas('users', [ - 'id' => $this->user->id, - ]); - } - - public function test_see_user(): void - { - $this->actingAs($this->user); - - $user = User::factory()->create(); - - $this->get(route('settings.users.show', $user)) - ->assertSuccessful() - ->assertSee($user->name); + Livewire::test(UsersList::class) + ->assertTableActionHidden('delete', $this->user); } public function test_edit_user_info(): void @@ -98,13 +86,14 @@ public function test_edit_user_info(): void $user = User::factory()->create(); - $this->post(route('settings.users.update', $user), [ - 'name' => 'new-name', - 'email' => 'newemail@example.com', - 'timezone' => 'Europe/London', - 'role' => UserRole::ADMIN, - ]) - ->assertSessionDoesntHaveErrors(); + Livewire::test(UsersList::class) + ->callTableAction('edit', $user, [ + 'name' => 'new-name', + 'email' => 'newemail@example.com', + 'timezone' => 'Europe/London', + 'role' => UserRole::ADMIN, + ]) + ->assertSuccessful(); $this->assertDatabaseHas('users', [ 'id' => $user->id, @@ -122,10 +111,11 @@ public function test_edit_user_projects(): void $user = User::factory()->create(); $project = Project::factory()->create(); - $this->post(route('settings.users.update-projects', $user), [ - 'projects' => [$project->id], - ]) - ->assertSessionDoesntHaveErrors(); + Livewire::test(UsersList::class) + ->callTableAction('update-projects', $user, [ + 'projects' => [$project->id], + ]) + ->assertSuccessful(); $this->assertDatabaseHas('user_project', [ 'user_id' => $user->id, @@ -137,16 +127,19 @@ public function test_edit_user_projects_with_current_project(): void { $this->actingAs($this->user); + /** @var User $user */ $user = User::factory()->create(); $user->current_project_id = null; $user->save(); + /** @var Project $project */ $project = Project::factory()->create(); - $this->post(route('settings.users.update-projects', $user), [ - 'projects' => [$project->id], - ]) - ->assertSessionDoesntHaveErrors(); + Livewire::test(UsersList::class) + ->callTableAction('update-projects', $user, [ + 'projects' => [$project->id], + ]) + ->assertSuccessful(); $this->assertDatabaseHas('user_project', [ 'user_id' => $user->id,