Passed
Push — master ( 6f2986...60854d )
by Rutger
13:35
created

User::hasLinkedIdentity()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 8
rs 10
cc 2
nc 2
nop 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
     * @inheritDoc
108
     */
109
    public function validatePassword($password)
110
    {
111
        return Yii::$app->security->validatePassword($password, $this->password_hash);
112
    }
113
    # endregion Oauth2PasswordGrantUserInterface
114
115
    # region Not Oauth specific but can be used with Oauth Scopes to hide/expose certain fields
116
    /**
117
     * @inheritDoc
118
     */
119
    public function fields()
120
    {
121
        /** @var Oauth2Module $oauth2Module */
122
        $oauth2Module = Yii::$app->getModule('oauth2');
123
        return [
124
            'id',
125
            ...($oauth2Module->requestHasScope('user.username.read') ? ['username'] : []),
126
            ...($oauth2Module->requestHasScope('user.email_address.read') ? ['email_address'] : []),
127
        ];
128
    }
129
    # endregion
130
131
    # region Application specific implementation for user identity selection
132
    /**
133
     * Checks if this user has another identity linked to their account
134
     * @param int $id
135
     * @return bool
136
     */
137
    public function hasLinkedIdentity($id)
138
    {
139
        if ($id == $this->id) {
140
            return true;
141
        }
142
        return $this->getUserIdentityLinks()
143
            ->andWhere(['linked_user_id' => $id])
144
            ->exists();
145
    }
146
147
    /**
148
     * Get an identity that is linked to this account
149
     * @param $id
150
     * @return User|null
151
     */
152
    public function getLinkedIdentity($id)
153
    {
154
        if ($id == $this->id) {
155
            return $this;
156
        }
157
158
        return $this->getLinkedIdentities()
159
            ->andWhere(['id' => $id])
160
            ->one();
161
    }
162
163
    /**
164
     * Get all available identities for this account (including itself)
165
     * @return User[]
166
     */
167
    public function getAvailableIdentities()
168
    {
169
        return [$this, ...$this->linkedIdentities];
170
    }
171
    # endregion
172
173
    # region ActiveRecord Relations
174
    /**
175
     * @return ActiveQuery
176
     */
177
    public function getUserIdentityLinks()
178
    {
179
        return $this->hasMany(UserIdentityLink::class, ['user_id' => 'id']);
180
    }
181
182
    /**
183
     * @return ActiveQuery
184
     */
185
    public function getLinkedIdentities()
186
    {
187
        return $this->hasMany(User::class, ['id' => 'linked_user_id'])->via('userIdentityLinks');
188
    }
189
    # endregion
190
}
191