]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - application/api/ApiMiddleware.php
Optimize and cleanup imports
[github/shaarli/Shaarli.git] / application / api / ApiMiddleware.php
CommitLineData
18e67967 1<?php
18e67967
A
2namespace Shaarli\Api;
3
18e67967 4use Shaarli\Api\Exceptions\ApiAuthorizationException;
dea72c71 5use Shaarli\Api\Exceptions\ApiException;
813849e5 6use Shaarli\Config\ConfigManager;
18e67967
A
7use Slim\Container;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11/**
12 * Class ApiMiddleware
13 *
14 * This will be called before accessing any API Controller.
15 * Its role is to make sure that the API is enabled, configured, and to validate the JWT token.
16 *
17 * If the request is validated, the controller is called, otherwise a JSON error response is returned.
18 *
19 * @package Api
20 */
21class ApiMiddleware
22{
23 /**
24 * @var int JWT token validity in seconds (9 min).
25 */
26 public static $TOKEN_DURATION = 540;
27
28 /**
29 * @var Container: contains conf, plugins, etc.
30 */
31 protected $container;
32
33 /**
813849e5 34 * @var ConfigManager instance.
18e67967
A
35 */
36 protected $conf;
37
38 /**
39 * ApiMiddleware constructor.
40 *
41 * @param Container $container instance.
42 */
43 public function __construct($container)
44 {
45 $this->container = $container;
46 $this->conf = $this->container->get('conf');
47 $this->setLinkDb($this->conf);
48 }
49
50 /**
51 * Middleware execution:
52 * - check the API request
53 * - execute the controller
54 * - return the response
55 *
56 * @param Request $request Slim request
57 * @param Response $response Slim response
58 * @param callable $next Next action
59 *
60 * @return Response response.
61 */
62 public function __invoke($request, $response, $next)
63 {
64 try {
65 $this->checkRequest($request);
66 $response = $next($request, $response);
f211e417 67 } catch (ApiException $e) {
18e67967
A
68 $e->setResponse($response);
69 $e->setDebug($this->conf->get('dev.debug', false));
70 $response = $e->getApiResponse();
71 }
72
73 return $response;
74 }
75
76 /**
77 * Check the request validity (HTTP method, request value, etc.),
78 * that the API is enabled, and the JWT token validity.
79 *
80 * @param Request $request Slim request
81 *
82 * @throws ApiAuthorizationException The API is disabled or the token is invalid.
83 */
84 protected function checkRequest($request)
85 {
86 if (! $this->conf->get('api.enabled', true)) {
87 throw new ApiAuthorizationException('API is disabled');
88 }
89 $this->checkToken($request);
90 }
91
92 /**
93 * Check that the JWT token is set and valid.
94 * The API secret setting must be set.
95 *
96 * @param Request $request Slim request
97 *
98 * @throws ApiAuthorizationException The token couldn't be validated.
99 */
f211e417
V
100 protected function checkToken($request)
101 {
63ef5497 102 if (! $request->hasHeader('Authorization')) {
18e67967
A
103 throw new ApiAuthorizationException('JWT token not provided');
104 }
105
106 if (empty($this->conf->get('api.secret'))) {
107 throw new ApiAuthorizationException('Token secret must be set in Shaarli\'s administration');
108 }
109
63ef5497
V
110 $authorization = $request->getHeaderLine('Authorization');
111
112 if (! preg_match('/^Bearer (.*)/i', $authorization, $matches)) {
113 throw new ApiAuthorizationException('Invalid JWT header');
114 }
115
116 ApiUtils::validateJwtToken($matches[1], $this->conf->get('api.secret'));
18e67967
A
117 }
118
119 /**
120 * Instantiate a new LinkDB including private links,
121 * and load in the Slim container.
122 *
123 * FIXME! LinkDB could use a refactoring to avoid this trick.
124 *
813849e5 125 * @param ConfigManager $conf instance.
18e67967
A
126 */
127 protected function setLinkDb($conf)
128 {
f24896b2 129 $linkDb = new \Shaarli\Bookmark\LinkDB(
18e67967
A
130 $conf->get('resource.datastore'),
131 true,
132 $conf->get('privacy.hide_public_links'),
133 $conf->get('redirector.url'),
134 $conf->get('redirector.encode_url')
135 );
136 $this->container['db'] = $linkDb;
137 }
138}