diff --git a/Makefile b/Makefile index 7825cef..c9d9b82 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ up: docker-up down: docker-down +reload: docker-down docker-up init: docker-down-clear docker-pull docker-build docker-up app-init app-db-seed docker-up: @@ -19,8 +20,6 @@ docker-build: app-init: docker compose run --rm php composer install - docker compose run --rm php chown root:www-data -R storage/ - docker compose run --rm php chmod 777 -R storage/ docker compose run --rm php cp .env.example .env docker compose run --rm php php artisan key:generate diff --git a/src/app/Http/Controllers/DashboardController.php b/src/app/Http/Controllers/DashboardController.php new file mode 100644 index 0000000..746087e --- /dev/null +++ b/src/app/Http/Controllers/DashboardController.php @@ -0,0 +1,10 @@ +hasMany(User::class); + } +} diff --git a/src/app/Models/User.php b/src/app/Models/User.php index 16416d5..12b4bff 100644 --- a/src/app/Models/User.php +++ b/src/app/Models/User.php @@ -5,7 +5,10 @@ declare(strict_types=1); namespace App\Models; // use Illuminate\Contracts\Auth\MustVerifyEmail; + +use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; @@ -14,6 +17,7 @@ class User extends Authenticatable /** @use HasFactory<\Database\Factories\UserFactory> */ use HasFactory; use Notifiable; + use HasUuids; /** * The attributes that are mass assignable. @@ -24,6 +28,7 @@ class User extends Authenticatable 'name', 'email', 'password', + 'role_uuid', ]; /** @@ -48,4 +53,16 @@ class User extends Authenticatable 'password' => 'hashed', ]; } + + /** + * The primary key for the model. + * + * @var string + */ + protected $primaryKey = 'uuid'; + + public function role(): BelongsTo + { + return $this->belongsTo(Role::class, 'role_uuid', 'uuid'); + } } diff --git a/src/database/factories/RoleFactory.php b/src/database/factories/RoleFactory.php new file mode 100644 index 0000000..b825646 --- /dev/null +++ b/src/database/factories/RoleFactory.php @@ -0,0 +1,23 @@ + + */ +class RoleFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + // + ]; + } +} diff --git a/src/database/migrations/2026_02_04_051435_create_roles_table.php b/src/database/migrations/2026_02_04_051435_create_roles_table.php new file mode 100644 index 0000000..21c7030 --- /dev/null +++ b/src/database/migrations/2026_02_04_051435_create_roles_table.php @@ -0,0 +1,30 @@ +uuid()->primary(); + $table->string('name')->unique(); + $table->string('code')->unique(); + $table->string('description'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('roles'); + } +}; diff --git a/src/database/migrations/0001_01_01_000000_create_users_table.php b/src/database/migrations/2026_02_04_051523_create_users_table.php similarity index 55% rename from src/database/migrations/0001_01_01_000000_create_users_table.php rename to src/database/migrations/2026_02_04_051523_create_users_table.php index 05fb5d9..78d30a3 100644 --- a/src/database/migrations/0001_01_01_000000_create_users_table.php +++ b/src/database/migrations/2026_02_04_051523_create_users_table.php @@ -12,28 +12,19 @@ return new class extends Migration public function up(): void { Schema::create('users', function (Blueprint $table) { - $table->id(); + $table->uuid()->primary(); + $table->uuid('role_uuid'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); - }); - Schema::create('password_reset_tokens', function (Blueprint $table) { - $table->string('email')->primary(); - $table->string('token'); - $table->timestamp('created_at')->nullable(); - }); - - Schema::create('sessions', function (Blueprint $table) { - $table->string('id')->primary(); - $table->foreignId('user_id')->nullable()->index(); - $table->string('ip_address', 45)->nullable(); - $table->text('user_agent')->nullable(); - $table->longText('payload'); - $table->integer('last_activity')->index(); + $table->foreign('role_uuid') + ->references('uuid') + ->on('roles') + ->onDelete('restrict'); }); } diff --git a/src/database/seeders/DatabaseSeeder.php b/src/database/seeders/DatabaseSeeder.php index 6b901f8..5d2382f 100644 --- a/src/database/seeders/DatabaseSeeder.php +++ b/src/database/seeders/DatabaseSeeder.php @@ -2,6 +2,7 @@ namespace Database\Seeders; +use App\Models\Role; use App\Models\User; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; @@ -15,11 +16,9 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // User::factory(10)->create(); - - User::factory()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', + $this->call([ + RoleSeeder::class, + UserSeeder::class, ]); } } diff --git a/src/database/seeders/RoleSeeder.php b/src/database/seeders/RoleSeeder.php new file mode 100644 index 0000000..d4b7c57 --- /dev/null +++ b/src/database/seeders/RoleSeeder.php @@ -0,0 +1,35 @@ + [ + 'name' => 'Admin', + 'code' => 'admin', + 'description' => 'Admin role', + ], + 'user' => [ + 'name' => 'User', + 'code' => 'user', + 'description' => 'User role', + ], + ]; + + DB::transaction(static function() use ($roles) { + $codes = collect($roles)->pluck('code'); + Role::whereNotIn('code', $codes)->delete(); + Role::upsert($roles, ['code'], ['name','description']); + }); + } +} diff --git a/src/database/seeders/UserSeeder.php b/src/database/seeders/UserSeeder.php new file mode 100644 index 0000000..267b07d --- /dev/null +++ b/src/database/seeders/UserSeeder.php @@ -0,0 +1,31 @@ +first(); + + if (!$defaultUser) { + User::factory()->create([ + 'name' => 'Admin', + 'role_uuid' => Role::where('code', 'admin')->first()->uuid, + 'email' => 'admin@example.com', + 'password' => bcrypt('qwaszxedc'), + ]); + } + } +}