Completed
Push — master ( d51485...4815df )
by yoshihiro
01:33
created

AuthenticationInterceptor::authenticate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Piotzkhider\FirebaseAuthenticationModule\Interceptor;
6
7
use Aura\Web\Request;
8
use BEAR\Resource\ResourceObject;
9
use Kreait\Firebase\Auth\UserRecord;
10
use Piotzkhider\FirebaseAuthenticationModule\Annotation\Authenticate;
11
use Piotzkhider\FirebaseAuthenticationModule\Exception\AuthenticationException;
12
use Piotzkhider\FirebaseAuthenticationModule\Exception\LogicException;
13
use Piotzkhider\FirebaseAuthenticationModule\Guard\AuthenticatorInterface;
14
use Ray\Aop\MethodInterceptor;
15
use Ray\Aop\MethodInvocation;
16
use Ray\Di\MethodInvocationProvider;
17
18
class AuthenticationInterceptor implements MethodInterceptor
19
{
20
    /**
21
     * @var AuthenticatorInterface
22
     */
23
    private $guard;
24
25
    /**
26
     * @var Request
27
     */
28
    private $request;
29
30
    /**
31
     * @var MethodInvocationProvider
32
     */
33
    private $invocationProvider;
34
35 1
    public function __construct(
36
        AuthenticatorInterface $guard,
37
        Request $request,
38
        MethodInvocationProvider $invocationProvider
39
    ) {
40 1
        $this->guard = $guard;
41 1
        $this->request = $request;
42 1
        $this->invocationProvider = $invocationProvider;
43 1
    }
44
45 1
    public function invoke(MethodInvocation $invocation)
46
    {
47 1
        $ro = $invocation->getThis();
48 1
        assert($ro instanceof ResourceObject);
49
50 1
        $annotation = $invocation->getMethod()->getAnnotation(Authenticate::class);
51 1
        assert($annotation instanceof Authenticate);
52
53
        try {
54 1
            $user = $this->authenticate();
55 1
            if ($annotation->user !== null) {
56 1
                $this->invocationProvider->set($invocation);
57 1
                $this->injectUser($invocation, $user);
58
            }
59
60 1
            return $invocation->proceed();
61
        } catch (AuthenticationException $e) {
62
            return $this->guard->onAuthenticationFailure($ro, $e);
63
        }
64
    }
65
66
    /**
67
     * @throws AuthenticationException
68
     */
69 1
    private function authenticate(): UserRecord
70
    {
71 1
        $token = $this->guard->getCredentials($this->request);
72
73 1
        return $this->guard->getUser($token);
74
    }
75
76 1
    private function injectUser(MethodInvocation $invocation, UserRecord $user): void
77
    {
78 1
        $method = $invocation->getMethod();
79 1
        $annotation = $method->getAnnotation(Authenticate::class);
80 1
        assert($annotation instanceof Authenticate);
81 1
        $parameters = $method->getParameters();
82 1
        $arguments = $invocation->getArguments()->getArrayCopy();
83
84 1
        foreach ($parameters as $parameter) {
85 1
            if ($parameter->getName() !== $annotation->user) {
86
                continue;
87
            }
88
            /** @var \ReflectionClass $hint */
89 1
            $hint = $parameter->getClass();
90 1
            if ($hint->getName() !== UserRecord::class) {
0 ignored issues
show
Bug introduced by
Consider using $hint->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
91
                throw new LogicException('User must be UserRecord.');
92
            }
93 1
            $pos = $parameter->getPosition();
94 1
            $arguments[$pos] = $user;
95
        }
96
97 1
        $invocation->getArguments()->exchangeArray($arguments);
98 1
    }
99
}
100