Completed
Push — master ( 57a157...155feb )
by Pavel
03:20 queued 01:21
created

Authentication::failNotAllowed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
1
<?php
2
3
namespace App\Middleware;
4
5
use App\Common\Acl;
6
use App\Common\Auth;
7
use App\Common\JsonException;
8
use App\Model\AccessToken;
9
10
use Psr\Http\Message\ServerRequestInterface;
11
use Psr\Http\Message\ResponseInterface;
12
13
class Authentication
14
{
15
    /**
16
     * @var Acl
17
     */
18
    private $acl;
19
20
    /**
21
     * @var
22
     */
23
    private $settings;
24
25
    /**
26
     * Authentication constructor.
27
     *
28
     * @param Acl $acl
29
     * @param     $settings
30
     */
31
    public function __construct(Acl $acl, $settings)
32
    {
33
        $this->acl      = $acl;
34
        $this->settings = $settings;
35
    }
36
37
    /**
38
     * Execute the middleware.
39
     *
40
     * @param ServerRequestInterface $request
41
     * @param ResponseInterface      $response
42
     * @param callable               $next
43
     *
44
     * @return ResponseInterface
45
     * @throws JsonException
46
     */
47
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
48
    {
49
        // Request has to have Authorization header
50
        if (!$request->getHeader('Authorization')) {
51
            throw new JsonException(null, 401, 'Not authorized', 'The user must be authorized');
52
        }
53
54
        // HTTP Authorization header available
55
        // Authorization: Bearer XXXXXXXXXXXXXXXXXXX
56
        // fetch XXXXXXXXXXXXX part
57
        $token = @explode(' ', @$request->getHeader('Authorization')[0]);
58
        $token = is_array($token) && (count($token) == 2) ? $token[1] : null;
59
        if (empty($token)) {
60
            throw new JsonException(null, 401, 'Not authorized', 'The user must be authorized');
61
        }
62
63
        // provided token must be valid
64
        if (!AccessToken::validateToken($token, $this->settings['accessToken'])) {
65
            throw new JsonException(null, 401, 'Not authorized', 'The user must be authorized');
66
        }
67
68
        // find user by token
69
        $user = AccessToken::getUserByToken($token);
70
        if (empty($user)) {
71
            throw new JsonException(null, 401, 'Not authorized', 'The user must be authorized');
72
        }
73
74
        Auth::setUser($user);
75
76
        $isAllowed = false;
77
        $route     = $request->getAttribute('route');
78
79
        if ($route) {
80
            // check access for the route
81
            $resource = Acl::buildResourceName(Acl::GUARD_TYPE_ROUTE, $route->getPattern());
82
            $privilege = Acl::getPrivilegeByHTTPMethod($request->getMethod());
83 View Code Duplication
            if ($this->acl->hasResource($resource)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
84
                $isAllowed = $isAllowed || $this->acl->isAllowed($user->role->name, $resource, $privilege);
85
            }
86
87
            // check access for the callable
88
            $resource = Acl::buildResourceName(Acl::GUARD_TYPE_CALLABLE, $route->getCallable());
89
            $privilege = null;
90 View Code Duplication
            if ($this->acl->hasResource($resource)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
91
                $isAllowed = $isAllowed || $this->acl->isAllowed($user->role->name, $resource, $privilege);
92
            }
93
94
            if (!$isAllowed) {
95
                throw new JsonException(null, 403, 'Not allowed', 'Access to this location is not allowed');
96
            }
97
        }
98
99
        // access allowed, move to next middleware
100
        return $next($request, $response);
101
    }
102
}
103