OtpService::retrieveByPlainText()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
/*
4
 * @copyright 2018 Hilmi Erdem KEREN
5
 * @license MIT
6
 */
7
8
namespace Erdemkeren\Otp;
9
10
use Illuminate\Contracts\Auth\Authenticatable;
11
12
/**
13
 * Class OtpService.
14
 */
15
class OtpService
16
{
17
    /**
18
     * The password generator manager.
19
     *
20
     * @var PasswordGeneratorManagerInterface
21
     */
22
    private $manager;
23
24
    /**
25
     * The encryptor implementation.
26
     *
27
     * @var EncryptorInterface
28
     */
29
    private $encryptor;
30
31
    /**
32
     * The password length.
33
     *
34
     * @var int
35
     */
36
    private $passwordLength;
37
38
    /**
39
     * The default otp password generator.
40
     *
41
     * @var string
42
     */
43
    private $defaultGenerator;
44
45
    /**
46
     * The password generator.
47
     *
48
     * @var callable
49
     */
50
    private $passwordGenerator;
51
52
    /**
53
     * The name of the token class being used
54
     * by the otp service.
55
     *
56
     * @var string
57
     */
58
    private $tokenClass;
59
60
    /**
61
     * OtpService constructor.
62
     *
63
     * @param PasswordGeneratorManagerInterface $manager
64
     * @param EncryptorInterface                $encryptor
65
     * @param string                            $defaultGenerator
66
     * @param int                               $passwordLength
67
     * @param string                            $tokenClass
68
     */
69 8
    public function __construct(
70
        PasswordGeneratorManagerInterface $manager,
71
        EncryptorInterface $encryptor,
72
        string $defaultGenerator,
73
        int $passwordLength,
74
        string $tokenClass
75
    ) {
76 8
        $this->manager = $manager;
77 8
        $this->encryptor = $encryptor;
78 8
        $this->passwordLength = $passwordLength;
79 8
        $this->defaultGenerator = $defaultGenerator;
80
81 8
        if (! class_exists($tokenClass)) {
82 1
            throw new \RuntimeException(
83 1
                "The token implementation [{$tokenClass}] could not be found."
84
            );
85
        }
86
87 8
        $generatorReflection = new \ReflectionClass($tokenClass);
88 8
        if (! $generatorReflection->isInstantiable()) {
89 1
            throw new \RuntimeException(
90 1
                "The token implementation [{$tokenClass}] is not instantiable."
91
            );
92
        }
93
94 8
        if (! is_subclass_of($tokenClass, TokenInterface::class)) {
95 1
            throw new \TypeError(
96 1
                'The token class should be an instance of '.TokenInterface::class
97
            );
98
        }
99
100 8
        $this->tokenClass = $tokenClass;
101 8
    }
102
103
    /**
104
     * Check the otp of the authenticable
105
     * with the given cipher text.
106
     *
107
     * @param mixed  $authenticableId
108
     * @param string $token
109
     *
110
     * @return bool
111
     */
112 1
    public function check($authenticableId, string $token): bool
113
    {
114 1
        $token = $this->retrieveByCipherText($authenticableId, $token);
115
116 1
        return (bool) $token && ! $token->expired();
117
    }
118
119
    /**
120
     * Set the active password generator of the otp service.
121
     *
122
     * @param string $name
123
     */
124 1
    public function setPasswordGenerator(string $name): void
125
    {
126 1
        $this->passwordGenerator = $this->manager->get($name);
127 1
    }
128
129
    /**
130
     * Create a new otp token.
131
     *
132
     * @param Authenticatable|mixed $authenticatableId
133
     * @param int                   $length
134
     *
135
     * @return Token
136
     */
137 2
    public function create($authenticatableId, ?int $length = null): TokenInterface
138
    {
139 2
        $plainText = $this->getPasswordGenerator()($length ?: $this->passwordLength);
140 2
        $cipherText = $this->encryptor->encrypt($plainText);
141
142 2
        if ($authenticatableId instanceof Authenticatable) {
143 2
            $authenticatableId = $authenticatableId->getAuthIdentifier();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $authenticatableId is correct as $authenticatableId->getAuthIdentifier() targeting Erdemkeren\Otp\Http\Midd...le::getAuthIdentifier() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
144
        }
145
146 2
        return $this->tokenClass::create($authenticatableId, $cipherText, $plainText);
147
    }
148
149
    /**
150
     * Retrieve the token of the authenticable
151
     * by the given plain text.
152
     *
153
     * @param mixed  $authenticableId
154
     * @param string $plainText
155
     *
156
     * @return null|TokenInterface
157
     */
158 1
    public function retrieveByPlainText($authenticableId, string $plainText): ?TokenInterface
159
    {
160 1
        return $this->retrieveByCipherText($authenticableId, $this->encryptor->encrypt($plainText));
161
    }
162
163
    /**
164
     * Retrieve the token of the authenticable
165
     * by the given cipher text.
166
     *
167
     * @param mixed  $authenticableId
168
     * @param string $cipherText
169
     *
170
     * @return null|TokenInterface
171
     */
172 3
    public function retrieveByCipherText($authenticableId, string $cipherText): ?TokenInterface
173
    {
174 3
        if ($authenticableId instanceof Authenticatable) {
175 3
            $authenticableId = $authenticableId->getAuthIdentifier();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $authenticableId is correct as $authenticableId->getAuthIdentifier() targeting Erdemkeren\Otp\Http\Midd...le::getAuthIdentifier() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
176
        }
177
178 3
        return $this->tokenClass::retrieveByAttributes([
179 3
            'authenticable_id' => $authenticableId,
180 3
            'cipher_text'      => $cipherText,
181
        ]);
182
    }
183
184
    /**
185
     * Add a new password generator implementation.
186
     *
187
     * @param string                                     $name
188
     * @param callable|PasswordGeneratorInterface|string $generator
189
     */
190 1
    public function addPasswordGenerator(string $name, $generator): void
191
    {
192 1
        $this->manager->register($name, $generator);
193 1
    }
194
195
    /**
196
     * Get the active password generator.
197
     *
198
     * @return callable
199
     */
200 2
    private function getPasswordGenerator(): callable
201
    {
202 2
        return $this->passwordGenerator ?: $this->passwordGenerator = $this->manager->get($this->defaultGenerator);
203
    }
204
}
205