feat: secure adminer etc ...
Laravel CI-CD / Tests Unitaires (push) Failing after 1m39s Details
Laravel CI-CD / Deploy with Kamal (push) Has been skipped Details

This commit is contained in:
Leon Morival 2026-05-26 14:13:11 +02:00
parent b3968a8181
commit 95dc772873
5 changed files with 76 additions and 15 deletions

View File

@ -82,16 +82,7 @@ class AppServiceProvider extends ServiceProvider
->to($notifiable->getEmailForPasswordReset()) ->to($notifiable->getEmailForPasswordReset())
); );
Gate::define('viewApiDocs', function ($user = null) { Gate::define('viewApiDocs', fn (?User $user): bool => $user?->isAdmin() === true);
// Option A : Autoriser tout le monde (Attention : la doc sera publique hors local)
return true;
/* // Option B : Autoriser seulement certains emails
return in_array($user?->email, [
'admin@tondomaine.com',
], true);
*/
});
Health::checks([ Health::checks([
DatabaseCheck::new(), DatabaseCheck::new(),

View File

@ -13,7 +13,6 @@ use Filament\Panel;
use Filament\PanelProvider; use Filament\PanelProvider;
use Filament\Support\Colors\Color; use Filament\Support\Colors\Color;
use Filament\Widgets\AccountWidget; use Filament\Widgets\AccountWidget;
use Filament\Widgets\FilamentInfoWidget;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies; use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
@ -42,7 +41,8 @@ class DashboardPanelProvider extends PanelProvider
->url(url('/horizon'), shouldOpenInNewTab: true) ->url(url('/horizon'), shouldOpenInNewTab: true)
->icon('heroicon-o-queue-list') ->icon('heroicon-o-queue-list')
->group('Settings') ->group('Settings')
->sort(3), ->sort(3)
->visible(fn (): bool => auth()->user()?->isAdmin() === true),
]) ])
->discoverResources(in: app_path('Filament/Resources'), for: 'App\Filament\Resources') ->discoverResources(in: app_path('Filament/Resources'), for: 'App\Filament\Resources')
->discoverPages(in: app_path('Filament/Pages'), for: 'App\Filament\Pages') ->discoverPages(in: app_path('Filament/Pages'), for: 'App\Filament\Pages')

View File

@ -2,6 +2,7 @@
namespace App\Providers; namespace App\Providers;
use App\Models\User;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
use Laravel\Horizon\Horizon; use Laravel\Horizon\Horizon;
use Laravel\Horizon\HorizonApplicationServiceProvider; use Laravel\Horizon\HorizonApplicationServiceProvider;
@ -27,8 +28,6 @@ class HorizonServiceProvider extends HorizonApplicationServiceProvider
*/ */
protected function gate(): void protected function gate(): void
{ {
Gate::define('viewHorizon', function ($user = null) { Gate::define('viewHorizon', fn (?User $user): bool => $user?->isAdmin() === true);
return true;
});
} }
} }

View File

@ -32,6 +32,10 @@ services:
image: adminer:latest image: adminer:latest
container_name: bemeal-adminer container_name: bemeal-adminer
restart: unless-stopped restart: unless-stopped
profiles:
- debug
ports:
- "127.0.0.1:${ADMINER_PORT:-8080}:8080"
environment: environment:
ADMINER_DEFAULT_SERVER: bemeal-pgsql ADMINER_DEFAULT_SERVER: bemeal-pgsql
networks: networks:

View File

@ -0,0 +1,67 @@
<?php
use App\Enums\UserRole;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Gate;
uses(RefreshDatabase::class);
it('allows only administrators through production tooling gates', function (): void {
$admin = User::factory()->create([
'role' => UserRole::ADMIN,
]);
$moderator = User::factory()->create([
'role' => UserRole::MODERATOR,
]);
$user = User::factory()->create([
'role' => UserRole::USER,
]);
expect(Gate::forUser($admin)->allows('viewHorizon'))->toBeTrue()
->and(Gate::forUser($admin)->allows('viewApiDocs'))->toBeTrue()
->and(Gate::forUser($moderator)->allows('viewHorizon'))->toBeFalse()
->and(Gate::forUser($moderator)->allows('viewApiDocs'))->toBeFalse()
->and(Gate::forUser($user)->allows('viewHorizon'))->toBeFalse()
->and(Gate::forUser($user)->allows('viewApiDocs'))->toBeFalse()
->and(Gate::allows('viewHorizon'))->toBeFalse()
->and(Gate::allows('viewApiDocs'))->toBeFalse();
});
it('protects the horizon dashboard outside local environments', function (): void {
$admin = User::factory()->create([
'role' => UserRole::ADMIN,
]);
$moderator = User::factory()->create([
'role' => UserRole::MODERATOR,
]);
$this->get('/horizon')->assertForbidden();
$this->actingAs($moderator)
->get('/horizon')
->assertForbidden();
$this->actingAs($admin)
->get('/horizon')
->assertSuccessful();
});
it('protects the scramble documentation outside local environments', function (): void {
$admin = User::factory()->create([
'role' => UserRole::ADMIN,
]);
$user = User::factory()->create([
'role' => UserRole::USER,
]);
$this->get('/docs/api')->assertForbidden();
$this->actingAs($user)
->get('/docs/api')
->assertForbidden();
$this->actingAs($admin)
->get('/docs/api')
->assertSuccessful();
});