Passed
Push — master ( 06cf71...6c597b )
by Rutger
03:06
created

User   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 21
eloc 33
c 2
b 0
f 0
dl 0
loc 177
rs 10

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getAuthKey() 0 2 1
A getId() 0 3 1
A validateAuthKey() 0 2 1
A findIdentity() 0 3 1
A isOauth2ClientAllowed() 0 5 1
A findByUsername() 0 3 1
A getLatestAuthenticatedAt() 0 3 2
A getAvailableIdentities() 0 3 1
A setPassword() 0 3 1
A validatePassword() 0 3 1
A fields() 0 8 3
A getLinkedIdentities() 0 3 1
A getLinkedIdentity() 0 9 2
A getUserIdentityLinks() 0 3 1
A hasLinkedIdentity() 0 8 2
A getCustomOpenIdConnectClaimProperty() 0 3 1
1
<?php
2
3
namespace sample\models;
4
5
use rhertogh\Yii2Oauth2Server\interfaces\models\external\user\Oauth2OidcUserInterface;
6
use rhertogh\Yii2Oauth2Server\interfaces\models\external\user\Oauth2PasswordGrantUserInterface;
7
use rhertogh\Yii2Oauth2Server\interfaces\models\external\user\Oauth2UserInterface;
8
use rhertogh\Yii2Oauth2Server\Oauth2Module;
9
use rhertogh\Yii2Oauth2Server\traits\models\Oauth2OidcUserIdentityTrait;
10
use rhertogh\Yii2Oauth2Server\traits\models\Oauth2UserIdentityTrait;
11
use Yii;
12
use yii\db\ActiveQuery;
13
use yii\db\ActiveRecord;
14
use yii\web\IdentityInterface;
15
16
/**
17
 * @property int $id
18
 * @property string $username
19
 * @property string $password_hash
20
 * @property string $email_address
21
 * @property string $latest_authenticated_at
22
 * @property boolean $enabled
23
 * @property int $created_at
24
 * @property int $updated_at
25
 *
26
 * @property-read User[] $linkedIdentities
27
 */
28
class User extends ActiveRecord implements
29
    IdentityInterface,
30
    Oauth2UserInterface,
31
    Oauth2OidcUserInterface, # Optional interface, only required when OpenID Connect support is enabled
32
    Oauth2PasswordGrantUserInterface # Optional interface, only required when `password` grant type is used
33
{
34
    // phpcs:disable Generic.Files.LineLength.TooLong, PSR12.Traits.UseDeclaration.NoBlankLineAfterUse -- Sample documentation
35
    use Oauth2UserIdentityTrait; # Helper trait for Oauth2UserInterface
36
    use Oauth2OidcUserIdentityTrait; # Optional helper trait for Oauth2OidcUserInterface, only required when OpenID Connect support is enabled
37
    // phpcs:enable Generic.Files.LineLength.TooLong, PSR12.Traits.UseDeclaration.NoBlankLineAfterUse
38
39
    # region IdentityInterface (Default Yii interface)
40
    /**
41
     * @inheritDoc
42
     */
43
    public static function findIdentity($id)
44
    {
45
        return static::findOne(['id' => $id]);
46
    }
47
48
    /**
49
     * @inheritDoc
50
     */
51
    public function getId()
52
    {
53
        return $this->id;
54
    }
55
56
    /**
57
     * @inheritDoc
58
     */
59
    public function getAuthKey()
60
    {
61
        // TODO: Implement getAuthKey() method (native to Yii2 \yii\web\IdentityInterface).
62
    }
63
64
    /**
65
     * @inheritDoc
66
     */
67
    public function validateAuthKey($authKey)
68
    {
69
        // TODO: Implement getAuthKey() method (native to Yii2 \yii\web\IdentityInterface).
70
    }
71
    # endregion IdentityInterface
72
73
    # region Oauth2UserInterface
74
    /**
75
     * @inheritDoc
76
     */
77
    public function isOauth2ClientAllowed($client, $grantType)
78
    {
79
        // If you want, you can restrict access to certain clients and/or grant types.
80
        // For now, allow all users to use all clients with any grant type.
81
        return true;
82
    }
83
    # endregion Oauth2UserInterface
84
85
    # region Oauth2OidcUserInterface
86
    /**
87
     * @inheritDoc
88
     */
89
    public function getLatestAuthenticatedAt()
90
    {
91
        return new \DateTimeImmutable('@' . ($this->latest_authenticated_at ?: $this->created_at));
92
    }
93
94
    # Other methods are implemented via Oauth2OidcUserIdentityTrait
95
    # endregion Oauth2OidcUserInterface
96
97
    # region Oauth2PasswordGrantUserInterface (Optional interface, only required when `password` grant type is used)
98
    /**
99
     * @inheritDoc
100
     */
101
    public static function findByUsername($username)
102
    {
103
        return static::findOne(['username' => $username]);
104
    }
105
106
    /**
107
     * Generates password hash from password and sets it to the model
108
     *
109
     * @param string $password
110
     */
111
    public function setPassword($password)
112
    {
113
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);
114
    }
