Files
breadcrumb-the-shire/templates/default.phtml
fs e1c211069e fix(session): preserve intended URL across session timeout with remember-me
Session timeout redirected to /de/login?return_to=... but the remember-me
cookie was not cleared by logoutDueToSessionTimeout(). On the next request,
autoLoginFromCookie() silently re-logged the user in, causing the MintyPHP
router to resolve the login route to pages/index().php (dashboard) instead
of the login action — the intended URL redirect logic never executed.

Fix: intercept ?return_to= immediately after successful auto-login in
index.php and redirect to the sanitized route path. Also harden the login
flow with hidden return_to form fields and POST body fallback for cases
without remember-me.

Additional improvements in this commit:
- Convert stored REQUEST_URI to router-compatible path (strip leading
  slash and locale prefix) via IntendedUrlService::toRoutePath()
- Consolidate duplicate CSRF data attributes into shared data-csrf-key
  and data-csrf-token on <html> element
- Add tenant branding (logo) to auth pages via appAuthLogoUrl() helper

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 18:28:13 +01:00

95 lines
3.8 KiB
PHTML

<?php
use MintyPHP\Buffer;
use MintyPHP\Http\RequestContext;
use MintyPHP\Session;
$defaultTitle = appTitle();
$user = $_SESSION['user'] ?? [];
$theme = currentTheme();
$primaryVars = appPrimaryCssVars();
$csrfKey = Session::$csrfSessionKey;
$csrfToken = (string) ($_SESSION[$csrfKey] ?? '');
$isLoggedIn = !empty($user['id']);
$sessionIdleMinutes = (int) (appSetting('session_idle_timeout_minutes') ?? 30);
$sessionIdleSeconds = max($sessionIdleMinutes, 5) * 60;
$telemetryEnabled = frontendTelemetryEnabled();
$telemetrySampleRate = frontendTelemetrySampleRate();
$telemetryAllowedEvents = implode(',', frontendTelemetryAllowedEvents());
$telemetryUrl = lurl('admin/frontend-telemetry/ingest');
$pageRequestId = RequestContext::id();
$viewAuth = is_array($viewAuth ?? null) ? $viewAuth : [];
$viewAuth['layout'] = is_array($viewAuth['layout'] ?? null) ? $viewAuth['layout'] : [];
$pageTitle = $defaultTitle;
ob_start();
Buffer::get('title');
$bufferTitle = trim((string) ob_get_clean());
if ($bufferTitle !== '') {
$pageTitle = $bufferTitle . ' - ' . $defaultTitle;
}
?>
<!DOCTYPE html>
<html
data-theme="<?php e($theme); ?>"
data-contrast="normal"
data-asset-base="<?php e(asset('')); ?>"
data-request-id="<?php e($pageRequestId); ?>"
data-telemetry-url="<?php e($telemetryUrl); ?>"
data-telemetry-enabled="<?php e($telemetryEnabled ? '1' : '0'); ?>"
data-telemetry-sample-rate="<?php e((string) $telemetrySampleRate); ?>"
data-telemetry-allowed-events="<?php e($telemetryAllowedEvents); ?>"
data-csrf-key="<?php e($csrfKey); ?>"
data-csrf-token="<?php e($csrfToken); ?>"
<?php if ($isLoggedIn): ?>
data-session-idle-seconds="<?php e((string) $sessionIdleSeconds); ?>"
data-session-ping-url="<?php e(lurl('admin/session-ping/data')); ?>"
data-session-logout-url="<?php e(lurl('logout')); ?>"
<?php endif; ?>
class="no-js"
<?php if ($primaryVars !== ''): ?>style="<?php e($primaryVars); ?>" <?php endif; ?>
>
<head>
<script src="<?php e(assetVersion('js/app-boot.js')); ?>"></script>
<base href="<?php e(localeBase()); ?>">
<title><?php e($pageTitle); ?></title>
<meta property="og:site_name" content="<?php e($defaultTitle); ?>">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" sizes="32x32" href="<?php e(appFaviconUrl('favicon-32x32.png')); ?>">
<link rel="icon" type="image/png" sizes="16x16" href="<?php e(appFaviconUrl('favicon-16x16.png')); ?>">
<link rel="apple-touch-icon" href="<?php e(appFaviconUrl('apple-touch-icon.png')); ?>">
<link rel="manifest" href="<?php e(asset('favicon/site.webmanifest')); ?>">
<?php renderTemplateStyles('default'); ?>
<?php renderPageStyles(); ?>
</head>
<body>
<a class="app-skip-link" href="#app-main-content"><?php e(t('Skip to main content')); ?></a>
<div class="app-container">
<?php require __DIR__ . '/partials/app-main-aside-icon-bar.phtml'; ?>
<?php require __DIR__ . '/partials/app-main-aside.phtml'; ?>
<div class="app-main">
<main>
<?php require __DIR__ . '/partials/app-topbar.phtml'; ?>
<div id="app-main-content" class="app-main-content" tabindex="-1">
<?php require __DIR__ . '/partials/app-flash.phtml'; ?>
<?php Buffer::get('html'); ?>
</div>
</main>
<?php require __DIR__ . '/partials/app-footer.phtml'; ?>
</div>
</div>
<script src="<?php e(assetVersion('vendor/fslightbox/fslightbox.js')); ?>"></script>
<?php require __DIR__ . '/partials/app-confirm-dialog.phtml'; ?>
<?php if ($isLoggedIn): ?>
<?php require __DIR__ . '/partials/app-session-warning-dialog.phtml'; ?>
<script type="module" src="<?php e(assetVersion('js/components/app-session-warning.js')); ?>"></script>
<?php endif; ?>
<script type="module" src="<?php e(assetVersion('js/app-init.js')); ?>"></script>
</body>
</html>