diff options
Diffstat (limited to 'application/front/ShaarliMiddleware.php')
-rw-r--r-- | application/front/ShaarliMiddleware.php | 83 |
1 files changed, 70 insertions, 13 deletions
diff --git a/application/front/ShaarliMiddleware.php b/application/front/ShaarliMiddleware.php index fa6c6467..c015c0c6 100644 --- a/application/front/ShaarliMiddleware.php +++ b/application/front/ShaarliMiddleware.php | |||
@@ -3,7 +3,7 @@ | |||
3 | namespace Shaarli\Front; | 3 | namespace Shaarli\Front; |
4 | 4 | ||
5 | use Shaarli\Container\ShaarliContainer; | 5 | use Shaarli\Container\ShaarliContainer; |
6 | use Shaarli\Front\Exception\ShaarliException; | 6 | use Shaarli\Front\Exception\UnauthorizedException; |
7 | use Slim\Http\Request; | 7 | use Slim\Http\Request; |
8 | use Slim\Http\Response; | 8 | use Slim\Http\Response; |
9 | 9 | ||
@@ -24,6 +24,8 @@ class ShaarliMiddleware | |||
24 | 24 | ||
25 | /** | 25 | /** |
26 | * Middleware execution: | 26 | * Middleware execution: |
27 | * - run updates | ||
28 | * - if not logged in open shaarli, redirect to login | ||
27 | * - execute the controller | 29 | * - execute the controller |
28 | * - return the response | 30 | * - return the response |
29 | * | 31 | * |
@@ -35,23 +37,78 @@ class ShaarliMiddleware | |||
35 | * | 37 | * |
36 | * @return Response response. | 38 | * @return Response response. |
37 | */ | 39 | */ |
38 | public function __invoke(Request $request, Response $response, callable $next) | 40 | public function __invoke(Request $request, Response $response, callable $next): Response |
39 | { | 41 | { |
42 | $this->initBasePath($request); | ||
43 | |||
40 | try { | 44 | try { |
41 | $response = $next($request, $response); | 45 | if (!is_file($this->container->conf->getConfigFileExt()) |
42 | } catch (ShaarliException $e) { | 46 | && !in_array($next->getName(), ['displayInstall', 'saveInstall'], true) |
43 | $this->container->pageBuilder->assign('message', $e->getMessage()); | 47 | ) { |
44 | if ($this->container->conf->get('dev.debug', false)) { | 48 | return $response->withRedirect($this->container->basePath . '/install'); |
45 | $this->container->pageBuilder->assign( | ||
46 | 'stacktrace', | ||
47 | nl2br(get_class($this) .': '. $e->getTraceAsString()) | ||
48 | ); | ||
49 | } | 49 | } |
50 | 50 | ||
51 | $response = $response->withStatus($e->getCode()); | 51 | $this->runUpdates(); |
52 | $response = $response->write($this->container->pageBuilder->render('error')); | 52 | $this->checkOpenShaarli($request, $response, $next); |
53 | |||
54 | return $next($request, $response); | ||
55 | } catch (UnauthorizedException $e) { | ||
56 | $returnUrl = urlencode($this->container->environment['REQUEST_URI']); | ||
57 | |||
58 | return $response->withRedirect($this->container->basePath . '/login?returnurl=' . $returnUrl); | ||
59 | } | ||
60 | // Other exceptions are handled by ErrorController | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * Run the updater for every requests processed while logged in. | ||
65 | */ | ||
66 | protected function runUpdates(): void | ||
67 | { | ||
68 | if ($this->container->loginManager->isLoggedIn() !== true) { | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | $this->container->updater->setBasePath($this->container->basePath); | ||
73 | $newUpdates = $this->container->updater->update(); | ||
74 | if (!empty($newUpdates)) { | ||
75 | $this->container->updater->writeUpdates( | ||
76 | $this->container->conf->get('resource.updates'), | ||
77 | $this->container->updater->getDoneUpdates() | ||
78 | ); | ||
79 | |||
80 | $this->container->pageCacheManager->invalidateCaches(); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * Access is denied to most pages with `hide_public_links` + `force_login` settings. | ||
86 | */ | ||
87 | protected function checkOpenShaarli(Request $request, Response $response, callable $next): bool | ||
88 | { | ||
89 | if (// if the user isn't logged in | ||
90 | !$this->container->loginManager->isLoggedIn() | ||
91 | // and Shaarli doesn't have public content... | ||
92 | && $this->container->conf->get('privacy.hide_public_links') | ||
93 | // and is configured to enforce the login | ||
94 | && $this->container->conf->get('privacy.force_login') | ||
95 | // and the current page isn't already the login page | ||
96 | // and the user is not requesting a feed (which would lead to a different content-type as expected) | ||
97 | && !in_array($next->getName(), ['login', 'atom', 'rss'], true) | ||
98 | ) { | ||
99 | throw new UnauthorizedException(); | ||
53 | } | 100 | } |
54 | 101 | ||
55 | return $response; | 102 | return true; |
103 | } | ||
104 | |||
105 | /** | ||
106 | * Initialize the URL base path if it hasn't been defined yet. | ||
107 | */ | ||
108 | protected function initBasePath(Request $request): void | ||
109 | { | ||
110 | if (null === $this->container->basePath) { | ||
111 | $this->container->basePath = rtrim($request->getUri()->getBasePath(), '/'); | ||
112 | } | ||
56 | } | 113 | } |
57 | } | 114 | } |