view($user, $schema); } public function view(User $user, FormSubmission $submission): bool { if ($this->isSubjectSelf($user, $submission)) { return true; } if ($this->isActiveDelegatee($user, $submission)) { return true; } return $this->isOrgStaff($user, $submission->schema?->organisation); } public function create(User $user, FormSchema $schema): bool { return app(FormSchemaPolicy::class)->view($user, $schema); } public function update(User $user, FormSubmission $submission): bool { if ($submission->status !== \App\Enums\FormBuilder\FormSubmissionStatus::DRAFT) { return false; } if ($this->isSubjectSelf($user, $submission)) { return true; } return $this->isActiveDelegatee($user, $submission); } public function submit(User $user, FormSubmission $submission): bool { return $this->update($user, $submission); } public function review(User $user, FormSubmission $submission): bool { return $this->isOrgStaff($user, $submission->schema?->organisation); } public function delegate(User $user, FormSubmission $submission): bool { return $this->isSubjectSelf($user, $submission); } public function revokeDelegation(User $user, FormSubmissionDelegation $delegation): bool { $submission = $delegation->submission; if ($submission === null) { return false; } return $this->isSubjectSelf($user, $submission) || $delegation->delegated_by_user_id === $user->id; } public function delete(User $user, FormSubmission $submission): bool { return $this->isOrgStaff($user, $submission->schema?->organisation, adminOnly: true); } private function isSubjectSelf(User $user, FormSubmission $submission): bool { if ($submission->submitted_by_user_id === $user->id) { return true; } if ($submission->subject_type === 'user' && $submission->subject_id === $user->id) { return true; } if ($submission->subject_type === 'person' && $submission->subject_id !== null) { $userId = \App\Models\Person::withoutGlobalScopes() ->whereKey($submission->subject_id) ->value('user_id'); return $userId === $user->id; } return false; } private function isActiveDelegatee(User $user, FormSubmission $submission): bool { return FormSubmissionDelegation::query() ->where('form_submission_id', $submission->id) ->where('delegated_to_user_id', $user->id) ->whereNull('revoked_at') ->exists(); } private function isOrgStaff(User $user, ?Organisation $organisation, bool $adminOnly = false): bool { if ($user->hasRole('super_admin')) { return true; } if ($organisation === null) { return false; } $query = $organisation->users()->where('user_id', $user->id); if ($adminOnly) { $query->wherePivot('role', 'org_admin'); } return $query->exists() || $user->hasRole('event_manager'); } }