Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.72% covered (success)
96.72%
59 / 61
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
UseraccountEdit
96.72% covered (success)
96.72%
59 / 61
50.00% covered (danger)
50.00%
2 / 4
16
0.00% covered (danger)
0.00%
0 / 1
 readResponse
97.67% covered (success)
97.67%
42 / 43
0.00% covered (danger)
0.00%
0 / 1
10
 writeUpdatedEntity
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 loadRoleList
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 hasSuperuserOnlyRole
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
1<?php
2
3/**
4 *
5 * @package Zmsadmin
6 * @copyright BerlinOnline Stadtportal GmbH & Co. KG
7 *
8 */
9
10namespace BO\Zmsadmin;
11
12use BO\Slim\Render;
13use BO\Mellon\Validator;
14use BO\Zmsentities\Collection\RoleList;
15use BO\Zmsentities\Exception\UserAccountMissingRights;
16use BO\Zmsentities\Exception\UserAccountAccessRightsFailed;
17use BO\Zmsentities\Schema\Loader;
18use BO\Zmsentities\Useraccount;
19
20class UseraccountEdit extends BaseController
21{
22    private const SUPERUSER_ONLY_ROLES = [
23        'system_admin',
24        'audit_viewer',
25    ];
26
27    /**
28     *
29     * @return \Psr\Http\Message\ResponseInterface
30     */
31    #[\Override]
32    public function readResponse(
33        \Psr\Http\Message\RequestInterface $request,
34        \Psr\Http\Message\ResponseInterface $response,
35        array $args
36    ): \Psr\Http\Message\ResponseInterface {
37        $workstation = \App::$http->readGetResult('/workstation/', ['resolveReferences' => 1])->getEntity();
38        if (! $workstation->getUseraccount()->hasPermissions(['useraccount'])) {
39            throw new UserAccountMissingRights();
40        }
41
42        $userAccountName = Validator::value($args['loginname'])->isString()->getValue();
43        $confirmSuccess = $request->getAttribute('validator')->getParameter('success')->isString()->getValue();
44        $userAccount = \App::$http->readGetResult('/useraccount/' . $userAccountName . '/')->getEntity();
45        if (
46            ! $workstation->getUseraccount()->isSuperUser()
47            && $this->hasSuperuserOnlyRole($userAccount)
48        ) {
49            throw new UserAccountAccessRightsFailed();
50        }
51        $ownerList = \App::$http->readGetResult('/owner/', ['resolveReferences' => 2])->getCollection();
52
53        if ($request->getMethod() === 'POST') {
54            $input = $request->getParsedBody();
55            $result = $this->writeUpdatedEntity($input, $userAccountName);
56            if ($result instanceof Useraccount) {
57                return Render::redirect(
58                    'useraccountEdit',
59                    array('loginname' => $result->id),
60                    array('success' => 'useraccount_saved')
61                );
62            }
63        }
64
65        $config = \App::$http->readGetResult('/config/', [], \App::CONFIG_SECURE_TOKEN)->getEntity();
66        $allowedProviderList = explode(',', $config->getPreference('oidc', 'provider') ?? '');
67
68        $roleList = $this->loadRoleList();
69
70        $userAccountRoles = (isset($userAccount->roles) && is_array($userAccount->roles))
71            ? $userAccount->roles
72            : [];
73
74
75        return Render::withHtml(
76            $response,
77            'page/useraccountEdit.twig',
78            [
79                'debug' => \App::DEBUG,
80                'userAccount' => $userAccount,
81                'success' => $confirmSuccess,
82                'ownerList' => $ownerList ? $ownerList->toDepartmentListByOrganisationName() : [],
83                'workstation' => $workstation,
84                'title' => 'Nutzer: Einrichtung und Administration','menuActive' => 'useraccount',
85                'exception' => (isset($result)) ? $result : null,
86                'metadata' => $this->getSchemaConstraintList(Loader::asArray(Useraccount::$schema)),
87                'oidcProviderList' => array_filter($allowedProviderList),
88                'isFromOidc' => in_array($userAccount->getOidcProviderFromName(), $allowedProviderList),
89                'roleList' => $roleList,
90                'userAccountRoles' => $userAccountRoles,
91            ]
92        );
93    }
94
95    protected function writeUpdatedEntity($input, $userAccountName)
96    {
97        $entity = (new Useraccount($input))->withCleanedUpFormData();
98        // TODO: Remove the password fields when password authentication is removed in the future
99        $entity->setPassword($input);
100        return $this->handleEntityWrite(function () use ($entity, $userAccountName) {
101            return \App::$http
102                ->readPostResult('/useraccount/' . $userAccountName . '/', $entity)
103                ->getEntity();
104        });
105    }
106
107    private function loadRoleList(): RoleList
108    {
109        $roleList = new RoleList();
110
111        $roleResult = \App::$http->readGetResult('/roles/', []);
112        if ($roleResult) {
113            $loaded = $roleResult->getCollection();
114            if ($loaded !== null) {
115                $roleList = $loaded;
116            }
117        }
118
119        return $roleList;
120    }
121
122    protected function hasSuperuserOnlyRole(Useraccount $userAccount): bool
123    {
124        $roles = $userAccount->roles ?? [];
125
126        if (! is_array($roles)) {
127            return false;
128        }
129
130        return (bool) array_intersect($roles, self::SUPERUSER_ONLY_ROLES);
131    }
132}