1a25f0a04SGreg Roach<?php 23976b470SGreg Roach 3a25f0a04SGreg Roach/** 4a25f0a04SGreg Roach * webtrees: online genealogy 5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team 6a25f0a04SGreg Roach * This program is free software: you can redistribute it and/or modify 7a25f0a04SGreg Roach * it under the terms of the GNU General Public License as published by 8a25f0a04SGreg Roach * the Free Software Foundation, either version 3 of the License, or 9a25f0a04SGreg Roach * (at your option) any later version. 10a25f0a04SGreg Roach * This program is distributed in the hope that it will be useful, 11a25f0a04SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 12a25f0a04SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13a25f0a04SGreg Roach * GNU General Public License for more details. 14a25f0a04SGreg Roach * You should have received a copy of the GNU General Public License 1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 16a25f0a04SGreg Roach */ 17fcfa147eSGreg Roach 18e7f56f2aSGreg Roachdeclare(strict_types=1); 19e7f56f2aSGreg Roach 2076692c8bSGreg Roachnamespace Fisharebest\Webtrees; 21a25f0a04SGreg Roach 22e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface; 2381b729d3SGreg Roachuse Fisharebest\Webtrees\Http\Exceptions\HttpAccessDeniedException; 2481b729d3SGreg Roachuse Fisharebest\Webtrees\Http\Exceptions\HttpNotFoundException; 259867b2f0SGreg Roachuse Fisharebest\Webtrees\Module\ModuleInterface; 26e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Services\UserService; 2779529c87SGreg Roach 28d8809d62SGreg Roachuse function is_int; 29d8809d62SGreg Roach 30a25f0a04SGreg Roach/** 3176692c8bSGreg Roach * Authentication. 32a25f0a04SGreg Roach */ 33c1010edaSGreg Roachclass Auth 34c1010edaSGreg Roach{ 354b9ff166SGreg Roach // Privacy constants 3616d6367aSGreg Roach public const PRIV_PRIVATE = 2; // Allows visitors to view the item 3716d6367aSGreg Roach public const PRIV_USER = 1; // Allows members to access the item 3816d6367aSGreg Roach public const PRIV_NONE = 0; // Allows managers to access the item 3916d6367aSGreg Roach public const PRIV_HIDE = -1; // Hide the item to all users 404b9ff166SGreg Roach 41a25f0a04SGreg Roach /** 42a25f0a04SGreg Roach * Are we currently logged in? 43a25f0a04SGreg Roach * 44cbc1590aSGreg Roach * @return bool 45a25f0a04SGreg Roach */ 468f53f488SRico Sonntag public static function check(): bool 47c1010edaSGreg Roach { 484b9ff166SGreg Roach return self::id() !== null; 49a25f0a04SGreg Roach } 50a25f0a04SGreg Roach 51a25f0a04SGreg Roach /** 52a25f0a04SGreg Roach * Is the specified/current user an administrator? 53a25f0a04SGreg Roach * 54e5a6b4d4SGreg Roach * @param UserInterface|null $user 55a25f0a04SGreg Roach * 56cbc1590aSGreg Roach * @return bool 57a25f0a04SGreg Roach */ 582c6f1bd5SGreg Roach public static function isAdmin(UserInterface|null $user = null): bool 59c1010edaSGreg Roach { 603529c469SGreg Roach $user ??= self::user(); 61a25f0a04SGreg Roach 621fe542e9SGreg Roach return $user->getPreference(UserInterface::PREF_IS_ADMINISTRATOR) === '1'; 63a25f0a04SGreg Roach } 64a25f0a04SGreg Roach 65a25f0a04SGreg Roach /** 664b9ff166SGreg Roach * Is the specified/current user a manager of a tree? 67a25f0a04SGreg Roach * 6884caa210SGreg Roach * @param Tree $tree 69e5a6b4d4SGreg Roach * @param UserInterface|null $user 70a25f0a04SGreg Roach * 71cbc1590aSGreg Roach * @return bool 72a25f0a04SGreg Roach */ 732c6f1bd5SGreg Roach public static function isManager(Tree $tree, UserInterface|null $user = null): bool 74c1010edaSGreg Roach { 753529c469SGreg Roach $user ??= self::user(); 76a25f0a04SGreg Roach 771fe542e9SGreg Roach return self::isAdmin($user) || $tree->getUserPreference($user, UserInterface::PREF_TREE_ROLE) === UserInterface::ROLE_MANAGER; 78a25f0a04SGreg Roach } 79a25f0a04SGreg Roach 80a25f0a04SGreg Roach /** 814b9ff166SGreg Roach * Is the specified/current user a moderator of a tree? 82a25f0a04SGreg Roach * 8384caa210SGreg Roach * @param Tree $tree 84e5a6b4d4SGreg Roach * @param UserInterface|null $user 85a25f0a04SGreg Roach * 86cbc1590aSGreg Roach * @return bool 87a25f0a04SGreg Roach */ 882c6f1bd5SGreg Roach public static function isModerator(Tree $tree, UserInterface|null $user = null): bool 89c1010edaSGreg Roach { 903529c469SGreg Roach $user ??= self::user(); 91a25f0a04SGreg Roach 921fe542e9SGreg Roach return 931fe542e9SGreg Roach self::isManager($tree, $user) || 941fe542e9SGreg Roach $tree->getUserPreference($user, UserInterface::PREF_TREE_ROLE) === UserInterface::ROLE_MODERATOR; 95a25f0a04SGreg Roach } 96a25f0a04SGreg Roach 97a25f0a04SGreg Roach /** 984b9ff166SGreg Roach * Is the specified/current user an editor of a tree? 99a25f0a04SGreg Roach * 10084caa210SGreg Roach * @param Tree $tree 101e5a6b4d4SGreg Roach * @param UserInterface|null $user 102a25f0a04SGreg Roach * 103cbc1590aSGreg Roach * @return bool 104a25f0a04SGreg Roach */ 1052c6f1bd5SGreg Roach public static function isEditor(Tree $tree, UserInterface|null $user = null): bool 106c1010edaSGreg Roach { 1073529c469SGreg Roach $user ??= self::user(); 108a25f0a04SGreg Roach 1091fe542e9SGreg Roach return 1101fe542e9SGreg Roach self::isModerator($tree, $user) || 1111fe542e9SGreg Roach $tree->getUserPreference($user, UserInterface::PREF_TREE_ROLE) === UserInterface::ROLE_EDITOR; 112a25f0a04SGreg Roach } 113a25f0a04SGreg Roach 114a25f0a04SGreg Roach /** 1154b9ff166SGreg Roach * Is the specified/current user a member of a tree? 116a25f0a04SGreg Roach * 11784caa210SGreg Roach * @param Tree $tree 118e5a6b4d4SGreg Roach * @param UserInterface|null $user 119a25f0a04SGreg Roach * 120cbc1590aSGreg Roach * @return bool 121a25f0a04SGreg Roach */ 1222c6f1bd5SGreg Roach public static function isMember(Tree $tree, UserInterface|null $user = null): bool 123c1010edaSGreg Roach { 1243529c469SGreg Roach $user ??= self::user(); 125a25f0a04SGreg Roach 1261fe542e9SGreg Roach return 1271fe542e9SGreg Roach self::isEditor($tree, $user) || 1281fe542e9SGreg Roach $tree->getUserPreference($user, UserInterface::PREF_TREE_ROLE) === UserInterface::ROLE_MEMBER; 129a25f0a04SGreg Roach } 130a25f0a04SGreg Roach 131a25f0a04SGreg Roach /** 1324b9ff166SGreg Roach * What is the specified/current user's access level within a tree? 1334b9ff166SGreg Roach * 1344b9ff166SGreg Roach * @param Tree $tree 135e5a6b4d4SGreg Roach * @param UserInterface|null $user 1364b9ff166SGreg Roach * 137cbc1590aSGreg Roach * @return int 1384b9ff166SGreg Roach */ 1392c6f1bd5SGreg Roach public static function accessLevel(Tree $tree, UserInterface|null $user = null): int 140c1010edaSGreg Roach { 1413529c469SGreg Roach $user ??= self::user(); 1424b9ff166SGreg Roach 1434b9ff166SGreg Roach if (self::isManager($tree, $user)) { 1444b9ff166SGreg Roach return self::PRIV_NONE; 1454b9ff166SGreg Roach } 146b2ce94c6SRico Sonntag 147b2ce94c6SRico Sonntag if (self::isMember($tree, $user)) { 148b2ce94c6SRico Sonntag return self::PRIV_USER; 149b2ce94c6SRico Sonntag } 150b2ce94c6SRico Sonntag 151b2ce94c6SRico Sonntag return self::PRIV_PRIVATE; 1524b9ff166SGreg Roach } 1534b9ff166SGreg Roach 1544b9ff166SGreg Roach /** 155a25f0a04SGreg Roach * The ID of the authenticated user, from the current session. 156a25f0a04SGreg Roach */ 157*1ff45046SGreg Roach public static function id(): int|null 158c1010edaSGreg Roach { 159d8809d62SGreg Roach $wt_user = Session::get('wt_user'); 160d8809d62SGreg Roach 161d8809d62SGreg Roach return is_int($wt_user) ? $wt_user : null; 162a25f0a04SGreg Roach } 163a25f0a04SGreg Roach 164a25f0a04SGreg Roach /** 165a25f0a04SGreg Roach * The authenticated user, from the current session. 166a25f0a04SGreg Roach * 167e5a6b4d4SGreg Roach * @return UserInterface 168a25f0a04SGreg Roach */ 169e5a6b4d4SGreg Roach public static function user(): UserInterface 170c1010edaSGreg Roach { 171d35568b4SGreg Roach $user_service = Registry::container()->get(UserService::class); 172b55cbc6bSGreg Roach 173b55cbc6bSGreg Roach return $user_service->find(self::id()) ?? new GuestUser(); 174a25f0a04SGreg Roach } 175a25f0a04SGreg Roach 176a25f0a04SGreg Roach /** 177a25f0a04SGreg Roach * Login directly as an explicit user - for masquerading. 178a25f0a04SGreg Roach * 179e5a6b4d4SGreg Roach * @param UserInterface $user 180cb923727SGreg Roach * 181cb923727SGreg Roach * @return void 182a25f0a04SGreg Roach */ 183e364afe4SGreg Roach public static function login(UserInterface $user): void 184c1010edaSGreg Roach { 18581b729d3SGreg Roach Session::regenerate(); 186895230eeSGreg Roach Session::put('wt_user', $user->id()); 187a25f0a04SGreg Roach } 188a25f0a04SGreg Roach 189a25f0a04SGreg Roach /** 190a25f0a04SGreg Roach * End the session for the current user. 191cb923727SGreg Roach * 192cb923727SGreg Roach * @return void 193a25f0a04SGreg Roach */ 194e364afe4SGreg Roach public static function logout(): void 195c1010edaSGreg Roach { 19631bc7874SGreg Roach Session::regenerate(true); 197a25f0a04SGreg Roach } 198e539f5c6SGreg Roach 199e539f5c6SGreg Roach /** 200ac19d600SGreg Roach * @template T of ModuleInterface 201ac19d600SGreg Roach * 2029867b2f0SGreg Roach * @param ModuleInterface $module 203ac19d600SGreg Roach * @param class-string<T> $interface 2049867b2f0SGreg Roach * @param Tree $tree 205e5a6b4d4SGreg Roach * @param UserInterface $user 2069867b2f0SGreg Roach * 2079867b2f0SGreg Roach * @return void 2089867b2f0SGreg Roach */ 209ef483801SGreg Roach public static function checkComponentAccess(ModuleInterface $module, string $interface, Tree $tree, UserInterface $user): void 2109867b2f0SGreg Roach { 211ef483801SGreg Roach if ($module->accessLevel($tree, $interface) < self::accessLevel($tree, $user)) { 212d501c45dSGreg Roach throw new HttpAccessDeniedException(); 2139867b2f0SGreg Roach } 2149867b2f0SGreg Roach } 2159867b2f0SGreg Roach 2169867b2f0SGreg Roach /** 217e539f5c6SGreg Roach * @param Family|null $family 218ffc0a61fSGreg Roach * @param bool $edit 219e539f5c6SGreg Roach * 220ddeb3354SGreg Roach * @return Family 22181b729d3SGreg Roach * @throws HttpNotFoundException 22281b729d3SGreg Roach * @throws HttpAccessDeniedException 223e539f5c6SGreg Roach */ 224*1ff45046SGreg Roach public static function checkFamilyAccess(Family|null $family, bool $edit = false): Family 225e539f5c6SGreg Roach { 22681b729d3SGreg Roach $message = I18N::translate('This family does not exist or you do not have permission to view it.'); 22781b729d3SGreg Roach 228e539f5c6SGreg Roach if ($family === null) { 22981b729d3SGreg Roach throw new HttpNotFoundException($message); 230e539f5c6SGreg Roach } 231e539f5c6SGreg Roach 2323c3fd0a5SGreg Roach if ($edit && $family->canEdit()) { 2338091bfd1SGreg Roach $family->lock(); 2348091bfd1SGreg Roach 235ddeb3354SGreg Roach return $family; 236e539f5c6SGreg Roach } 237e539f5c6SGreg Roach 2383c3fd0a5SGreg Roach if ($family->canShow()) { 2393c3fd0a5SGreg Roach return $family; 2403c3fd0a5SGreg Roach } 2413c3fd0a5SGreg Roach 24281b729d3SGreg Roach throw new HttpAccessDeniedException($message); 2433c3fd0a5SGreg Roach } 2443c3fd0a5SGreg Roach 245e539f5c6SGreg Roach /** 2461635452cSGreg Roach * @param Header|null $header 2471635452cSGreg Roach * @param bool $edit 2481635452cSGreg Roach * 2491635452cSGreg Roach * @return Header 25081b729d3SGreg Roach * @throws HttpNotFoundException 25181b729d3SGreg Roach * @throws HttpAccessDeniedException 2521635452cSGreg Roach */ 253*1ff45046SGreg Roach public static function checkHeaderAccess(Header|null $header, bool $edit = false): Header 2541635452cSGreg Roach { 25581b729d3SGreg Roach $message = I18N::translate('This record does not exist or you do not have permission to view it.'); 25681b729d3SGreg Roach 2571635452cSGreg Roach if ($header === null) { 25881b729d3SGreg Roach throw new HttpNotFoundException($message); 2591635452cSGreg Roach } 2601635452cSGreg Roach 2611635452cSGreg Roach if ($edit && $header->canEdit()) { 2628091bfd1SGreg Roach $header->lock(); 2638091bfd1SGreg Roach 2641635452cSGreg Roach return $header; 2651635452cSGreg Roach } 2661635452cSGreg Roach 2671635452cSGreg Roach if ($header->canShow()) { 2681635452cSGreg Roach return $header; 2691635452cSGreg Roach } 2701635452cSGreg Roach 27181b729d3SGreg Roach throw new HttpAccessDeniedException($message); 2721635452cSGreg Roach } 2731635452cSGreg Roach 2741635452cSGreg Roach /** 275e539f5c6SGreg Roach * @param Individual|null $individual 276ffc0a61fSGreg Roach * @param bool $edit 2773c3fd0a5SGreg Roach * @param bool $chart For some charts, we can show private records 278e539f5c6SGreg Roach * 279ddeb3354SGreg Roach * @return Individual 28081b729d3SGreg Roach * @throws HttpNotFoundException 28181b729d3SGreg Roach * @throws HttpAccessDeniedException 282e539f5c6SGreg Roach */ 283*1ff45046SGreg Roach public static function checkIndividualAccess(Individual|null $individual, bool $edit = false, bool $chart = false): Individual 284e539f5c6SGreg Roach { 28581b729d3SGreg Roach $message = I18N::translate('This individual does not exist or you do not have permission to view it.'); 28681b729d3SGreg Roach 287e539f5c6SGreg Roach if ($individual === null) { 28881b729d3SGreg Roach throw new HttpNotFoundException($message); 289e539f5c6SGreg Roach } 290e539f5c6SGreg Roach 2913c3fd0a5SGreg Roach if ($edit && $individual->canEdit()) { 2928091bfd1SGreg Roach $individual->lock(); 2938091bfd1SGreg Roach 294ddeb3354SGreg Roach return $individual; 295e539f5c6SGreg Roach } 296e539f5c6SGreg Roach 2973c3fd0a5SGreg Roach if ($chart && $individual->tree()->getPreference('SHOW_PRIVATE_RELATIONSHIPS') === '1') { 2983c3fd0a5SGreg Roach return $individual; 2993c3fd0a5SGreg Roach } 3003c3fd0a5SGreg Roach 3013c3fd0a5SGreg Roach if ($individual->canShow()) { 3023c3fd0a5SGreg Roach return $individual; 3033c3fd0a5SGreg Roach } 3043c3fd0a5SGreg Roach 30581b729d3SGreg Roach throw new HttpAccessDeniedException($message); 3063c3fd0a5SGreg Roach } 3073c3fd0a5SGreg Roach 308e539f5c6SGreg Roach /** 309e8ded2caSGreg Roach * @param Location|null $location 310e8ded2caSGreg Roach * @param bool $edit 311e8ded2caSGreg Roach * 312e8ded2caSGreg Roach * @return Location 31381b729d3SGreg Roach * @throws HttpNotFoundException 31481b729d3SGreg Roach * @throws HttpAccessDeniedException 315e8ded2caSGreg Roach */ 316*1ff45046SGreg Roach public static function checkLocationAccess(Location|null $location, bool $edit = false): Location 317e8ded2caSGreg Roach { 31881b729d3SGreg Roach $message = I18N::translate('This record does not exist or you do not have permission to view it.'); 31981b729d3SGreg Roach 320e8ded2caSGreg Roach if ($location === null) { 32181b729d3SGreg Roach throw new HttpNotFoundException($message); 322e8ded2caSGreg Roach } 323e8ded2caSGreg Roach 324e8ded2caSGreg Roach if ($edit && $location->canEdit()) { 325e8ded2caSGreg Roach $location->lock(); 326e8ded2caSGreg Roach 327e8ded2caSGreg Roach return $location; 328e8ded2caSGreg Roach } 329e8ded2caSGreg Roach 330e8ded2caSGreg Roach if ($location->canShow()) { 331e8ded2caSGreg Roach return $location; 332e8ded2caSGreg Roach } 333e8ded2caSGreg Roach 33481b729d3SGreg Roach throw new HttpAccessDeniedException($message); 335e8ded2caSGreg Roach } 336e8ded2caSGreg Roach 337e8ded2caSGreg Roach /** 338e539f5c6SGreg Roach * @param Media|null $media 339ffc0a61fSGreg Roach * @param bool $edit 340e539f5c6SGreg Roach * 341ddeb3354SGreg Roach * @return Media 34281b729d3SGreg Roach * @throws HttpNotFoundException 34381b729d3SGreg Roach * @throws HttpAccessDeniedException 344e539f5c6SGreg Roach */ 345*1ff45046SGreg Roach public static function checkMediaAccess(Media|null $media, bool $edit = false): Media 346e539f5c6SGreg Roach { 34781b729d3SGreg Roach $message = I18N::translate('This media object does not exist or you do not have permission to view it.'); 34881b729d3SGreg Roach 349e539f5c6SGreg Roach if ($media === null) { 35081b729d3SGreg Roach throw new HttpNotFoundException($message); 351e539f5c6SGreg Roach } 352e539f5c6SGreg Roach 3533c3fd0a5SGreg Roach if ($edit && $media->canEdit()) { 3548091bfd1SGreg Roach $media->lock(); 3558091bfd1SGreg Roach 356ddeb3354SGreg Roach return $media; 357e539f5c6SGreg Roach } 358e539f5c6SGreg Roach 3593c3fd0a5SGreg Roach if ($media->canShow()) { 3603c3fd0a5SGreg Roach return $media; 3613c3fd0a5SGreg Roach } 3623c3fd0a5SGreg Roach 36381b729d3SGreg Roach throw new HttpAccessDeniedException($message); 3643c3fd0a5SGreg Roach } 3653c3fd0a5SGreg Roach 366e539f5c6SGreg Roach /** 367e539f5c6SGreg Roach * @param Note|null $note 368ffc0a61fSGreg Roach * @param bool $edit 369e539f5c6SGreg Roach * 370ddeb3354SGreg Roach * @return Note 37181b729d3SGreg Roach * @throws HttpNotFoundException 37281b729d3SGreg Roach * @throws HttpAccessDeniedException 373e539f5c6SGreg Roach */ 374*1ff45046SGreg Roach public static function checkNoteAccess(Note|null $note, bool $edit = false): Note 375e539f5c6SGreg Roach { 37681b729d3SGreg Roach $message = I18N::translate('This note does not exist or you do not have permission to view it.'); 37781b729d3SGreg Roach 378e539f5c6SGreg Roach if ($note === null) { 37981b729d3SGreg Roach throw new HttpNotFoundException($message); 380e539f5c6SGreg Roach } 381e539f5c6SGreg Roach 3823c3fd0a5SGreg Roach if ($edit && $note->canEdit()) { 3838091bfd1SGreg Roach $note->lock(); 3848091bfd1SGreg Roach 385ddeb3354SGreg Roach return $note; 386e539f5c6SGreg Roach } 387e539f5c6SGreg Roach 3883c3fd0a5SGreg Roach if ($note->canShow()) { 3893c3fd0a5SGreg Roach return $note; 3903c3fd0a5SGreg Roach } 3913c3fd0a5SGreg Roach 39281b729d3SGreg Roach throw new HttpAccessDeniedException($message); 3933c3fd0a5SGreg Roach } 3943c3fd0a5SGreg Roach 395e539f5c6SGreg Roach /** 396701f5d18SGreg Roach * @param SharedNote|null $shared_note 397701f5d18SGreg Roach * @param bool $edit 398701f5d18SGreg Roach * 399701f5d18SGreg Roach * @return SharedNote 400701f5d18SGreg Roach * @throws HttpNotFoundException 401701f5d18SGreg Roach * @throws HttpAccessDeniedException 402701f5d18SGreg Roach */ 403*1ff45046SGreg Roach public static function checkSharedNoteAccess(SharedNote|null $shared_note, bool $edit = false): SharedNote 404701f5d18SGreg Roach { 405701f5d18SGreg Roach $message = I18N::translate('This note does not exist or you do not have permission to view it.'); 406701f5d18SGreg Roach 407701f5d18SGreg Roach if ($shared_note === null) { 408701f5d18SGreg Roach throw new HttpNotFoundException($message); 409701f5d18SGreg Roach } 410701f5d18SGreg Roach 411701f5d18SGreg Roach if ($edit && $shared_note->canEdit()) { 412701f5d18SGreg Roach $shared_note->lock(); 413701f5d18SGreg Roach 414701f5d18SGreg Roach return $shared_note; 415701f5d18SGreg Roach } 416701f5d18SGreg Roach 417701f5d18SGreg Roach if ($shared_note->canShow()) { 418701f5d18SGreg Roach return $shared_note; 419701f5d18SGreg Roach } 420701f5d18SGreg Roach 421701f5d18SGreg Roach throw new HttpAccessDeniedException($message); 422701f5d18SGreg Roach } 423701f5d18SGreg Roach 424701f5d18SGreg Roach /** 425e539f5c6SGreg Roach * @param GedcomRecord|null $record 426ffc0a61fSGreg Roach * @param bool $edit 427e539f5c6SGreg Roach * 428ddeb3354SGreg Roach * @return GedcomRecord 42981b729d3SGreg Roach * @throws HttpNotFoundException 43081b729d3SGreg Roach * @throws HttpAccessDeniedException 431e539f5c6SGreg Roach */ 432*1ff45046SGreg Roach public static function checkRecordAccess(GedcomRecord|null $record, bool $edit = false): GedcomRecord 433e539f5c6SGreg Roach { 43481b729d3SGreg Roach $message = I18N::translate('This record does not exist or you do not have permission to view it.'); 43581b729d3SGreg Roach 436e539f5c6SGreg Roach if ($record === null) { 43781b729d3SGreg Roach throw new HttpNotFoundException($message); 438e539f5c6SGreg Roach } 439e539f5c6SGreg Roach 4403c3fd0a5SGreg Roach if ($edit && $record->canEdit()) { 4418091bfd1SGreg Roach $record->lock(); 4428091bfd1SGreg Roach 443ddeb3354SGreg Roach return $record; 444e539f5c6SGreg Roach } 445e539f5c6SGreg Roach 4463c3fd0a5SGreg Roach if ($record->canShow()) { 4473c3fd0a5SGreg Roach return $record; 4483c3fd0a5SGreg Roach } 4493c3fd0a5SGreg Roach 45081b729d3SGreg Roach throw new HttpAccessDeniedException($message); 4513c3fd0a5SGreg Roach } 4523c3fd0a5SGreg Roach 453e539f5c6SGreg Roach /** 454e539f5c6SGreg Roach * @param Repository|null $repository 455ffc0a61fSGreg Roach * @param bool $edit 456e539f5c6SGreg Roach * 457ddeb3354SGreg Roach * @return Repository 45881b729d3SGreg Roach * @throws HttpNotFoundException 45981b729d3SGreg Roach * @throws HttpAccessDeniedException 460e539f5c6SGreg Roach */ 461*1ff45046SGreg Roach public static function checkRepositoryAccess(Repository|null $repository, bool $edit = false): Repository 462e539f5c6SGreg Roach { 46381b729d3SGreg Roach $message = I18N::translate('This repository does not exist or you do not have permission to view it.'); 46481b729d3SGreg Roach 465e539f5c6SGreg Roach if ($repository === null) { 46681b729d3SGreg Roach throw new HttpNotFoundException($message); 467e539f5c6SGreg Roach } 468e539f5c6SGreg Roach 4693c3fd0a5SGreg Roach if ($edit && $repository->canEdit()) { 4708091bfd1SGreg Roach $repository->lock(); 4718091bfd1SGreg Roach 472ddeb3354SGreg Roach return $repository; 473e539f5c6SGreg Roach } 474e539f5c6SGreg Roach 4753c3fd0a5SGreg Roach if ($repository->canShow()) { 4763c3fd0a5SGreg Roach return $repository; 4773c3fd0a5SGreg Roach } 4783c3fd0a5SGreg Roach 47981b729d3SGreg Roach throw new HttpAccessDeniedException($message); 4803c3fd0a5SGreg Roach } 4813c3fd0a5SGreg Roach 482e539f5c6SGreg Roach /** 483e539f5c6SGreg Roach * @param Source|null $source 484ffc0a61fSGreg Roach * @param bool $edit 485e539f5c6SGreg Roach * 486ddeb3354SGreg Roach * @return Source 48781b729d3SGreg Roach * @throws HttpNotFoundException 48881b729d3SGreg Roach * @throws HttpAccessDeniedException 489e539f5c6SGreg Roach */ 490*1ff45046SGreg Roach public static function checkSourceAccess(Source|null $source, bool $edit = false): Source 491e539f5c6SGreg Roach { 49281b729d3SGreg Roach $message = I18N::translate('This source does not exist or you do not have permission to view it.'); 49381b729d3SGreg Roach 494e539f5c6SGreg Roach if ($source === null) { 49581b729d3SGreg Roach throw new HttpNotFoundException($message); 496e539f5c6SGreg Roach } 497e539f5c6SGreg Roach 4983c3fd0a5SGreg Roach if ($edit && $source->canEdit()) { 4998091bfd1SGreg Roach $source->lock(); 5008091bfd1SGreg Roach 501ddeb3354SGreg Roach return $source; 502e539f5c6SGreg Roach } 503ffc0a61fSGreg Roach 5043c3fd0a5SGreg Roach if ($source->canShow()) { 5053c3fd0a5SGreg Roach return $source; 5063c3fd0a5SGreg Roach } 5073c3fd0a5SGreg Roach 50881b729d3SGreg Roach throw new HttpAccessDeniedException($message); 5093c3fd0a5SGreg Roach } 5103c3fd0a5SGreg Roach 511b1089081SGreg Roach /** 512ffc0a61fSGreg Roach * @param Submitter|null $submitter 513ffc0a61fSGreg Roach * @param bool $edit 514ffc0a61fSGreg Roach * 515ffc0a61fSGreg Roach * @return Submitter 516b1089081SGreg Roach * @throws HttpNotFoundException 517b1089081SGreg Roach * @throws HttpAccessDeniedException 518ffc0a61fSGreg Roach */ 519*1ff45046SGreg Roach public static function checkSubmitterAccess(Submitter|null $submitter, bool $edit = false): Submitter 520ffc0a61fSGreg Roach { 52181b729d3SGreg Roach $message = I18N::translate('This record does not exist or you do not have permission to view it.'); 52281b729d3SGreg Roach 523ffc0a61fSGreg Roach if ($submitter === null) { 52481b729d3SGreg Roach throw new HttpNotFoundException($message); 525ffc0a61fSGreg Roach } 526ffc0a61fSGreg Roach 5273c3fd0a5SGreg Roach if ($edit && $submitter->canEdit()) { 5288091bfd1SGreg Roach $submitter->lock(); 5298091bfd1SGreg Roach 530ffc0a61fSGreg Roach return $submitter; 531ffc0a61fSGreg Roach } 5323c3fd0a5SGreg Roach 5333c3fd0a5SGreg Roach if ($submitter->canShow()) { 5343c3fd0a5SGreg Roach return $submitter; 5353c3fd0a5SGreg Roach } 5363c3fd0a5SGreg Roach 53781b729d3SGreg Roach throw new HttpAccessDeniedException($message); 5383c3fd0a5SGreg Roach } 5391635452cSGreg Roach 540b1089081SGreg Roach /** 5411635452cSGreg Roach * @param Submission|null $submission 5421635452cSGreg Roach * @param bool $edit 5431635452cSGreg Roach * 5441635452cSGreg Roach * @return Submission 54581b729d3SGreg Roach * @throws HttpNotFoundException 54681b729d3SGreg Roach * @throws HttpAccessDeniedException 5471635452cSGreg Roach */ 548*1ff45046SGreg Roach public static function checkSubmissionAccess(Submission|null $submission, bool $edit = false): Submission 5491635452cSGreg Roach { 55081b729d3SGreg Roach $message = I18N::translate('This record does not exist or you do not have permission to view it.'); 55181b729d3SGreg Roach 5521635452cSGreg Roach if ($submission === null) { 55381b729d3SGreg Roach throw new HttpNotFoundException($message); 5541635452cSGreg Roach } 5551635452cSGreg Roach 5561635452cSGreg Roach if ($edit && $submission->canEdit()) { 5578091bfd1SGreg Roach $submission->lock(); 5588091bfd1SGreg Roach 5591635452cSGreg Roach return $submission; 5601635452cSGreg Roach } 5611635452cSGreg Roach 5621635452cSGreg Roach if ($submission->canShow()) { 5631635452cSGreg Roach return $submission; 5641635452cSGreg Roach } 5651635452cSGreg Roach 56681b729d3SGreg Roach throw new HttpAccessDeniedException($message); 5671635452cSGreg Roach } 568870365fbSGreg Roach 569870365fbSGreg Roach /** 5705416d6ddSGreg Roach * @param Tree $tree 5715416d6ddSGreg Roach * @param UserInterface $user 5725416d6ddSGreg Roach * 5735416d6ddSGreg Roach * @return bool 5745416d6ddSGreg Roach */ 5755416d6ddSGreg Roach public static function canUploadMedia(Tree $tree, UserInterface $user): bool 5765416d6ddSGreg Roach { 5775416d6ddSGreg Roach return 578be410956SGreg Roach self::isEditor($tree, $user) && 579be410956SGreg Roach self::accessLevel($tree, $user) <= (int) $tree->getPreference('MEDIA_UPLOAD'); 5805416d6ddSGreg Roach } 5815416d6ddSGreg Roach 5825416d6ddSGreg Roach /** 583870365fbSGreg Roach * @return array<int,string> 584870365fbSGreg Roach */ 585870365fbSGreg Roach public static function accessLevelNames(): array 586870365fbSGreg Roach { 587870365fbSGreg Roach return [ 588d823340dSGreg Roach self::PRIV_PRIVATE => I18N::translate('Show to visitors'), 589d823340dSGreg Roach self::PRIV_USER => I18N::translate('Show to members'), 590d823340dSGreg Roach self::PRIV_NONE => I18N::translate('Show to managers'), 591d823340dSGreg Roach self::PRIV_HIDE => I18N::translate('Hide from everyone'), 592870365fbSGreg Roach ]; 593870365fbSGreg Roach } 594138139c2SGreg Roach 595138139c2SGreg Roach /** 596138139c2SGreg Roach * @return array<string,string> 597138139c2SGreg Roach */ 598138139c2SGreg Roach public static function privacyRuleNames(): array 599138139c2SGreg Roach { 600138139c2SGreg Roach return [ 601138139c2SGreg Roach 'none' => I18N::translate('Show to visitors'), 602138139c2SGreg Roach 'privacy' => I18N::translate('Show to members'), 603138139c2SGreg Roach 'confidential' => I18N::translate('Show to managers'), 604138139c2SGreg Roach 'hidden' => I18N::translate('Hide from everyone'), 605138139c2SGreg Roach ]; 606138139c2SGreg Roach } 607a25f0a04SGreg Roach} 608