Completed
Push — master ( 5cc45f...cc9f19 )
by Pavel
14s
created

Authentication::failNotAuthorized()   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
            return $this->failNotAuthorized();
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
            return $this->failNotAuthorized();
61
        }
62
63
        // provided token must be valid
64
        if (!AccessToken::validateToken($token, $this->settings['params']['allowHosts'])) {
65
            return $this->failNotAuthorized();
66
        }
67
68
        // find user by token
69
        $user = AccessToken::getUserByToken($token);
70
        if (empty($user)) {
71
            return $this->failNotAuthorized();
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
                // access is not allowed
96
                return $this->failNotAllowed();
97
            }
98
        }
99
100
        // access allowed, move to next middleware
101
        return $next($request, $response);
102
    }
103
104
    /**
105
     * Produce HTTP 401 Not authorized
106
     *
107
     * @throws JsonException
108
     */
109
    protected function failNotAuthorized()
110
    {
111
        throw new JsonException(null, 401, 'Not authorized', 'The user must be authorized');
112
    }
113
114
    /**
115
     * Produce HTTP 403 Not allowed
116
     *
117
     * @throws JsonException
118
     */
119
    protected function failNotAllowed()
120
    {
121
        throw new JsonException(null, 403, 'Not allowed', ' Access to this location is not allowed');
122
    }
123
}
124