Skip to content

Commit 05ad11a

Browse files
committed
feat: RedirectToLogin now honors guest READ permission
1 parent fc06337 commit 05ad11a

1 file changed

Lines changed: 39 additions & 8 deletions

File tree

src/Middleware/RedirectToLogin.php

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Exception;
88
use Horde\Core\Config\State;
99
use Horde\Core\Horde;
10+
use Horde\Core\Service\PermissionService;
1011
use Psr\Http\Message\ResponseFactoryInterface;
1112
use Psr\Http\Message\ResponseInterface;
1213
use Psr\Http\Message\ServerRequestInterface;
@@ -17,42 +18,72 @@
1718
/**
1819
* RedirectToLogin middleware
1920
*
20-
* Purpose: Redirect to login if not authenticated
21+
* Purpose: Redirect to login if not authenticated or if the user lacks
22+
* top level read permission on the target app.
2123
*
2224
* Reads attribute:
2325
* - HORDE_AUTHENTICATED_USER the uid, if authenticated
26+
* - app the target application name
2427
*
2528
*/
2629
class RedirectToLogin implements MiddlewareInterface
2730
{
2831
private State $conf;
2932
private Horde_Registry $registry;
3033
private ResponseFactoryInterface $responseFactory;
31-
public function __construct(Horde_Registry $registry, ResponseFactoryInterface $responseFactory, State $conf)
32-
{
34+
private ?PermissionService $permissionService;
35+
36+
public function __construct(
37+
Horde_Registry $registry,
38+
ResponseFactoryInterface $responseFactory,
39+
State $conf,
40+
?PermissionService $permissionService = null,
41+
) {
3342
$this->registry = $registry;
3443
$this->responseFactory = $responseFactory;
3544
$this->conf = $conf;
45+
$this->permissionService = $permissionService;
3646
}
47+
3748
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
3849
{
39-
if ($request->getAttribute('HORDE_AUTHENTICATED_USER')) {
50+
$user = $request->getAttribute('HORDE_AUTHENTICATED_USER');
51+
$app = $request->getAttribute('app');
52+
53+
// Check app-level read permission if PermissionService is available
54+
if ($this->permissionService !== null && $app) {
55+
if ($this->permissionService->exists($app)) {
56+
// Pass empty string for guests — backend returns guest permissions
57+
$checkUser = $user ?: '';
58+
if (!$this->permissionService->hasPermission($app, $checkUser, ['read'])) {
59+
return $this->redirectToLogin($request);
60+
}
61+
// Permission granted — allow through even if not authenticated (guest read)
62+
return $handler->handle($request);
63+
}
64+
}
65+
66+
// No permission defined or no service — fall back to authentication check
67+
if ($user) {
4068
return $handler->handle($request);
4169
}
4270

71+
return $this->redirectToLogin($request);
72+
}
73+
74+
private function redirectToLogin(ServerRequestInterface $request): ResponseInterface
75+
{
4376
$requestUrl = (string) $request->getUri();
4477
$signedRequestUrl = Horde::signUrl($requestUrl);
4578

46-
// set baseurl: check if alternative login is set and use it as baseurl
4779
$configArray = $this->conf->toArray();
48-
$configArray['auth']['alternate_login'] ?? null;
80+
$alternateLogin = $configArray['auth']['alternate_login'] ?? null;
4981

5082
if (!empty($alternateLogin)) {
5183
$baseUrl = $alternateLogin;
5284
} else {
53-
// set baseurl: if no alternative login, use Horde login as baseurl
5485
$baseUrl = $this->registry->getServiceLink('login');
55-
};
86+
}
5687

5788
$redirectUrl = (string) Horde::url($baseUrl, true)->add('url', $signedRequestUrl);
5889

0 commit comments

Comments
 (0)