auth tests
This commit is contained in:
25
backend/database/factories/Lists/UserRoleFactory.php
Normal file
25
backend/database/factories/Lists/UserRoleFactory.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories\Lists;
|
||||
|
||||
use App\Models\Lists\UserRole;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<UserRole>
|
||||
*/
|
||||
class UserRoleFactory extends Factory
|
||||
{
|
||||
protected $model = UserRole::class;
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => ucfirst($this->faker->unique()->word()),
|
||||
'description' => $this->faker->sentence(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropSoftDeletes();
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('user_roles', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->unique();
|
||||
$table->string('description')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('user_roles');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('role_id')->nullable()->after('id');
|
||||
$table->foreign('role_id')->references('id')->on('user_roles')->onDelete('set null');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropForeign(['role_id']);
|
||||
$table->dropColumn('role_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->boolean('must_change_password')->default(true)->after('password');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('must_change_password');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
// Utente di sistema: riceve i contenuti riassegnati e non è eliminabile.
|
||||
$table->boolean('is_system')->default(false)->after('role_id');
|
||||
|
||||
// Traccia l'avvenuta anonimizzazione (GDPR). Il record resta ai fini
|
||||
// di integrità referenziale ma esce dal cestino e dalle liste utenti.
|
||||
$table->timestamp('anonymized_at')->nullable()->after('deleted_at');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn(['is_system', 'anonymized_at']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->text('two_factor_secret')
|
||||
->after('password')
|
||||
->nullable();
|
||||
|
||||
$table->text('two_factor_recovery_codes')
|
||||
->after('two_factor_secret')
|
||||
->nullable();
|
||||
|
||||
$table->timestamp('two_factor_confirmed_at')
|
||||
->after('two_factor_recovery_codes')
|
||||
->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'two_factor_secret',
|
||||
'two_factor_recovery_codes',
|
||||
'two_factor_confirmed_at',
|
||||
]);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$connection = config('audit.drivers.database.connection', config('database.default'));
|
||||
$table = config('audit.drivers.database.table', 'audits');
|
||||
|
||||
Schema::connection($connection)->create($table, function (Blueprint $table) {
|
||||
|
||||
$morphPrefix = config('audit.user.morph_prefix', 'user');
|
||||
|
||||
$table->bigIncrements('id');
|
||||
$table->string($morphPrefix.'_type')->nullable();
|
||||
$table->unsignedBigInteger($morphPrefix.'_id')->nullable();
|
||||
$table->string('event');
|
||||
$table->morphs('auditable');
|
||||
$table->text('old_values')->nullable();
|
||||
$table->text('new_values')->nullable();
|
||||
$table->text('url')->nullable();
|
||||
$table->ipAddress('ip_address')->nullable();
|
||||
$table->string('user_agent', 1023)->nullable();
|
||||
$table->string('tags')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->index([$morphPrefix.'_id', $morphPrefix.'_type']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
$connection = config('audit.drivers.database.connection', config('database.default'));
|
||||
$table = config('audit.drivers.database.table', 'audits');
|
||||
|
||||
Schema::connection($connection)->drop($table);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->timestamp('two_factor_setup_completed_at')
|
||||
->nullable()
|
||||
->after('two_factor_confirmed_at');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('two_factor_setup_completed_at');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
@@ -11,15 +10,14 @@ class DatabaseSeeder extends Seeder
|
||||
use WithoutModelEvents;
|
||||
|
||||
/**
|
||||
* Seed the application's database.
|
||||
* Seed dell'applicazione. L'ordine conta: i ruoli prima dell'utente di
|
||||
* sistema (che richiede il ruolo Admin).
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// User::factory(10)->create();
|
||||
|
||||
User::factory()->create([
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
$this->call([
|
||||
UserRoleSeeder::class,
|
||||
SystemUserSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
41
backend/database/seeders/SystemUserSeeder.php
Normal file
41
backend/database/seeders/SystemUserSeeder.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Lists\UserRole;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Crea l'utente di sistema: riceve i contenuti riassegnati dagli utenti
|
||||
* cancellati (flusso GDPR / oblio) e non è eliminabile né accessibile
|
||||
* (password casuale, nessun login previsto). Idempotente.
|
||||
*
|
||||
* Dipende da UserRoleSeeder (serve il ruolo Admin).
|
||||
*/
|
||||
class SystemUserSeeder extends Seeder
|
||||
{
|
||||
public const EMAIL = 'system@dyncoll.local';
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$adminRoleId = UserRole::where('name', UserRole::ADMIN)->value('id');
|
||||
|
||||
User::updateOrCreate(
|
||||
['email' => self::EMAIL],
|
||||
[
|
||||
'name' => 'Dyncoll System',
|
||||
'password' => Hash::make(Str::random(60)),
|
||||
'role_id' => $adminRoleId,
|
||||
'is_system' => true,
|
||||
'must_change_password' => false,
|
||||
'email_verified_at' => now(),
|
||||
'two_factor_setup_completed_at' => now(),
|
||||
]
|
||||
);
|
||||
|
||||
$this->command?->info('✅ System user ready: '.self::EMAIL);
|
||||
}
|
||||
}
|
||||
42
backend/database/seeders/UserRoleSeeder.php
Normal file
42
backend/database/seeders/UserRoleSeeder.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Lists\UserRole;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class UserRoleSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Ruoli applicativi di base. Idempotente.
|
||||
* (description in inglese: lingua ufficiale dell'applicazione.)
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
UserRole::updateOrCreate(
|
||||
['name' => UserRole::ADMIN],
|
||||
['description' => 'Full access to all features.'
|
||||
.' Manages users, configurations and global data supervision.'
|
||||
.' Can create, read, update and delete any record.']
|
||||
);
|
||||
|
||||
UserRole::updateOrCreate(
|
||||
['name' => UserRole::SUPERVISOR],
|
||||
['description' => 'Limited access to certain features.'
|
||||
.' Can manage users but not administrators.'
|
||||
.' Can create, read, update and delete both own and other users\' records.']
|
||||
);
|
||||
|
||||
UserRole::updateOrCreate(
|
||||
['name' => UserRole::USER],
|
||||
['description' => 'Day-to-day operational use. Can access all records'
|
||||
.' and create new ones, but can only update or delete their own.']
|
||||
);
|
||||
|
||||
UserRole::updateOrCreate(
|
||||
['name' => UserRole::GUEST],
|
||||
['description' => 'Very limited access. Can only view information'
|
||||
.' not publicly available, with no editing capabilities.']
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user