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