Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
58.21% |
39 / 67 |
|
81.82% |
9 / 11 |
CRAP | |
0.00% |
0 / 1 |
| Access | |
58.21% |
39 / 67 |
|
81.82% |
9 / 11 |
118.37 | |
0.00% |
0 / 1 |
| initAccessRights | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
4 | |||
| readWorkstation | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| readDepartment | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
| readOrganisation | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
| readOwner | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
| validateAccessRights | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| validateAccess | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
7 | |||
| validateScope | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
4.59 | |||
| isPathWithoutScope | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
4 | |||
| testLogin | |
0.00% |
0 / 27 |
|
0.00% |
0 / 1 |
42 | |||
| exceptionTemplateExists | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * |
| 5 | * @package zmsstatistic |
| 6 | * @copyright BerlinOnline Stadtportal GmbH & Co. KG |
| 7 | * |
| 8 | */ |
| 9 | |
| 10 | namespace BO\Zmsstatistic\Helper; |
| 11 | |
| 12 | use BO\Zmsclient\Auth; |
| 13 | use BO\Zmsentities\Exception\UserAccountAccessRightsFailed; |
| 14 | use BO\Zmsentities\Exception\WorkstationMissingScope; |
| 15 | use BO\Zmsentities\Useraccount; |
| 16 | use BO\Zmsentities\Workstation; |
| 17 | use Psr\Http\Message\RequestInterface; |
| 18 | |
| 19 | class Access extends \BO\Slim\Controller |
| 20 | { |
| 21 | protected mixed $workstation = null; |
| 22 | |
| 23 | protected mixed $organisation = null; |
| 24 | |
| 25 | protected mixed $department = null; |
| 26 | |
| 27 | protected int $resolveLevel = 2; |
| 28 | |
| 29 | protected bool $withAccess = true; |
| 30 | |
| 31 | protected mixed $owner = null; |
| 32 | |
| 33 | protected function initAccessRights(RequestInterface $request): void |
| 34 | { |
| 35 | $this->workstation = $this->readWorkstation(); |
| 36 | if ($this->workstation && isset($this->workstation->scope['id']) && $this->workstation->scope['id'] > 0) { |
| 37 | $this->department = $this->readDepartment(); |
| 38 | $this->organisation = $this->readOrganisation(); |
| 39 | $this->owner = $this->readOwner(); |
| 40 | } |
| 41 | $this->validateAccessRights($request); |
| 42 | } |
| 43 | |
| 44 | protected function readWorkstation(): mixed |
| 45 | { |
| 46 | $workstation = \App::http()->readGetResult('/workstation/', ['resolveReferences' => $this->resolveLevel]); |
| 47 | return $workstation->getEntity(); |
| 48 | } |
| 49 | |
| 50 | protected function readDepartment(): mixed |
| 51 | { |
| 52 | if ($this->workstation->getUseraccount()->hasPermissions(['statistic'])) { |
| 53 | return \App::http() |
| 54 | ->readGetResult('/scope/' . $this->workstation->scope['id'] . '/department/') |
| 55 | ->getEntity(); |
| 56 | } |
| 57 | return null; |
| 58 | } |
| 59 | |
| 60 | protected function readOrganisation(): mixed |
| 61 | { |
| 62 | if ($this->workstation->getUseraccount()->isSuperUser()) { |
| 63 | return \App::http() |
| 64 | ->readGetResult('/department/' . $this->department->getId() . '/organisation/') |
| 65 | ->getEntity(); |
| 66 | } |
| 67 | return null; |
| 68 | } |
| 69 | |
| 70 | protected function readOwner(): mixed |
| 71 | { |
| 72 | if ($this->workstation->getUseraccount()->isSuperUser()) { |
| 73 | return \App::http() |
| 74 | ->readGetResult('/organisation/' . $this->organisation->getId() . '/owner/') |
| 75 | ->getEntity(); |
| 76 | } |
| 77 | return null; |
| 78 | } |
| 79 | |
| 80 | protected function validateAccessRights(RequestInterface $request): void |
| 81 | { |
| 82 | $path = $request->getUri()->getPath(); |
| 83 | $this->validateAccess($path); |
| 84 | $this->validateScope($path); |
| 85 | } |
| 86 | |
| 87 | protected function validateAccess(string $path): void |
| 88 | { |
| 89 | if ( |
| 90 | (false !== strpos($path, 'owner') && ! $this->owner) || |
| 91 | (false !== strpos($path, 'organisation') && ! $this->organisation) || |
| 92 | (false !== strpos($path, 'department') && ! $this->department) |
| 93 | ) { |
| 94 | throw new UserAccountAccessRightsFailed(); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | protected function validateScope(string $path): void |
| 99 | { |
| 100 | if ( |
| 101 | $this->isPathWithoutScope($path) |
| 102 | && (! isset($this->workstation['scope']) || ! isset($this->workstation['scope']['id'])) |
| 103 | ) { |
| 104 | throw new WorkstationMissingScope(); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | protected function isPathWithoutScope(string $path): bool |
| 109 | { |
| 110 | // TODO: refactor to integrate these access rules in the controller to make them visible |
| 111 | return (false === strpos($path, 'select') |
| 112 | && false === strpos($path, 'warehouse') |
| 113 | && false === strpos($path, 'logout') |
| 114 | && false === strpos($path, 'report') |
| 115 | ); |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | * @return mixed |
| 120 | */ |
| 121 | protected function testLogin(mixed $input): mixed |
| 122 | { |
| 123 | $userAccount = new Useraccount(array( |
| 124 | 'id' => $input['loginName'], |
| 125 | 'password' => $input['password'], |
| 126 | 'departments' => array('id' => 0) // required in schema validation |
| 127 | )); |
| 128 | try { |
| 129 | /** @var Workstation $workstation */ |
| 130 | $workstation = \App::http()->readPostResult('/workstation/login/', $userAccount)->getEntity(); |
| 131 | return $workstation; |
| 132 | } catch (\BO\Zmsclient\Exception $exception) { |
| 133 | $template = TwigExceptionHandler::getExceptionTemplate($exception); |
| 134 | if ('BO\Zmsentities\Exception\SchemaValidation' == $exception->template) { |
| 135 | $exceptionData = [ |
| 136 | 'template' => 'exception/bo/zmsbackend/useraccount/exception/invalidcredentials.twig' |
| 137 | ]; |
| 138 | $exceptionData['data']['password']['messages'] = [ |
| 139 | 'Der Nutzername oder das Passwort wurden falsch eingegeben' |
| 140 | ]; |
| 141 | } elseif ('BO\Zmsbackend\Useraccount\Exception\UserAlreadyLoggedIn' == $exception->template) { |
| 142 | Auth::setKey($exception->data['authkey'], time() + \App::SESSION_DURATION); |
| 143 | throw $exception; |
| 144 | } elseif ( |
| 145 | '' != $exception->template |
| 146 | && $this->exceptionTemplateExists($template) |
| 147 | ) { |
| 148 | $exceptionData = [ |
| 149 | 'template' => $template, |
| 150 | 'data' => $exception->data |
| 151 | ]; |
| 152 | } else { |
| 153 | throw $exception; |
| 154 | } |
| 155 | } |
| 156 | return $exceptionData; |
| 157 | } |
| 158 | |
| 159 | protected function exceptionTemplateExists(string $template): bool |
| 160 | { |
| 161 | /** @var mixed $container */ |
| 162 | $container = \App::$slim->getContainer(); |
| 163 | return $container->get('view')->getLoader()->exists($template); |
| 164 | } |
| 165 | } |