fix: dismiss stale session-timeout flash on auto-login, resolve PHPStan and i18n issues
- Add Flash::dismissByKey() to clear flash messages by key+scope - Dismiss 'session_timeout' flash after successful remember-me auto-login so the message doesn't persist through manual logout - Suppress PHPStan false positives for dynamically defined MINTY_ALLOW_OUTPUT - Remove unnecessary ?? [] fallbacks on preg_match_all results in tests - Add missing i18n key 'No active roles are configured yet.' Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -159,6 +159,7 @@
|
||||
"Select permissions": "Berechtigungen auswählen",
|
||||
"No permissions available": "Keine Berechtigungen verfügbar",
|
||||
"No active permissions are configured yet.": "Es sind noch keine aktiven Berechtigungen konfiguriert.",
|
||||
"No active roles are configured yet.": "Es sind noch keine aktiven Rollen konfiguriert.",
|
||||
"Permission denied": "Keine Berechtigung",
|
||||
"No active tenant assigned": "Kein aktiver Mandant zugewiesen",
|
||||
"Please select at least one tenant": "Bitte mindestens einen Mandanten auswählen",
|
||||
|
||||
@@ -159,6 +159,7 @@
|
||||
"Select permissions": "Select permissions",
|
||||
"No permissions available": "No permissions available",
|
||||
"No active permissions are configured yet.": "No active permissions are configured yet.",
|
||||
"No active roles are configured yet.": "No active roles are configured yet.",
|
||||
"Permission denied": "Permission denied",
|
||||
"No active tenant assigned": "No active tenant assigned",
|
||||
"Please select at least one tenant": "Please select at least one tenant",
|
||||
|
||||
@@ -95,6 +95,30 @@ class Flash
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all flash messages matching a given key (and optionally scope).
|
||||
*/
|
||||
public static function dismissByKey(string $key, ?string $scope = null): void
|
||||
{
|
||||
self::ensureSession();
|
||||
$messages = $_SESSION[self::SESSION_KEY] ?? [];
|
||||
$messages = array_values(array_filter($messages, function ($message) use ($key, $scope) {
|
||||
if (($message['key'] ?? null) !== $key) {
|
||||
return true;
|
||||
}
|
||||
if ($scope !== null && ($message['scope'] ?? null) !== $scope) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
|
||||
if ($messages) {
|
||||
$_SESSION[self::SESSION_KEY] = $messages;
|
||||
} else {
|
||||
unset($_SESSION[self::SESSION_KEY]);
|
||||
}
|
||||
}
|
||||
|
||||
// Prevents messages from being cleared on the next render — useful when a redirect chain crosses multiple pages.
|
||||
public static function keep(int $times = 1)
|
||||
{
|
||||
|
||||
@@ -305,7 +305,7 @@ class AuthzUiContractTest extends TestCase
|
||||
private function extractPageAuthKeys(string $content): array
|
||||
{
|
||||
preg_match_all('/\\$pageAuth\\[[\'"]([a-z_]+)[\'"]\\]/', $content, $matches);
|
||||
$keys = array_values(array_unique($matches[1] ?? []));
|
||||
$keys = array_values(array_unique($matches[1]));
|
||||
sort($keys);
|
||||
return $keys;
|
||||
}
|
||||
@@ -317,9 +317,9 @@ class AuthzUiContractTest extends TestCase
|
||||
{
|
||||
$keys = [];
|
||||
preg_match_all('/\\$viewAuth\\[\'page\'\\]\\s*=\\s*\\[(.*?)\\];/s', $content, $blocks);
|
||||
foreach ($blocks[1] ?? [] as $block) {
|
||||
foreach ($blocks[1] as $block) {
|
||||
preg_match_all('/[\'"]([a-z_]+)[\'"]\\s*=>/', $block, $matches);
|
||||
foreach ($matches[1] ?? [] as $key) {
|
||||
foreach ($matches[1] as $key) {
|
||||
$keys[] = $key;
|
||||
}
|
||||
}
|
||||
@@ -348,7 +348,7 @@ class AuthzUiContractTest extends TestCase
|
||||
);
|
||||
|
||||
preg_match_all('/[\'"]([a-z_]+)[\'"]\\s*=>/', (string) ($constantMatch[1] ?? ''), $keyMatches);
|
||||
$keys = array_values(array_unique($keyMatches[1] ?? []));
|
||||
$keys = array_values(array_unique($keyMatches[1]));
|
||||
sort($keys);
|
||||
return $keys;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,10 @@ if ($defaultLocale !== null) {
|
||||
if (empty($_SESSION['user']['id'])) {
|
||||
$autoLoginResult = $rememberMeService->autoLoginFromCookie();
|
||||
if ($autoLoginResult) {
|
||||
// The session timeout flash is no longer relevant — the user was
|
||||
// seamlessly re-authenticated and never saw the login page.
|
||||
Flash::dismissByKey('session_timeout', 'login');
|
||||
|
||||
// After auto-login (e.g. session timeout with active remember-me cookie),
|
||||
// honour ?return_to= so the user lands on the page they were on.
|
||||
$returnToParam = trim((string) ($_GET['return_to'] ?? ''));
|
||||
@@ -209,13 +213,13 @@ if (Router::getTemplateAction()) {
|
||||
}
|
||||
if (ob_get_contents()) {
|
||||
ob_end_flush();
|
||||
if (!defined('MINTY_ALLOW_OUTPUT') || !MINTY_ALLOW_OUTPUT) {
|
||||
if (!defined('MINTY_ALLOW_OUTPUT') || !MINTY_ALLOW_OUTPUT) { // @phpstan-ignore booleanNot.alwaysFalse
|
||||
trigger_error('MintyPHP template action"' . Router::getTemplateAction() . '" should not send output. Error raised ', E_USER_WARNING);
|
||||
}
|
||||
} else {
|
||||
ob_end_clean();
|
||||
}
|
||||
if (defined('MINTY_ALLOW_OUTPUT') && MINTY_ALLOW_OUTPUT) {
|
||||
if (defined('MINTY_ALLOW_OUTPUT') && MINTY_ALLOW_OUTPUT) { // @phpstan-ignore booleanAnd.rightAlwaysTrue
|
||||
Session::end();
|
||||
DB::close();
|
||||
exit;
|
||||
@@ -228,13 +232,13 @@ if (Router::getAction()) {
|
||||
}
|
||||
if (ob_get_contents()) {
|
||||
ob_end_flush();
|
||||
if (!defined('MINTY_ALLOW_OUTPUT') || !MINTY_ALLOW_OUTPUT) {
|
||||
if (!defined('MINTY_ALLOW_OUTPUT') || !MINTY_ALLOW_OUTPUT) { // @phpstan-ignore booleanNot.alwaysFalse
|
||||
trigger_error('MintyPHP action "' . Router::getAction() . '" should not send output. Error raised ', E_USER_WARNING);
|
||||
}
|
||||
} else {
|
||||
ob_end_clean();
|
||||
}
|
||||
if (defined('MINTY_ALLOW_OUTPUT') && MINTY_ALLOW_OUTPUT) {
|
||||
if (defined('MINTY_ALLOW_OUTPUT') && MINTY_ALLOW_OUTPUT) { // @phpstan-ignore booleanAnd.rightAlwaysTrue
|
||||
Session::end();
|
||||
DB::close();
|
||||
exit;
|
||||
|
||||
Reference in New Issue
Block a user