Completed
Push — master ( 80619a...e9eada )
by Arman
03:36
created

BaseAuth::twoStepVerification()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 15
c 0
b 0
f 0
dl 0
loc 28
rs 9.7666
cc 1
nc 1
nop 2
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.0.0
13
 */
14
15
namespace Quantum\Libraries\Auth;
16
17
use Quantum\Libraries\Mailer\Mailer;
18
19
/**
20
 * Class BaseAuth
21
 * @package Quantum\Libraries\Auth
22
 */
23
abstract class BaseAuth
24
{
25
26
    /**
27
     * One time password length
28
     */
29
    const OTP_LENGTH = 6;
30
    
31
    /**
32
     * One time password key
33
     */
34
    const OTP_KEY = 'otpKey';
35
    
36
    /**
37
     * One time password expiry key
38
     */
39
    const OTP_EXPIRY_KEY = 'otpExpiryKey';
40
    
41
    /**
42
     * One time password token key
43
     */
44
    const OTP_TOKEN_KEY = 'otpTokenKey';
45
46
    /**
47
     * Username key
48
     */
49
    const USERNAME_KEY = 'usernameKey';
50
    
51
    /**
52
     * Password key
53
     */
54
    const PASSWORD_KEY = 'passwordKey';
55
56
    /**
57
     * Access token key
58
     */
59
    const ACCESS_TOKEN_KEY = 'accessTokenKey';
60
61
    /**
62
     * Refresh token key
63
     */
64
    const REFRESH_TOKEN_KEY = 'refreshTokenKey';
65
    
66
    /**
67
     * Activation token key
68
     */
69
    const ACTIVATION_TOKEN_KEY = 'activationTokenKey';
70
    
71
    /**
72
     * Reset token key
73
     */
74
    const RESET_TOKEN_KEY = 'resetTokenKey';
75
    
76
    /**
77
     * Remember token key
78
     */
79
    const REMEMBER_TOKEN_KEY = 'rememberTokenKey';
80
    
81
    /**
82
     * User
83
     * @return mixed|null
84
     */
85
    protected abstract function user();
86
87
    /**
88
     * Check
89
     * @return bool
90
     */
91
    public function check()
92
    {
93
        return !is_null($this->user());
94
    }
95
96
    /**
97
     * Check Verification
98
     * @return bool
99
     */
100
    public function checkVerification()
101
    {
102
        if (isset($this->user()->verification_code) && !empty($this->user()->verification_code)) {
103
            return true;
104
        }
105
        return false;
106
    }
107
108
    /**
109
     * Sign Up
110
     * @param array $userData
111
     * @param array|null $customData
112
     * @return mixed
113
     */
114
    public function signup(Mailer $mailer, $userData, $customData = null)
115
    {
116
        $activationToken = $this->generateToken();
117
118
        $userData[$this->keys[self::PASSWORD_KEY]] = $this->hasher->hash($userData[$this->keys[self::PASSWORD_KEY]]);
119
        $userData[$this->keys[self::ACTIVATION_TOKEN_KEY]] = $activationToken;
120
121
        $user = $this->authService->add($userData);
122
123
        $body = [
124
            'user' => $user,
125
            'activationToken' => $activationToken
126
        ];
127
128
        if ($customData) {
129
            $body = array_merge($body, $customData);
130
        }
131
132
        $this->sendMail($mailer, $user, $body);
133
134
        return $user;
135
    }
136
137
    /**
138
     * Activate
139
     * @param string $token
140
     */
141
    public function activate($token)
142
    {
143
        $this->authService->update(
144
                $this->keys[self::ACTIVATION_TOKEN_KEY], 
145
                $token, 
146
                [$this->keys[self::ACTIVATION_TOKEN_KEY] => '']
147
        );
148
    }
149
150
    /**
151
     * Forget
152
     * @param Mailer $mailer
153
     * @param string $username
154
     * @param string $template
155
     * @return string
156
     */
157
    public function forget(Mailer $mailer, $username)
158
    {
159
        $user = $this->authService->get($this->keys[self::USERNAME_KEY], $username);
160
161
        $resetToken = $this->generateToken();
162
163
        $this->authService->update(
164
                $this->keys[self::USERNAME_KEY], 
165
                $username, 
166
                [$this->keys[self::RESET_TOKEN_KEY] => $resetToken]
167
        );
168
169
        $body = [
170
            'user' => $user,
171
            'resetToken' => $resetToken
172
        ];
173
174
        $this->sendMail($mailer, $user, $body);
175
176
        return $resetToken;
177
    }
178
179
    /**
180
     * Reset
181
     * @param string $token
182
     * @param string $password
183
     */
184
    public function reset($token, $password)
185
    {
186
        $user = $this->authService->get($this->keys[self::RESET_TOKEN_KEY], $token);
187
188
        if (!$this->isActivated($user)) {
189
            $this->activate($token);
190
        }
191
192
        $this->authService->update(
193
                $this->keys[self::RESET_TOKEN_KEY], 
194
                $token, 
195
                [
196
                    $this->keys[self::PASSWORD_KEY] => $this->hasher->hash($password), 
197
                    $this->keys[self::RESET_TOKEN_KEY] => ''
198
                ]
199
        );
200
    }
201
    
202
    /**
203
     * Two Step Verification
204
     * @param Mailer $mailer
205
     * @param array $user
206
     * @return string
207
     */
208
    protected function twoStepVerification(Mailer $mailer, $user)
209
    {
210
        $otp = random_number(self::OTP_LENGTH);
211
        
212
        $otpToken = $this->generateToken($user[$this->keys[self::USERNAME_KEY]]);
213
        
214
        $time = new \DateTime();
215
216
        $time->add(new \DateInterval('PT' . config()->get('otp_expires') . 'M'));
217
218
        $this->authService->update(
219
                $this->keys[self::USERNAME_KEY], 
220
                $user[$this->keys[self::USERNAME_KEY]], 
221
                [
222
                    $this->keys[self::OTP_KEY] => $otp,
223
                    $this->keys[self::OTP_EXPIRY_KEY] => $time->format('Y-m-d H:i'),
224
                    $this->keys[self::OTP_TOKEN_KEY] => $otpToken,
225
                ]
226
        );
227
228
        $body = [
229
            'user' => $user,
230
            'code' => $otp
231
        ];
232
        
233
        $this->sendMail($mailer, $user, $body);
234
235
        return $otpToken;
236
    }
237
238
    /**
239
     * Filter Fields
240
     * @param array $user
241
     * @return mixed
242
     */
243
    protected function filterFields(array $user)
244
    {
245
        if (count($this->authService->getVisibleFields())) {
246
            foreach ($user as $key => $value) {
247
                if (!in_array($key, $this->authService->getVisibleFields())) {
248
                    unset($user[$key]);
249
                }
250
            }
251
        }
252
253
        return $user;
254
    }
255
256
    /**
257
     * Generate Token
258
     * @param mixed|null $val
259
     * @return string
260
     */
261
    protected function generateToken($val = null)
262
    {
263
        return base64_encode($this->hasher->hash($val ?: env('APP_KEY')));
264
    }
265
266
    /**
267
     * Is user account activated
268
     * @param mixed $user
269
     * @return bool
270
     */
271
    protected function isActivated($user)
272
    {
273
        return empty($user[$this->keys[self::ACTIVATION_TOKEN_KEY]]) ? true : false;
274
    }
275
276
    /**
277
     * Send email
278
     * @param Mailer $mailer
279
     * @param array $user
280
     * @param array $body
281
     */
282
    protected function sendMail(Mailer $mailer, array $user, array $body)
283
    {
284
        $fullName = (isset($user['firstname']) && isset($user['lastname'])) ? $user['firstname'] . ' ' . $user['lastname'] : '';
285
286
        $mailer->setFrom(config()->get('app_email'), config()->get('app_name'))
287
                ->setAddress($user[$this->keys[self::USERNAME_KEY]], $fullName)
288
                ->setBody($body)
289
                ->send();
290
    }
291
292
}
293