Passed
Pull Request — master (#222)
by Arman
02:52
created

SessionAuthAdapter::removeRememberToken()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 17
rs 9.9332
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.9.6
13
 */
14
15
namespace Quantum\Libraries\Auth\Adapters;
16
17
use Quantum\Libraries\Auth\Contracts\AuthenticatableInterface;
18
use Quantum\Libraries\Database\Exceptions\DatabaseException;
19
use Quantum\Libraries\Session\Exceptions\SessionException;
20
use Quantum\Libraries\Auth\Contracts\AuthServiceInterface;
21
use Quantum\Libraries\Config\Exceptions\ConfigException;
22
use Quantum\Libraries\Auth\Exceptions\AuthException;
23
use Quantum\Libraries\Auth\Constants\AuthKeys;
24
use Quantum\Libraries\Auth\Traits\AuthTrait;
25
use Quantum\Di\Exceptions\DiException;
26
use Quantum\Exceptions\BaseException;
27
use Quantum\Libraries\Hasher\Hasher;
28
use Quantum\Libraries\Mailer\Mailer;
29
use Quantum\Libraries\Auth\User;
30
use ReflectionException;
31
use Exception;
32
33
/**
34
 * Class WebAuth
35
 * @package Quantum\Libraries\Auth
36
 */
37
class SessionAuthAdapter implements AuthenticatableInterface
38
{
39
40
    use AuthTrait;
41
42
    /**
43
     * @param AuthServiceInterface $authService
44
     * @param Mailer $mailer
45
     * @param Hasher $hasher
46
     * @throws AuthException
47
     */
48
    public function __construct(AuthServiceInterface $authService, Mailer $mailer, Hasher $hasher)
49
    {
50
        $this->authService = $authService;
51
        $this->mailer = $mailer;
0 ignored issues
show
Documentation Bug introduced by
It seems like $mailer of type Quantum\Libraries\Mailer\Mailer is incompatible with the declared type Quantum\Libraries\Mailer\Contracts\MailerInterface of property $mailer.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
52
        $this->hasher = $hasher;
53
54
        $this->verifySchema($this->authService->userSchema());
55
    }
56
57
    /**
58
     * @inheritDoc
59
     * @throws AuthException
60
     * @throws ConfigException
61
     * @throws DatabaseException
62
     * @throws DiException
63
     * @throws ReflectionException
64
     * @throws SessionException
65
     * @throws Exception
66
     */
67
    public function signin(string $username, string $password, bool $remember = false)
68
    {
69
        $user = $this->getUser($username, $password);
70
71
        if ($remember) {
72
            $this->setRememberToken($user);
73
        }
74
75
        if ($this->isTwoFactorEnabled()) {
76
            return $this->twoStepVerification($user);
77
        }
78
79
        session()->regenerateId();
80
        session()->set(self::AUTH_USER, $this->getVisibleFields($user));
81
82
        return true;
83
    }
84
85
    /**
86
     * @inheritDoc
87
     * @throws ConfigException
88
     * @throws DiException
89
     * @throws ReflectionException
90
     * @throws BaseException
91
     */
92
    public function signout(): bool
93
    {
94
        if (session()->has(self::AUTH_USER)) {
95
            session()->delete(self::AUTH_USER);
96
            session()->regenerateId();
97
            $this->removeRememberToken();
98
99
            return true;
100
        }
101
102
        return false;
103
    }
104
105
    /**
106
     * @inheritDoc
107
     * @throws BaseException
108
     * @throws ConfigException
109
     * @throws DiException
110
     * @throws ReflectionException
111
     */
112
    public function user(): ?User
113
    {
114
        if (session()->has(self::AUTH_USER) && is_array(session()->get(self::AUTH_USER))) {
115
            return (new User())->setData(session()->get(self::AUTH_USER));
0 ignored issues
show
Bug introduced by
It seems like session()->get(self::AUTH_USER) can also be of type null; however, parameter $data of Quantum\Libraries\Auth\User::setData() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

115
            return (new User())->setData(/** @scrutinizer ignore-type */ session()->get(self::AUTH_USER));
Loading history...
116
        }
117
118
        if (cookie()->has($this->keyFields[AuthKeys::REMEMBER_TOKEN])) {
119
            $user = $this->checkRememberToken();
120
121
            if ($user) {
122
                session()->set(self::AUTH_USER, $this->getVisibleFields($user));
123
                return $this->user();
124
            }
125
        }
126
127
        return null;
128
    }
129
130
    /**
131
     * Verify OTP
132
     * @param int $otp
133
     * @param string $otpToken
134
     * @return bool
135
     * @throws AuthException
136
     * @throws BaseException
137
     * @throws ConfigException
138
     * @throws DiException
139
     * @throws ReflectionException
140
     */
141
    public function verifyOtp(int $otp, string $otpToken): bool
142
    {
143
        $user = $this->verifyAndUpdateOtp($otp, $otpToken);
144
145
        session()->set(self::AUTH_USER, $this->getVisibleFields($user));
146
147
        return true;
148
    }
149
150
    /**
151
     * Check Remember Token
152
     * @return User|false
153
     */
154
    private function checkRememberToken()
155
    {
156
        $user = $this->authService->get(
157
            $this->keyFields[AuthKeys::REMEMBER_TOKEN],
158
            cookie()->get($this->keyFields[AuthKeys::REMEMBER_TOKEN])
159
        );
160
161
        if (!$user) {
162
            return false;
163
        }
164
165
        if ($this->isTwoFactorEnabled() && !empty($user->getFieldValue($this->keyFields[AuthKeys::OTP_TOKEN]))) {
166
            return false;
167
        }
168
169
        return $user;
170
    }
171
172
    /**
173
     * Set Remember Token
174
     * @param User $user
175
     */
176
    private function setRememberToken(User $user)
177
    {
178
        $rememberToken = $this->generateToken();
179
180
        $this->authService->update(
181
            $this->keyFields[AuthKeys::USERNAME],
182
            $user->getFieldValue($this->keyFields[AuthKeys::USERNAME]),
183
            [$this->keyFields[AuthKeys::REMEMBER_TOKEN] => $rememberToken]
184
        );
185
186
        cookie()->set($this->keyFields[AuthKeys::REMEMBER_TOKEN], $rememberToken);
187
    }
188
189
    /**
190
     * Remove Remember token
191
     */
192
    private function removeRememberToken()
193
    {
194
        if (cookie()->has($this->keyFields[AuthKeys::REMEMBER_TOKEN])) {
195
            $user = $this->authService->get(
196
                $this->keyFields[AuthKeys::REMEMBER_TOKEN],
197
                cookie()->get($this->keyFields[AuthKeys::REMEMBER_TOKEN])
198
            );
199
200
            if ($user) {
201
                $this->authService->update(
202
                    $this->keyFields[AuthKeys::REMEMBER_TOKEN],
203
                    $user->getFieldValue($this->keyFields[AuthKeys::REMEMBER_TOKEN]),
204
                    [$this->keyFields[AuthKeys::REMEMBER_TOKEN] => '']
205
                );
206
            }
207
208
            cookie()->delete($this->keyFields[AuthKeys::REMEMBER_TOKEN]);
209
        }
210
    }
211
}