Passed
Push — main ( a8595a...1afaaf )
by Garbuz
03:24
created

TokenManager::isMorph()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 10
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Garbuzivan\Laraveltokens;
6
7
use Garbuzivan\Laraveltokens\Exceptions\TokenIsNotValidException;
8
use Garbuzivan\Laraveltokens\Exceptions\UserNotExistsException;
9
use Garbuzivan\Laraveltokens\Interfaces\AccessTokenRepositoryInterface;
10
use Garbuzivan\Laraveltokens\Interfaces\GlobalTokenRepositoryInterface;
11
use Garbuzivan\Laraveltokens\Traits\ManagerAccessTokenTrait;
12
use Garbuzivan\Laraveltokens\Traits\ManagerGlobalTokenTrait;
13
14
class TokenManager
15
{
16
    use ManagerAccessTokenTrait, ManagerGlobalTokenTrait;
17
18
    /**
19
     * @var Config $config
20
     */
21
    protected Config $config;
22
23
    /**
24
     * @var Token $token
25
     */
26
    protected Token $token;
27
28
    /**
29
     * @var AccessTokenRepositoryInterface
30
     */
31
    protected AccessTokenRepositoryInterface $accessTokenRepository;
32
33
    /**
34
     * @var GlobalTokenRepositoryInterface
35
     */
36
    protected GlobalTokenRepositoryInterface $globalTokenRepository;
37
38
    /**
39
     * @var Coder
40
     */
41
    protected Coder $coder;
42
43
    /**
44
     * Configuration constructor.
45
     *
46
     * @param Config                         $config
47
     * @param AccessTokenRepositoryInterface $TokenRepository
48
     * @param GlobalTokenRepositoryInterface $globalTokenRepository
49
     * @param Coder                          $coder
50
     */
51
    public function __construct(
52
        Config                         $config,
53
        AccessTokenRepositoryInterface $TokenRepository,
54
        GlobalTokenRepositoryInterface $globalTokenRepository,
55
        Coder                          $coder
56
    ) {
57
        $this->config = $config;
58
        $this->accessTokenRepository = $TokenRepository;
59
        $this->globalTokenRepository = $globalTokenRepository;
60
        $this->coder = $coder;
61
        $this->token = app(Token::class);
62
    }
63
64
    /**
65
     * Авторизация по токену
66
     *
67
     * @param string $token
68
     *
69
     * @return Token
70
     * @throws TokenIsNotValidException
71
     */
72
    public function auth(string $token): Token
73
    {
74
        $this->token->loadTokenHeader($this->coder->decode($token, $this->config->getSalt()));
75
        $token = $this->config->isEncryption() ? $this->getHash($token) : $token;
76
        $tokenDb = $this->accessTokenRepository->getAccessToken($token);
77
        $this->token->load($tokenDb);
78
        if (!$this->token->isValid()) {
79
            $tokenDb = $this->globalTokenRepository->getGlobalToken($token);
80
            $this->token->load($tokenDb);
81
        }
82
        if (!$this->token->isValid()) {
83
            throw new TokenIsNotValidException;
84
        }
85
        $this->setLastUse($this->token->id);
86
        return $this->token;
87
    }
88
89
    /**
90
     * @param int $token_id
91
     */
92
    public function setLastUse(int $token_id): void
93
    {
94
        if (!$this->config->isLastUse()) {
95
            return;
96
        }
97
        $this->accessTokenRepository->setLastUseAccessToken($token_id);
98
        $this->globalTokenRepository->setLastUseGlobalToken($token_id);
99
    }
100
101
    /**
102
     * Очистить таблицу токенов
103
     *
104
     * @return void
105
     */
106
    public function deleteAllTokens(): void
107
    {
108
        $this->accessTokenRepository->deleteAllAccessToken();
109
        $this->globalTokenRepository->deleteAllGlobalToken();
110
    }
111
112
    /**
113
     * Проверить актуальность токена (наличие токена и дата активности)
114
     *
115
     * @param string $token
116
     *
117
     * @return bool
118
     */
119
    public function isValid(string $token): bool
120
    {
121
        $token = $this->config->isEncryption() ? $this->getHash($token) : $token;
122
        $tokenInfo = $this->accessTokenRepository->getAccessToken($token);
123
        if (is_null($tokenInfo) || !$tokenInfo->isValid()) {
124
            return false;
125
        }
126
        return true;
127
    }
128
129
    /**
130
     * Генерация случайного токена на основе даты и случайной строки
131
     *
132
     * @param array $payload
133
     * @param array $head
134
     *
135
     * @return string
136
     * @throws \Exception
137
     */
138
    public function generateToken(array $payload = [], array $head = []): string
139
    {
140
        return $this->coder->encode($payload, $this->config->getSalt(), $head);
141
    }
142
143
    /**
144
     * Преобразование токена для БД в зависимости от настройки Encryption
145
     *
146
     * @param string $token
147
     *
148
     * @return string
149
     */
150
    public function getTokenDb(string $token): string
151
    {
152
        return $this->config->isEncryption() ? $this->getHash($token) : $token;
153
    }
154
155
    /**
156
     * Получение хэша
157
     *
158
     * @param string $string
159
     *
160
     * @return string
161
     */
162
    public function getHash(string $string): string
163
    {
164
        return hash('sha256', $string);
165
    }
166
167
    /**
168
     * Сравнение токена
169
     *
170
     * @param string $token
171
     * @param string $hash
172
     *
173
     * @return bool
174
     */
175
    public function isVerify(string $token, string $hash): bool
176
    {
177
        return strcmp($this->getTokenDb($token), $hash) !== 0;
178
    }
179
180
    /**
181
     * Получить deault Morph
182
     *
183
     * @return string
184
     */
185
    public function getDefaultMorph(): string
186
    {
187
        return 'App\Models\User';
188
    }
189
190
    /**
191
     * @return Token
192
     */
193
    public function getToken(): Token
194
    {
195
        return $this->token;
196
    }
197
198
    /**
199
     * Проверка полиморфной связи
200
     *
201
     * @param int    $user_id
202
     * @param string $user_type
203
     *
204
     * @return void
205
     * @throws UserNotExistsException
206
     */
207
    public function isMorph(int $user_id, string $user_type): void
208
    {
209
        $user = app($user_type)->/** @scrutinizer ignore-call */ where('id', $user_id)->first();
210
        if (is_null($user)) {
211
            throw new UserNotExistsException;
212
        }
213
    }
214
}
215