diff --git a/.env.example b/.env.example index bef8d7d..15f3e42 100644 --- a/.env.example +++ b/.env.example @@ -9,9 +9,9 @@ APP_PORT=8080 SEED_DEV_DATA=false RUN_DB_SEED_ON_FIRST_START=true ENSURE_INITIAL_ADMIN_ON_EMPTY_DB=true -INITIAL_ADMIN_NAME=Administrator -INITIAL_ADMIN_EMAIL=info@termanager.it -INITIAL_ADMIN_PASSWORD=Password123! +INITIAL_ADMIN_NAME= +INITIAL_ADMIN_EMAIL= +INITIAL_ADMIN_PASSWORD= DB_CONNECTION=mysql DB_HOST=mariadb diff --git a/.gitignore b/.gitignore index b062421..ff78a90 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ /node_modules/ /.env /storage/*.key +/storage/app/.app_key +/storage/app/.db_seeded /storage/logs/ /storage/framework/ /bootstrap/cache/ @@ -13,6 +15,7 @@ /.vscode/ *.swp *.swo +*.sql docker-compose.override.yml db_data/ redis_data/ diff --git a/app/Console/Commands/CreateInitialAdmin.php b/app/Console/Commands/CreateInitialAdmin.php index 6f6300c..8949545 100644 --- a/app/Console/Commands/CreateInitialAdmin.php +++ b/app/Console/Commands/CreateInitialAdmin.php @@ -2,8 +2,11 @@ namespace App\Console\Commands; +use Database\Seeders\RolesAndPermissionsSeeder; use App\Models\User; +use Illuminate\Support\Facades\Artisan; use Illuminate\Console\Command; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; @@ -19,10 +22,8 @@ class CreateInitialAdmin extends Command public function handle(): int { - if (User::count() > 0) { - $this->info('Users already exist. Skipping initial admin creation.'); - return self::SUCCESS; - } + // Always ensure roles/permissions are present before assigning roles. + Artisan::call('db:seed', ['--class' => RolesAndPermissionsSeeder::class, '--force' => true]); $name = (string) ($this->option('name') ?? ''); $email = (string) ($this->option('email') ?? ''); @@ -45,6 +46,30 @@ class CreateInitialAdmin extends Command $password = $password !== '' ? $password : (string) $this->secret('Password amministratore (min 8 caratteri)'); } + if (User::count() > 0) { + $existingAdmin = User::role('amministratore')->first(); + if ($existingAdmin) { + $this->info('An administrator already exists. Skipping initial admin creation.'); + return self::SUCCESS; + } + + if ($email !== '') { + $existingUser = User::where('email', $email)->first(); + if ($existingUser) { + $existingUser->assignRole('amministratore'); + $this->info("Granted admin role to existing user: {$existingUser->email}"); + return self::SUCCESS; + } + } + + $firstUser = User::query()->oldest('id')->first(); + if ($firstUser) { + $firstUser->assignRole('amministratore'); + $this->warn("No admin role found. Granted admin role to first existing user: {$firstUser->email}"); + return self::SUCCESS; + } + } + $validator = Validator::make([ 'name' => $name, 'email' => $email, @@ -63,13 +88,17 @@ class CreateInitialAdmin extends Command return self::FAILURE; } - $admin = User::create([ - 'name' => $name, - 'email' => $email, - 'password' => Hash::make($password), - ]); + $admin = DB::transaction(function () use ($name, $email, $password) { + $user = User::create([ + 'name' => $name, + 'email' => $email, + 'password' => Hash::make($password), + ]); - $admin->assignRole('amministratore'); + $user->assignRole('amministratore'); + + return $user; + }); $this->info("Initial admin created: {$admin->email}"); diff --git a/app/Livewire/Settings/UsersIndex.php b/app/Livewire/Settings/UsersIndex.php new file mode 100644 index 0000000..09cb6f9 --- /dev/null +++ b/app/Livewire/Settings/UsersIndex.php @@ -0,0 +1,60 @@ +availablePermissions = Permission::query() + ->orderBy('name') + ->pluck('name') + ->all(); + } + + protected function rules(): array + { + return [ + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'email', 'max:255', Rule::unique('users', 'email')], + 'password' => ['required', 'string', 'min:8', 'confirmed'], + 'selectedPermissions' => ['array'], + 'selectedPermissions.*' => ['string', Rule::in($this->availablePermissions)], + ]; + } + + public function createUser(): void + { + $validated = $this->validate(); + + $user = User::create([ + 'name' => $validated['name'], + 'email' => $validated['email'], + 'password' => $validated['password'], + ]); + + $user->syncPermissions($validated['selectedPermissions'] ?? []); + + $this->reset(['name', 'email', 'password', 'password_confirmation', 'selectedPermissions']); + session()->flash('success', 'Utente creato con successo.'); + } + + public function render() + { + return view('livewire.settings.users-index', [ + 'users' => User::query()->with('roles', 'permissions')->orderBy('name')->get(), + ]); + } +} diff --git a/docker/php/entrypoint.sh b/docker/php/entrypoint.sh index 328b833..7233d42 100755 --- a/docker/php/entrypoint.sh +++ b/docker/php/entrypoint.sh @@ -181,7 +181,7 @@ retry 10 3 php artisan migrate --force # ----------------------------------------------- # 7b. Seed database on first container startup only # ----------------------------------------------- -SEED_MARKER_FILE="/var/www/html/storage/app/.db_seeded" +SEED_MARKER_FILE="/var/www/html/storage/framework/.runtime_db_seeded" RUN_DB_SEED_ON_FIRST_START="${RUN_DB_SEED_ON_FIRST_START:-true}" if [ "$RUN_DB_SEED_ON_FIRST_START" = "true" ]; then diff --git a/resources/views/components/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php index 4c5a634..681daaa 100644 --- a/resources/views/components/layouts/app.blade.php +++ b/resources/views/components/layouts/app.blade.php @@ -114,6 +114,11 @@ Impostazioni + + + Utenti + diff --git a/resources/views/livewire/settings/users-index.blade.php b/resources/views/livewire/settings/users-index.blade.php new file mode 100644 index 0000000..b10c910 --- /dev/null +++ b/resources/views/livewire/settings/users-index.blade.php @@ -0,0 +1,101 @@ +
+
+

Utenti

+

Crea utenti e assegna i permessi applicativi.

+
+ +
+

Nuovo utente

+ +
+
+
+ + + @error('name')

{{ $message }}

@enderror +
+ +
+ + + @error('email')

{{ $message }}

@enderror +
+ +
+ + + @error('password')

{{ $message }}

@enderror +
+ +
+ + +
+
+ +
+

Permessi utente

+
+ @foreach($availablePermissions as $permission) + + @endforeach +
+ @error('selectedPermissions.*')

{{ $message }}

@enderror +
+ +
+ +
+
+
+ +
+

Utenti esistenti

+ +
+ + + + + + + + + + + @forelse($users as $user) + + + + + + + @empty + + + + @endforelse + +
NomeEmailRuoliPermessi diretti
{{ $user->name }}{{ $user->email }} +
+ @forelse($user->roles as $role) + {{ $role->name }} + @empty + - + @endforelse +
+
+
+ @forelse($user->permissions as $permission) + {{ $permission->name }} + @empty + - + @endforelse +
+
Nessun utente trovato
+
+
+
diff --git a/routes/web.php b/routes/web.php index 2c4bc74..21d37c3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -24,6 +24,7 @@ use App\Livewire\AuditLog; use App\Livewire\Settings\SettingsEdit; use App\Livewire\Settings\ZoneIndex; use App\Livewire\Settings\TipologieIndex; +use App\Livewire\Settings\UsersIndex; use App\Livewire\Privacy; /* @@ -101,6 +102,7 @@ Route::middleware('auth')->group(function () { // Settings (admin) Route::middleware('permission:settings.manage')->group(function () { Route::get('impostazioni', SettingsEdit::class)->name('settings.edit'); + Route::get('utenti', UsersIndex::class)->name('users.index'); Route::get('zone', ZoneIndex::class)->name('zone.index'); Route::get('tipologie', TipologieIndex::class)->name('tipologie.index'); });