--- title: Policies --- # Policies Authorization policies for ArtisanPack UI Forms. ## Overview The package includes two authorization policies: - **FormPolicy** - Controls access to forms - **SubmissionPolicy** - Controls access to submissions ## FormPolicy Controls who can view, create, update, and delete forms. ### Policy Methods | Method | Description | |--------|-------------| | `viewAny` | Can list all forms | | `view` | Can view a specific form | | `create` | Can create new forms | | `update` | Can update a form | | `delete` | Can delete a form | | `restore` | Can restore soft-deleted forms | | `forceDelete` | Can permanently delete forms | ### Default Behavior By default, the package uses permissive authorization: ```php // config/artisanpack/forms.php 'authorization' => [ 'restrict_by_owner' => false, // Anyone can access any form 'allow_admin_bypass' => true, 'user_model' => 'App\\Models\\User', ], ``` **Security Warning**: With `restrict_by_owner = false`, any authenticated user can access all forms. Enable ownership enforcement for multi-user applications. ### Ownership Enforcement Enable ownership-based access: ```php // config/artisanpack/forms.php 'authorization' => [ 'restrict_by_owner' => true, ], ``` With this enabled: ```php // Users can only access their own forms $user->can('view', $form); // true if $form->user_id === $user->id // Admins bypass ownership checks $admin->can('view', $form); // true if $admin->is_admin ``` ### Admin Bypass Users with `is_admin` attribute can bypass ownership: ```php // config/artisanpack/forms.php 'authorization' => [ 'allow_admin_bypass' => true, ], ``` Ensure your User model has the `is_admin` attribute: ```php // User model protected $casts = [ 'is_admin' => 'boolean', ]; ``` ### Custom Policy Override the default policy: ```php // app/Policies/CustomFormPolicy.php namespace App\Policies; use App\Models\User; use ArtisanPackUI\Forms\Models\Form; use ArtisanPackUI\Forms\Policies\FormPolicy; class CustomFormPolicy extends FormPolicy { public function update(User $user, Form $form): bool { // Add custom logic if ($user->hasRole('editor')) { return true; } return parent::update($user, $form); } public function delete(User $user, Form $form): bool { // Only allow deletion for admins return $user->is_admin; } } ``` Register the custom policy: ```php // app/Providers/AuthServiceProvider.php use ArtisanPackUI\Forms\Models\Form; use App\Policies\CustomFormPolicy; protected $policies = [ Form::class => CustomFormPolicy::class, ]; ``` --- ## SubmissionPolicy Controls access to form submissions. ### Policy Methods | Method | Description | |--------|-------------| | `viewAny` | Can list submissions | | `view` | Can view a specific submission | | `delete` | Can delete a submission | | `export` | Can export submissions | | `downloadUpload` | Can download uploaded files | ### Default Behavior Submission access follows form access: ```php // If user can view the form, they can view its submissions $user->can('view', $submission); // Checks form access ``` ### Custom Policy ```php // app/Policies/CustomSubmissionPolicy.php namespace App\Policies; use App\Models\User; use ArtisanPackUI\Forms\Models\FormSubmission; use ArtisanPackUI\Forms\Policies\SubmissionPolicy; class CustomSubmissionPolicy extends SubmissionPolicy { public function view(User $user, FormSubmission $submission): bool { // Custom access rules if ($submission->form->is_public) { return true; } return parent::view($user, $submission); } public function export(User $user, FormSubmission $submission): bool { // Only managers can export return $user->hasRole('manager') || $user->is_admin; } } ``` --- ## Using Policies ### In Controllers ```php public function show(Form $form) { $this->authorize('view', $form); return view('forms.show', compact('form')); } public function destroy(FormSubmission $submission) { $this->authorize('delete', $submission); $submission->delete(); return redirect()->back()->with('success', 'Submission deleted.'); } ``` ### In Blade Templates ```blade @can('update', $form) Edit @endcan @can('delete', $submission) @endcan ``` ### In Livewire Components ```php public function deleteSubmission(int $id): void { $submission = FormSubmission::findOrFail($id); $this->authorize('delete', $submission); $submission->delete(); } ``` ### Using Gates ```php use Illuminate\Support\Facades\Gate; if (Gate::allows('update', $form)) { // User can update the form } if (Gate::denies('delete', $submission)) { abort(403, 'You cannot delete this submission.'); } ``` --- ## Configuration Reference ```php // config/artisanpack/forms.php 'authorization' => [ // Enable ownership-based access control // When true: users can only access their own forms // When false: any authenticated user can access any form 'restrict_by_owner' => env('FORMS_RESTRICT_BY_OWNER', false), // Allow users with is_admin=true to bypass ownership checks 'allow_admin_bypass' => env('FORMS_ALLOW_ADMIN_BYPASS', true), // User model class for ownership relationships 'user_model' => env('FORMS_USER_MODEL', 'App\\Models\\User'), ], ``` ## Testing Policies ```php use ArtisanPackUI\Forms\Models\Form; use App\Models\User; test('owner can update their form', function () { $user = User::factory()->create(); $form = Form::factory()->create(['user_id' => $user->id]); config(['artisanpack.forms.authorization.restrict_by_owner' => true]); $this->assertTrue($user->can('update', $form)); }); test('non-owner cannot update others form', function () { $owner = User::factory()->create(); $other = User::factory()->create(); $form = Form::factory()->create(['user_id' => $owner->id]); config(['artisanpack.forms.authorization.restrict_by_owner' => true]); $this->assertFalse($other->can('update', $form)); }); test('admin can update any form', function () { $admin = User::factory()->create(['is_admin' => true]); $form = Form::factory()->create(); config(['artisanpack.forms.authorization.restrict_by_owner' => true]); config(['artisanpack.forms.authorization.allow_admin_bypass' => true]); $this->assertTrue($admin->can('update', $form)); }); ``` ## Next Steps - [Configuration](../installation/configuration.md) - Authorization settings - [Models](./models.md) - Model documentation - [Services](./services.md) - Service documentation