JFIFxxC      C  " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr{ gilour
<?php namespace Common\Core\Policies; use App\Models\User; use Arr; use Common\Files\FileEntry; use Common\Files\FileEntryUser; use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Support\Collection; use Laravel\Sanctum\PersonalAccessToken; class FileEntryPolicy extends BasePolicy { public function index( ?User $user, array $entryIds = null, int $userId = null, ): bool { if ($entryIds) { return $this->userCan($user, 'files.view', $entryIds); } else { return $user->hasPermission('files.view') || $userId === $user->id; } } public function show(?User $user, FileEntry $entry): bool { $token = $this->getAccessTokenFromRequest(); if ($token) { if ($entry->preview_token === $token) { return true; } elseif ( $accessToken = app(PersonalAccessToken::class)->findToken( $token, ) ) { $user = $accessToken->tokenable; } } return $user && $this->userCan($user, 'files.view', $entry); } public function download(User $user, $entries): bool { $token = $this->getAccessTokenFromRequest(); if ($token) { $previewTokenMatches = collect($entries)->every(function ( $entry, ) use ($token) { return $entry['preview_token'] === $token; }); if ($previewTokenMatches) { return true; } elseif ( $accessToken = app(PersonalAccessToken::class)->findToken( $token, ) ) { $user = $accessToken->tokenable; } } return $this->userCan($user, 'files.download', $entries); } public function store(User $user, int $parentId = null): bool { //check if user can modify parent entry (if specified) if ($parentId) { return $this->userCan($user, 'files.update', [$parentId]); } return $user->hasPermission('files.create'); } public function update(User $user, Collection|array|FileEntry $entries) { return $this->userCan($user, 'files.update', $entries); } /** * @param User $user * @param Collection|array|FileEntry $entries * @return bool */ public function destroy(User $user, $entries) { return $this->userCan($user, 'files.delete', $entries); } /** * @param User $currentUser * @param string $permission * @param FileEntry|array|Collection $entries * @return bool */ protected function userCan(User $currentUser, string $permission, $entries) { if ($currentUser->hasPermission($permission)) { return true; } $entries = $this->findEntries($entries); // extending class might use "findEntries" method so we load users here if (!$entries->every->relationLoaded('users')) { $entries->load([ 'users' => function (MorphToMany $builder) use ($currentUser) { $builder->where('users.id', $currentUser->id); }, ]); } return $entries->every(function (FileEntry $entry) use ( $permission, $currentUser, ) { $user = $entry->users->find($currentUser->id); return $this->userOwnsEntryOrWasGrantedPermission( $user, $permission, ); }); } /** * @param null|array|FileEntryUser $user * @param string $permission * @return bool */ public function userOwnsEntryOrWasGrantedPermission( $user, string $permission, ) { return $user && ($user['owns_entry'] || Arr::get( $user['entry_permissions'], $this->sharedFilePermission($permission), )); } protected function findEntries( FileEntry|array|Collection $entries, ): Collection { if ($entries instanceof FileEntry) { return $entries->newCollection([$entries]); } elseif (isset($entries[0]) && is_numeric($entries[0])) { return app(FileEntry::class) ->whereIn('id', $entries) ->get(); } else { return $entries; } } protected function sharedFilePermission($fullPermission): string { switch ($fullPermission) { case 'files.view': return 'view'; case 'files.create': case 'files.update': return 'edit'; case 'files.delete': return 'delete'; case 'files.download': return 'download'; } } protected function getAccessTokenFromRequest(): ?string { if ($token = request()->bearerToken()) { return $token; } elseif ($token = request()->get('preview_token')) { return $token; } elseif ($token = request()->get('accessToken')) { return $token; } else { return null; } } }