Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.45% covered (success)
95.45%
21 / 22
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
SignatureAccessTokenService
95.45% covered (success)
95.45%
21 / 22
66.67% covered (warning)
66.67%
2 / 3
9
0.00% covered (danger)
0.00%
0 / 1
 issueForSigner
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 publicUrl
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 resolve
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
6.03
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Signatures\Application\Services;
6
7use Illuminate\Support\Str;
8use ImovelZapAi\Signatures\Domain\Exceptions\SignatureException;
9use ImovelZapAi\Signatures\Infrastructure\Persistence\Eloquent\SignatureRequestModel;
10use ImovelZapAi\Signatures\Infrastructure\Persistence\Eloquent\SignerModel;
11
12final class SignatureAccessTokenService
13{
14    /** @return array{plain: string, url: string} */
15    public function issueForSigner(SignerModel $signer): array
16    {
17        $plain = Str::lower(Str::random(40));
18
19        $signer->forceFill([
20            'access_token_hash' => hash('sha256', $plain),
21            'access_token_prefix' => substr($plain, 0, 8),
22        ])->save();
23
24        return [
25            'plain' => $plain,
26            'url' => $this->publicUrl($plain),
27        ];
28    }
29
30    public function publicUrl(string $plain): string
31    {
32        $base = rtrim((string) (config('signatures.public_base_url') ?: config('app.url')), '/');
33
34        return $base.'/assinar/'.$plain;
35    }
36
37    /** @return array{signer: SignerModel, request: SignatureRequestModel} */
38    public function resolve(string $plain): array
39    {
40        $signer = SignerModel::query()
41            ->where('access_token_hash', hash('sha256', $plain))
42            ->first();
43
44        if ($signer === null) {
45            throw SignatureException::tokenInvalid();
46        }
47
48        $request = SignatureRequestModel::query()->whereKey($signer->signature_request_id)->first();
49        if ($request === null || ! $request->isOpen()) {
50            throw SignatureException::tokenInvalid();
51        }
52
53        if ($request->expires_at !== null && $request->expires_at->isPast()) {
54            throw SignatureException::tokenInvalid();
55        }
56
57        return ['signer' => $signer, 'request' => $request];
58    }
59}