Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
36 / 36 |
|
100.00% |
4 / 4 |
CRAP | |
100.00% |
1 / 1 |
RequestHandler | |
100.00% |
36 / 36 |
|
100.00% |
4 / 4 |
22 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
process | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
5 | |||
resolveRequestHandler | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
9 | |||
checkPermissions | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
7 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Engelsystem\Middleware; |
6 | |
7 | use Engelsystem\Application; |
8 | use Engelsystem\Controllers\BaseController; |
9 | use Engelsystem\Helpers\Authenticator; |
10 | use Engelsystem\Http\Exceptions\HttpForbidden; |
11 | use Illuminate\Support\Str; |
12 | use Psr\Http\Message\ResponseInterface; |
13 | use Psr\Http\Message\ServerRequestInterface; |
14 | use Psr\Http\Server\MiddlewareInterface; |
15 | use Psr\Http\Server\RequestHandlerInterface; |
16 | |
17 | class RequestHandler implements MiddlewareInterface |
18 | { |
19 | use ResolvesMiddlewareTrait; |
20 | |
21 | public function __construct(protected Application $container) |
22 | { |
23 | } |
24 | |
25 | /** |
26 | * Process an incoming server request and return a response, optionally delegating |
27 | * response creation to a handler. |
28 | * Implements basic permission checking if the controller supports it. |
29 | */ |
30 | public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface |
31 | { |
32 | $requestHandler = $request->getAttribute('route-request-handler'); |
33 | $this->container->instance(ServerRequestInterface::class, $request); |
34 | $this->container->instance('request', $request); |
35 | |
36 | /** @var CallableHandler|MiddlewareInterface|RequestHandlerInterface $requestHandler */ |
37 | $requestHandler = $this->resolveRequestHandler($requestHandler); |
38 | |
39 | if ($requestHandler instanceof CallableHandler) { |
40 | $callable = $requestHandler->getCallable(); |
41 | |
42 | if (is_array($callable) && $callable[0] instanceof BaseController) { |
43 | $this->checkPermissions($callable[0], $callable[1]); |
44 | } |
45 | } |
46 | |
47 | if ($requestHandler instanceof MiddlewareInterface) { |
48 | return $requestHandler->process($request, $handler); |
49 | } |
50 | |
51 | /** |
52 | * Is RequestHandlerInterface |
53 | * @see RequestHandlerInterface |
54 | */ |
55 | return $requestHandler->handle($request); |
56 | } |
57 | |
58 | /** |
59 | * Resolve the given class |
60 | */ |
61 | protected function resolveRequestHandler( |
62 | string|callable|MiddlewareInterface|RequestHandlerInterface $handler |
63 | ): MiddlewareInterface|RequestHandlerInterface { |
64 | if (is_string($handler) && mb_strpos($handler, '@') !== false) { |
65 | list($class, $method) = explode('@', $handler, 2); |
66 | if (!class_exists($class) && !$this->container->has($class)) { |
67 | $class = sprintf('Engelsystem\\Controllers\\%s', $class); |
68 | } |
69 | |
70 | $handler = [$class, $method]; |
71 | } |
72 | |
73 | if ( |
74 | is_array($handler) |
75 | && is_string($handler[0]) |
76 | && ( |
77 | class_exists($handler[0]) |
78 | || $this->container->has($handler[0]) |
79 | ) |
80 | ) { |
81 | $handler[0] = $this->container->make($handler[0]); |
82 | } |
83 | |
84 | return $this->resolveMiddleware($handler); |
85 | } |
86 | |
87 | /** |
88 | * Check required page permissions |
89 | */ |
90 | protected function checkPermissions(BaseController $controller, string $method): bool |
91 | { |
92 | /** @var Authenticator $auth */ |
93 | $auth = $this->container->get('auth'); |
94 | $permissions = $controller->getPermissions(); |
95 | |
96 | // Merge action permissions |
97 | if (isset($permissions[$method])) { |
98 | $permissions = array_merge($permissions, (array) $permissions[$method]); |
99 | } |
100 | |
101 | foreach ($permissions as $key => $permission) { |
102 | // Skip all action permission entries |
103 | if (!is_int($key)) { |
104 | continue; |
105 | } |
106 | |
107 | foreach ((array) $permission as $value) { |
108 | if ( |
109 | Str::contains($value, '||') |
110 | ? !$auth->canAny(explode('||', $value)) |
111 | : !$auth->can($permission) |
112 | ) { |
113 | throw new HttpForbidden(); |
114 | } |
115 | } |
116 | } |
117 | |
118 | return true; |
119 | } |
120 | } |