Completed
Push — master ( c458f8...eeebc2 )
by Matze
06:56
created

UserProvider::deleteUser()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 15
rs 9.4285
cc 2
eloc 9
nc 2
nop 1
1
<?php
2
3
namespace BrainExe\Core\Authentication;
4
5
use BrainExe\Annotations\Annotations\Inject;
6
use BrainExe\Annotations\Annotations\Service;
7
use BrainExe\Core\Authentication\Event\DeleteUserEvent;
8
use BrainExe\Core\Authentication\Exception\UsernameNotFoundException;
9
use BrainExe\Core\Traits\EventDispatcherTrait;
10
use BrainExe\Core\Traits\IdGeneratorTrait;
11
use BrainExe\Core\Traits\RedisTrait;
12
13
/**
14
 * @api
15
 * @Service("Core.Authentication.UserProvider", public=false)
16
 */
17
class UserProvider
18
{
19
20
    use RedisTrait;
21
    use IdGeneratorTrait;
22
    use EventDispatcherTrait;
23
24
    const REDIS_USER       = 'user:%d';
25
    const REDIS_USER_NAMES = 'user_names';
26
27
    /**
28
     * @var PasswordHasher
29
     */
30
    private $hasher;
31
32
    /**
33
     * @var LoadUser
34
     */
35
    private $loadUser;
36
37
    /**
38
     * @Inject({
39
        "@PasswordHasher",
40
        "@Authentication.LoadUser",
41
     * })
42
     * @param PasswordHasher $passwordHasher
43
     * @param LoadUser $loadUser
44
     */
45
    public function __construct(PasswordHasher $passwordHasher, LoadUser $loadUser)
46
    {
47
        $this->hasher   = $passwordHasher;
48
        $this->loadUser = $loadUser;
49
    }
50
51
    /**
52
     * @param string $username
53
     * @return UserVO
54
     * @throws UsernameNotFoundException
55
     */
56
    public function loadUserByUsername(string $username) : UserVO
57
    {
58
        return $this->loadUser->loadUserByUsername($username);
59
    }
60
61
    /**
62
     * @param int $userId
63
     * @return UserVO
64
     * @throws UsernameNotFoundException
65
     */
66
    public function loadUserById(int $userId) : UserVO
67
    {
68
        return $this->loadUser->loadUserById($userId);
69
    }
70
71
    /**
72
     * @return string[]
73
     */
74
    public function getAllUserNames() : array
75
    {
76
        return $this->getRedis()->hgetall(self::REDIS_USER_NAMES);
77
    }
78
79
    /**
80
     * @param string $password
81
     * @return string $hash
82
     */
83
    public function generateHash(string $password) : string
84
    {
85
        return $this->hasher->generateHash($password);
86
    }
87
88
    /**
89
     * @param string $password
90
     * @param string $hash
91
     * @return bool
92
     */
93
    public function verifyHash(string $password, string $hash) : bool
94
    {
95
        return $this->hasher->verifyHash($password, $hash);
96
    }
97
98
    /**
99
     * @param UserVO $user
100
     * @param string $newPassword
101
     */
102
    public function changePassword(UserVO $user, string $newPassword)
103
    {
104
        $hash           = $this->generateHash($newPassword);
105
        $user->password = $hash;
106
107
        $this->setUserProperty($user, 'password');
108
    }
109
110
    /**
111
     * @param UserVO $userVo
112
     * @param string $property
113
     */
114
    public function setUserProperty(UserVO $userVo, string $property)
115
    {
116
        $redis = $this->getRedis();
117
        $value = $userVo->$property;
118
119
        if (is_array($value)) {
120
            $value = implode(',', $value);
121
        }
122
        $redis->hset($this->getKey($userVo->id), $property, $value);
123
    }
124
125
    /**
126
     * @param UserVO $user
127
     * @return int $user_id
128
     */
129
    public function register(UserVO $user) : int
130
    {
131
        $redis        = $this->getRedis()->pipeline();
132
        $passwordHash = $this->generateHash($user->password);
133
134
        $userArray = [
135
            'username' => $user->getUsername(),
136
            'password' => $passwordHash,
137
            'roles'    => implode(',', $user->roles),
138
            'one_time_secret' => $user->one_time_secret,
139
            'avatar'   => $user->avatar
140
        ];
141
142
        $newUserId = $this->generateUniqueId('userid');
143
144
        $redis->hset(self::REDIS_USER_NAMES, strtolower($user->getUsername()), $newUserId);
145
        $redis->hmset($this->getKey($newUserId), $userArray);
146
147
        $redis->execute();
148
149
        $user->id = $newUserId;
150
151
        return $newUserId;
152
    }
153
154
    /**
155
     * @param int $userId
156
     */
157
    public function deleteUser(int $userId)
158
    {
159
        $user = $this->loadUser->loadUserById($userId);
160
161
        if ($user instanceof AnonymusUserVO) {
162
            return;
163
        }
164
165
        $event = new DeleteUserEvent($user, DeleteUserEvent::DELETE);
166
        $this->dispatchEvent($event);
167
168
        $redis = $this->getRedis();
169
        $redis->hdel(self::REDIS_USER_NAMES, strtolower($user->getUsername()));
170
        $redis->del($this->getKey($userId));
171
    }
172
173
    /**
174
     * @param int $userId
175
     * @return string
176
     */
177
    private function getKey(int $userId) : string
178
    {
179
        return sprintf(self::REDIS_USER, $userId);
180
    }
181
}
182