OneTimePassword   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 3
dl 0
loc 125
ccs 40
cts 40
cp 1
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A generateSecret() 0 9 1
A getData() 0 10 1
A verifyOneTimePassword() 0 16 4
A deleteOneTimeSecret() 0 6 1
A sendCodeViaMail() 0 16 3
1
<?php
2
3
namespace BrainExe\Core\Authentication\TOTP;
4
5
use BrainExe\Core\Annotations\Service;
6
use BrainExe\Core\Application\UserException;
7
use BrainExe\Core\Authentication\Exception\UserNotFoundException;
8
use BrainExe\Core\Authentication\UserProvider;
9
use BrainExe\Core\Authentication\UserVO;
10
use BrainExe\Core\EventDispatcher\EventDispatcher;
11
use BrainExe\Core\Mail\SendMailEvent;
12
use BrainExe\Core\Util\IdGenerator;
13
14
/**
15
 * @Service
16
 */
17
class OneTimePassword
18
{
19
20
    const SECRET_LENGTH = 16;
21
22
    /**
23
     * @var UserProvider
24
     */
25
    private $userProvider;
26
27
    /**
28
     * @var TOTP
29
     */
30
    private $totp;
31
32
    /**
33
     * @var EventDispatcher
34
     */
35
    private $dispatcher;
36
37
    /**
38
     * @var IdGenerator
39
     */
40
    private $idGenerator;
41
42
    /**
43
     * @param UserProvider $databaseUserProvider
44
     * @param TOTP $totp
45
     * @param EventDispatcher $dispatcher
46
     * @param IdGenerator $idGenerator
47
     */
48 9
    public function __construct(
49
        UserProvider $databaseUserProvider,
50
        TOTP $totp,
51
        EventDispatcher $dispatcher,
52
        IdGenerator $idGenerator
53
    ) {
54 9
        $this->userProvider = $databaseUserProvider;
55 9
        $this->totp         = $totp;
56 9
        $this->dispatcher   = $dispatcher;
57 9
        $this->idGenerator  = $idGenerator;
58 9
    }
59
60
    /**
61
     * @param UserVO $userVo
62
     * @return Data
63
     */
64 1
    public function generateSecret(UserVO $userVo)
65
    {
66 1
        $secret = $this->idGenerator->generateRandomId(self::SECRET_LENGTH);
67
68 1
        $userVo->one_time_secret = $secret;
69 1
        $this->userProvider->setUserProperty($userVo, 'one_time_secret');
70
71 1
        return $this->getData($secret);
72
    }
73
74
    /**
75
     * @param $secret
76
     * @return Data
77
     */
78 1
    public function getData($secret)
79
    {
80 1
        $url = $this->totp->getUri($secret);
81
82 1
        $data = new Data();
83 1
        $data->secret = $secret;
84 1
        $data->url    = $url;
85
86 1
        return $data;
87
    }
88
89
    /**
90
     * @param UserVO $userVo
91
     * @param string $givenToken
92
     * @throws UserException
93
     */
94 4
    public function verifyOneTimePassword(UserVO $userVo, $givenToken)
95
    {
96 4
        if (empty($userVo->one_time_secret)) {
97 1
            throw new UserException(_('No one time secret requested'));
98
        }
99
100 3
        if (empty($givenToken)) {
101 1
            throw new UserException(_('No one time token given'));
102
        }
103
104 2
        $verified = $this->totp->verify($userVo->one_time_secret, $givenToken);
105
106 2
        if (!$verified) {
107 1
            throw new UserException(sprintf(_('Invalid token: "%s"!'), $givenToken));
108
        }
109 1
    }
110
111
    /**
112
     * @param UserVO $userVo
113
     */
114 1
    public function deleteOneTimeSecret(UserVO $userVo)
115
    {
116 1
        $userVo->one_time_secret = null;
117
118 1
        $this->userProvider->setUserProperty($userVo, 'one_time_secret');
119 1
    }
120
121
    /**
122
     * @param string $userName
123
     * @throws UserException
124
     */
125 3
    public function sendCodeViaMail($userName)
126
    {
127
        try {
128 3
            $user = $this->userProvider->loadUserByUsername($userName);
129
130 2
            if (empty($user->email)) {
131 1
                throw new UserException(_('No email address defined for this user'));
132
            }
133 1
            $code = $this->totp->current($user->one_time_secret);
134
135 1
            $event = new SendMailEvent($user->email, $code, $code);
136 1
            $this->dispatcher->dispatchEvent($event);
137 2
        } catch (UserNotFoundException $e) {
138 1
            throw new UserException(_('Invalid username'));
139
        }
140 1
    }
141
}
142