4 use Shaarli\Api\Exceptions\ApiAuthorizationException
;
5 use Shaarli\Api\Exceptions\ApiException
;
6 use Shaarli\Config\ConfigManager
;
9 use Slim\Http\Response
;
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.
17 * If the request is validated, the controller is called, otherwise a JSON error response is returned.
24 * @var int JWT token validity in seconds (9 min).
26 public static $TOKEN_DURATION = 540;
29 * @var Container: contains conf, plugins, etc.
34 * @var ConfigManager instance.
39 * ApiMiddleware constructor.
41 * @param Container $container instance.
43 public function __construct($container)
45 $this->container
= $container;
46 $this->conf
= $this->container
->get('conf');
47 $this->setLinkDb($this->conf
);
51 * Middleware execution:
52 * - check the API request
53 * - execute the controller
54 * - return the response
56 * @param Request $request Slim request
57 * @param Response $response Slim response
58 * @param callable $next Next action
60 * @return Response response.
62 public function __invoke($request, $response, $next)
65 $this->checkRequest($request);
66 $response = $next($request, $response);
67 } catch (ApiException
$e) {
68 $e->setResponse($response);
69 $e->setDebug($this->conf
->get('dev.debug', false));
70 $response = $e->getApiResponse();
77 * Check the request validity (HTTP method, request value, etc.),
78 * that the API is enabled, and the JWT token validity.
80 * @param Request $request Slim request
82 * @throws ApiAuthorizationException The API is disabled or the token is invalid.
84 protected function checkRequest($request)
86 if (! $this->conf
->get('api.enabled', true)) {
87 throw new ApiAuthorizationException('API is disabled');
89 $this->checkToken($request);
93 * Check that the JWT token is set and valid.
94 * The API secret setting must be set.
96 * @param Request $request Slim request
98 * @throws ApiAuthorizationException The token couldn't be validated.
100 protected function checkToken($request)
102 if (! $request->hasHeader('Authorization')) {
103 throw new ApiAuthorizationException('JWT token not provided');
106 if (empty($this->conf
->get('api.secret'))) {
107 throw new ApiAuthorizationException('Token secret must be set in Shaarli\'s administration');
110 $authorization = $request->getHeaderLine('Authorization');
112 if (! preg_match('/^Bearer (.*)/i', $authorization, $matches)) {
113 throw new ApiAuthorizationException('Invalid JWT header');
116 ApiUtils
::validateJwtToken($matches[1], $this->conf
->get('api.secret'));
120 * Instantiate a new LinkDB including private links,
121 * and load in the Slim container.
123 * FIXME! LinkDB could use a refactoring to avoid this trick.
125 * @param ConfigManager $conf instance.
127 protected function setLinkDb($conf)
129 $linkDb = new \Shaarli\Bookmark\
LinkDB(
130 $conf->get('resource.datastore'),
132 $conf->get('privacy.hide_public_links'),
133 $conf->get('redirector.url'),
134 $conf->get('redirector.encode_url')
136 $this->container
['db'] = $linkDb;