diff --git a/app/Http/Controllers/ResumeController.php b/app/Http/Controllers/ResumeController.php new file mode 100644 index 0000000..8f237c1 --- /dev/null +++ b/app/Http/Controllers/ResumeController.php @@ -0,0 +1,66 @@ +user()->can('create', Resume::class); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array|string> + */ + public function rules(): array + { + return UpdateResumeRequest::rules(); + } +} diff --git a/app/Http/Requests/UpdateResumeRequest.php b/app/Http/Requests/UpdateResumeRequest.php new file mode 100644 index 0000000..01beae3 --- /dev/null +++ b/app/Http/Requests/UpdateResumeRequest.php @@ -0,0 +1,31 @@ +user()->can('update', $this->resume); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array|string> + */ + public function rules(): array + { + return [ + 'name' => 'required|string|max:255', + 'creator_id' => 'required|exists:users,id', + ]; + } +} diff --git a/app/Models/Resume.php b/app/Models/Resume.php new file mode 100644 index 0000000..d5c8a1b --- /dev/null +++ b/app/Models/Resume.php @@ -0,0 +1,25 @@ + */ + use HasFactory; + + protected $fillable = [ + 'name', + 'creator_id' + ]; + + public function creator(): BelongsTo + { + return $this->belongsTo(User::class, 'creator_id'); + } +} diff --git a/app/Policies/ResumePolicy.php b/app/Policies/ResumePolicy.php new file mode 100644 index 0000000..9870293 --- /dev/null +++ b/app/Policies/ResumePolicy.php @@ -0,0 +1,57 @@ +id === $resume->creator_id + ? Response::allow() + : Response::deny('You do not own this resume.'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, Resume $resume): Response + { + return $this->isCreator($user, $resume); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return true; + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, Resume $resume): Response + { + return $this->isCreator($user, $resume); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Resume $resume): Response + { + return $this->isCreator($user, $resume); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Resume $resume): Response + { + return $this->isCreator($user, $resume); + } +} diff --git a/database/factories/ResumeFactory.php b/database/factories/ResumeFactory.php new file mode 100644 index 0000000..ed87c5c --- /dev/null +++ b/database/factories/ResumeFactory.php @@ -0,0 +1,25 @@ + + */ +class ResumeFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => "CV " . $this->faker->company(), + 'creator_id' => User::inRandomOrder()->first()->id, + ]; + } +} diff --git a/database/migrations/2025_08_15_161427_create_resumes_table.php b/database/migrations/2025_08_15_161427_create_resumes_table.php new file mode 100644 index 0000000..b8eba4d --- /dev/null +++ b/database/migrations/2025_08_15_161427_create_resumes_table.php @@ -0,0 +1,32 @@ +id(); + + $table->string('name', 255); + $table->foreignIdFor(User::class, "creator_id")->constrained()->onDelete('cascade'); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('resumes'); + } +}; diff --git a/database/seeders/ResumeSeeder.php b/database/seeders/ResumeSeeder.php new file mode 100644 index 0000000..be3d63a --- /dev/null +++ b/database/seeders/ResumeSeeder.php @@ -0,0 +1,19 @@ +count(10) + ->create(); + } +} diff --git a/routes/web.php b/routes/web.php index fddbaba..746baa8 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,5 +1,6 @@ middleware(['auth', 'verified'])->name('dashboard'); +Route::resource('resumes', ResumeController::class); + require __DIR__.'/settings.php'; require __DIR__.'/auth.php';