115
116
    /**
117
     * @inheritDoc
118
     */
119
    public function validatePassword($password)
120
    {
121
        return Yii::$app->security->validatePassword($password, $this->password_hash);
122
    }
123
    # endregion Oauth2PasswordGrantUserInterface
124
125
    # region Not Oauth specific but can be used with Oauth Scopes to hide/expose certain fields
126
    /**
127
     * @inheritDoc
128
     */
129
    public function fields()
130
    {
131
        /** @var Oauth2Module $oauth2Module */
132
        $oauth2Module = Yii::$app->getModule('oauth2');
133
        return [
134
            'id',
135
            ...($oauth2Module->requestHasScope('user.username.read') ? ['username'] : []),
136
            ...($oauth2Module->requestHasScope('user.email_address.read') ? ['email_address'] : []),
137
        ];
138
    }
139
    # endregion
140
141
    # region Sample for a custom OpenID Connect Claim
142
    public function getCustomOpenIdConnectClaimProperty()
143
    {
144
        return 'Custom property for user ' . $this->id;
145
    }
146
    # endregion
147
148
    # region Application specific implementation for user identity selection
149
    /**
150
     * Checks if this user has another identity linked to their account
151
     * @param int $id
152
     * @return bool
153
     */
154
    public function hasLinkedIdentity($id)
155
    {
156
        if ($id == $this->id) {
157
            return true;
158
        }
159
        return $this->getUserIdentityLinks()
160
            ->andWhere(['linked_user_id' => $id])
161
            ->exists();
162
    }
163
164
    /**
165
     * Get an identity that is linked to this account
166
     * @param $id
167
     * @return User|null
168
     */
169
    public function getLinkedIdentity($id)
170
    {
171
        if ($id == $this->id) {
172
            return $this;
173
        }
174
175
        return $this->getLinkedIdentities()
176
            ->andWhere(['id' => $id])
177
            ->one();
178
    }
179
180
    /**
181
     * Get all available identities for this account (including itself)
182
     * @return User[]
183
     */
184
    public function getAvailableIdentities()
185
    {
186
        return [$this, ...$this->linkedIdentities];
187
    }
188
    # endregion
189
190
    # region ActiveRecord Relations
191
    /**
192
     * @return ActiveQuery
193
     */
194
    public function getUserIdentityLinks()
195
    {
196
        return $this->hasMany(UserIdentityLink::class, ['user_id' => 'id']);
197
    }
198
199
    /**
200
     * @return ActiveQuery
201
     */
202
    public function getLinkedIdentities()
203
    {
204
        return $this->hasMany(User::class, ['id' => 'linked_user_id'])->via('userIdentityLinks');
205
    }
206
    # endregion
207
}
208