isSubjectSelf($user, $submission)) { return true; } $restrictions = $this->effectiveRestrictions($field); $readRule = $restrictions['read'] ?? true; return $this->matches($user, $readRule); } public function canWrite(?User $user, FormField $field, ?FormSubmission $submission = null): bool { if ($this->isSubjectSelf($user, $submission)) { return true; } $restrictions = $this->effectiveRestrictions($field); $writeRule = $restrictions['write'] ?? ['any_of_roles' => ['org_admin', 'event_manager']]; return $this->matches($user, $writeRule); } /** * @param Collection $fields * @return Collection */ public function filterVisibleFields(?User $user, Collection $fields, ?FormSubmission $submission = null): Collection { return $fields->filter(fn (FormField $f) => $this->canRead($user, $f, $submission))->values(); } /** * @return array */ private function effectiveRestrictions(FormField $field): array { $r = $field->role_restrictions ?? null; if (is_array($r) && $r !== []) { return $r; } if ($field->is_admin_only) { return [ 'read' => ['any_of_roles' => ['org_admin']], 'write' => ['any_of_roles' => ['org_admin']], ]; } return [ 'read' => true, 'write' => ['any_of_roles' => ['org_admin', 'event_manager']], ]; } private function isSubjectSelf(?User $user, ?FormSubmission $submission): bool { if ($user === null || $submission === null) { return false; } 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 === 'user_profile' && $submission->subject_id !== null) { $profile = \App\Models\UserProfile::query()->find($submission->subject_id); if ($profile !== null && $profile->user_id === $user->id) { return true; } } if ($submission->subject_type === 'person' && $submission->subject_id !== null) { $personUserId = \App\Models\Person::withoutGlobalScopes() ->whereKey($submission->subject_id) ->value('user_id'); if ($personUserId !== null && $personUserId === $user->id) { return true; } } return false; } /** * @param mixed $rule */ private function matches(?User $user, $rule): bool { if ($rule === true) { return true; } if ($rule === false) { return false; } if (! is_array($rule)) { return false; } if ($user === null) { return false; } if (isset($rule['subject_self']) && $rule['subject_self'] === true) { return true; } if (isset($rule['any_of_roles']) && is_array($rule['any_of_roles'])) { foreach ($rule['any_of_roles'] as $role) { if ($user->hasRole((string) $role)) { return true; } } return false; } if (isset($rule['all_of_roles']) && is_array($rule['all_of_roles'])) { foreach ($rule['all_of_roles'] as $role) { if (! $user->hasRole((string) $role)) { return false; } } return true; } if (isset($rule['not_roles']) && is_array($rule['not_roles'])) { foreach ($rule['not_roles'] as $role) { if ($user->hasRole((string) $role)) { return false; } } return true; } return false; } }