Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.07% covered (success)
91.07%
51 / 56
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
UpdateUserEndpoint
91.07% covered (success)
91.07%
51 / 56
0.00% covered (danger)
0.00%
0 / 1
17.21
0.00% covered (danger)
0.00%
0 / 1
 handle
91.07% covered (success)
91.07%
51 / 56
0.00% covered (danger)
0.00%
0 / 1
17.21
1<?php
2
3namespace Olz\Users\Endpoints;
4
5use Olz\Api\OlzUpdateEntityTypedEndpoint;
6use Olz\Entity\Users\User;
7use PhpTypeScriptApi\HttpError;
8
9/**
10 * @phpstan-import-type OlzUserId from UserEndpointTrait
11 * @phpstan-import-type OlzUserData from UserEndpointTrait
12 *
13 * @extends OlzUpdateEntityTypedEndpoint<OlzUserId, OlzUserData, never, array{
14 *   status: 'OK'|'OK_NO_EMAIL_VERIFICATION'|'DENIED'|'ERROR',
15 * }>
16 */
17class UpdateUserEndpoint extends OlzUpdateEntityTypedEndpoint {
18    use UserEndpointTrait;
19
20    protected function handle(mixed $input): mixed {
21        $user_repo = $this->entityManager()->getRepository(User::class);
22        $entity = $this->getEntityById($input['id']);
23
24        $current_user = $this->authUtils()->getCurrentUser();
25        $is_me = (
26            $current_user
27            && $entity->getUsername() === $current_user->getUsername()
28            && $entity->getId() === $current_user->getId()
29        );
30        $can_update = $this->entityUtils()->canUpdateOlzEntity($entity, null, 'users');
31        if (!$is_me && !$can_update) {
32            throw new HttpError(403, "Kein Zugriff!");
33        }
34
35        // Username validation
36        $old_username = $entity->getUsername();
37        $new_username = $input['data']['username'];
38        $is_username_updated = $new_username !== $old_username;
39        if (!$this->authUtils()->isUsernameAllowed($new_username)) {
40            throw HttpError::validationError(['username' => ["Der Benutzername darf nur Buchstaben, Zahlen, und die Zeichen -_. enthalten."]]);
41        }
42        if ($is_username_updated && !$this->authUtils()->isUsernameUnique($new_username, $entity)) {
43            throw HttpError::validationError(['username' => ["Dieser Benutzername ist bereits vergeben."]]);
44        }
45
46        // Email validation
47        $new_email = $input['data']['email'] ?? null;
48        $is_email_updated = $new_email !== $entity->getEmail();
49        if (preg_match('/@olzimmerberg\.ch$/i', $new_email ?? '')) {
50            throw HttpError::validationError(['email' => ["Bitte keine @olzimmerberg.ch E-Mail verwenden."]]);
51        }
52        if ($is_email_updated) {
53            $same_email_user = $user_repo->findOneBy(['email' => $new_email]);
54            if ($same_email_user) {
55                throw HttpError::validationError(['email' => ["Es existiert bereits eine Person mit dieser E-Mail Adresse."]]);
56            }
57        }
58
59        // TODO Do this more elegantly?
60        $old_data = $this->getEntityData($entity);
61        $this->log()->notice('OLD:', [$old_data]);
62
63        $this->entityUtils()->updateOlzEntity($entity, $input['meta']);
64        if ($is_username_updated) {
65            $entity->setOldUsername($entity->getUsername());
66        }
67        $this->updateEntityWithData($entity, $input['data']);
68        if ($is_email_updated) {
69            $entity->setEmailIsVerified(false);
70            $entity->setEmailVerificationToken(null);
71            $entity->removePermission('verified_email');
72        }
73
74        // TODO Do this more elegantly?
75        $new_data = $this->getEntityData($entity);
76        $this->log()->notice('NEW:', [$new_data]);
77
78        $this->entityManager()->persist($entity);
79        $this->entityManager()->flush();
80        $this->persistUploads($entity, $input['data']);
81
82        if ($is_username_updated && $this->session()->get('user') === $old_username) {
83            $this->session()->set('user', $new_username);
84        }
85
86        if ($is_email_updated) {
87            $this->emailUtils()->setLogger($this->log());
88            try {
89                $this->emailUtils()->sendEmailVerificationEmail($entity);
90            } catch (\Throwable $th) {
91                return [
92                    'custom' => ['status' => 'OK_NO_EMAIL_VERIFICATION'],
93                    'id' => $entity->getId() ?? 0,
94                ];
95            }
96            $this->entityManager()->flush();
97        }
98
99        return [
100            'custom' => ['status' => 'OK'],
101            'id' => $entity->getId() ?? 0,
102        ];
103    }
104}