Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
70.83% covered (warning)
70.83%
34 / 48
53.85% covered (warning)
53.85%
7 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
AuthenticatedUser
70.83% covered (warning)
70.83%
34 / 48
53.85% covered (warning)
53.85%
7 / 13
31.94
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 base64UrlDecode
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 fromJwtPayload
80.00% covered (warning)
80.00%
16 / 20
0.00% covered (danger)
0.00%
0 / 1
7.39
 getExternalUserId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setExternalUserId
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getEmail
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setEmail
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getGivenName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setGivenName
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getFamilyName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setFamilyName
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 toArray
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 jsonSerialize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace BO\Zmscitizenapi\Models;
6
7use BO\Zmscitizenapi\Exceptions\InvalidAuthTokenException;
8use JsonSerializable;
9
10class AuthenticatedUser implements JsonSerializable
11{
12    private ?string $externalUserId;
13    private ?string $givenName;
14    private ?string $familyName;
15    private ?string $email;
16
17    public function __construct(
18        ?string $externalUserId = null,
19        ?string $email = null,
20        ?string $givenName = null,
21        ?string $familyName = null,
22    ) {
23        $this->externalUserId = $externalUserId;
24        $this->email = $email;
25        $this->givenName = $givenName;
26        $this->familyName = $familyName;
27    }
28
29    private static function base64UrlDecode(string $data): string
30    {
31        $replaced = strtr($data, '-_', '+/');
32        $pad = strlen($replaced) % 4;
33        if ($pad) {
34            $replaced .= str_repeat('=', 4 - $pad);
35        }
36        return base64_decode($replaced) ?: '';
37    }
38
39    public static function fromJwtPayload(?string $token): ?self
40    {
41        // Token is validated in API gateway
42        if (is_null($token)) {
43            return null;
44        }
45        $tokenParts = explode('.', $token);
46        if (count($tokenParts) !== 3) {
47            throw new InvalidAuthTokenException('authKeyMismatch', 'Invalid JWT payload.');
48        }
49        $payload = json_decode(self::base64UrlDecode($tokenParts[1]), true);
50
51        $instance = new self();
52        if (empty($payload['lhmExtID'])) {
53            throw new InvalidAuthTokenException('authKeyMismatch', 'Property `lhmExtID` is missing from the JWT payload.');
54        }
55        $instance->setExternalUserId($payload['lhmExtID']);
56        if (empty($payload['email'])) {
57            throw new InvalidAuthTokenException('authKeyMismatch', 'Property `email` is missing from the JWT payload.');
58        }
59        $instance->setEmail($payload['email']);
60        if (empty($payload['given_name'])) {
61            throw new InvalidAuthTokenException('authKeyMismatch', 'Property `given_name` is missing from the JWT payload.');
62        }
63        $instance->setGivenName($payload['given_name']);
64        if (empty($payload['family_name'])) {
65            throw new InvalidAuthTokenException('authKeyMismatch', 'Property `family_name` is missing from the JWT payload.');
66        }
67        $instance->setFamilyName($payload['family_name']);
68        return $instance;
69    }
70
71    public function getExternalUserId(): ?string
72    {
73        return $this->externalUserId;
74    }
75
76    public function setExternalUserId(?string $externalUserId): self
77    {
78        $this->externalUserId = $externalUserId;
79        return $this;
80    }
81
82    public function getEmail(): ?string
83    {
84        return $this->email;
85    }
86
87    public function setEmail(?string $email): self
88    {
89        $this->email = $email;
90        return $this;
91    }
92
93    public function getGivenName(): ?string
94    {
95        return $this->givenName;
96    }
97
98    public function setGivenName(?string $givenName): self
99    {
100        $this->givenName = $givenName;
101        return $this;
102    }
103
104    public function getFamilyName(): ?string
105    {
106        return $this->familyName;
107    }
108
109    public function setFamilyName(?string $familyName): self
110    {
111        $this->familyName = $familyName;
112        return $this;
113    }
114
115    public function toArray(): array
116    {
117        return [
118            'external_user_id' => $this->externalUserId,
119            'email' => $this->email,
120            'given_name' => $this->givenName,
121            'family_name' => $this->familyName,
122        ];
123    }
124
125    public function jsonSerialize(): mixed
126    {
127        return $this->toArray();
128    }
129}