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",
|
"Select permissions": "Berechtigungen auswählen",
|
||||||
"No permissions available": "Keine Berechtigungen verfügbar",
|
"No permissions available": "Keine Berechtigungen verfügbar",
|
||||||
"No active permissions are configured yet.": "Es sind noch keine aktiven Berechtigungen konfiguriert.",
|
"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",
|
"Permission denied": "Keine Berechtigung",
|
||||||
"No active tenant assigned": "Kein aktiver Mandant zugewiesen",
|
"No active tenant assigned": "Kein aktiver Mandant zugewiesen",
|
||||||
"Please select at least one tenant": "Bitte mindestens einen Mandanten auswählen",
|
"Please select at least one tenant": "Bitte mindestens einen Mandanten auswählen",
|
||||||
|
|||||||
@@ -159,6 +159,7 @@
|
|||||||
"Select permissions": "Select permissions",
|
"Select permissions": "Select permissions",
|
||||||
"No permissions available": "No permissions available",
|
"No permissions available": "No permissions available",
|
||||||
"No active permissions are configured yet.": "No active permissions are configured yet.",
|
"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",
|
"Permission denied": "Permission denied",
|
||||||
"No active tenant assigned": "No active tenant assigned",
|
"No active tenant assigned": "No active tenant assigned",
|
||||||
"Please select at least one tenant": "Please select at least one tenant",
|
"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.
|
// Prevents messages from being cleared on the next render — useful when a redirect chain crosses multiple pages.
|
||||||
public static function keep(int $times = 1)
|
public static function keep(int $times = 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ class AuthzUiContractTest extends TestCase
|
|||||||
private function extractPageAuthKeys(string $content): array
|
private function extractPageAuthKeys(string $content): array
|
||||||
{
|
{
|
||||||
preg_match_all('/\\$pageAuth\\[[\'"]([a-z_]+)[\'"]\\]/', $content, $matches);
|
preg_match_all('/\\$pageAuth\\[[\'"]([a-z_]+)[\'"]\\]/', $content, $matches);
|
||||||
$keys = array_values(array_unique($matches[1] ?? []));
|
$keys = array_values(array_unique($matches[1]));
|
||||||
sort($keys);
|
sort($keys);
|
||||||
return $keys;
|
return $keys;
|
||||||
}
|
}
|
||||||
@@ -317,9 +317,9 @@ class AuthzUiContractTest extends TestCase
|
|||||||
{
|
{
|
||||||
$keys = [];
|
$keys = [];
|
||||||
preg_match_all('/\\$viewAuth\\[\'page\'\\]\\s*=\\s*\\[(.*?)\\];/s', $content, $blocks);
|
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);
|
preg_match_all('/[\'"]([a-z_]+)[\'"]\\s*=>/', $block, $matches);
|
||||||
foreach ($matches[1] ?? [] as $key) {
|
foreach ($matches[1] as $key) {
|
||||||
$keys[] = $key;
|
$keys[] = $key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,7 +348,7 @@ class AuthzUiContractTest extends TestCase
|
|||||||
);
|
);
|
||||||
|
|
||||||
preg_match_all('/[\'"]([a-z_]+)[\'"]\\s*=>/', (string) ($constantMatch[1] ?? ''), $keyMatches);
|
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);
|
sort($keys);
|
||||||
return $keys;
|
return $keys;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ if ($defaultLocale !== null) {
|
|||||||
if (empty($_SESSION['user']['id'])) {
|
if (empty($_SESSION['user']['id'])) {
|
||||||
$autoLoginResult = $rememberMeService->autoLoginFromCookie();
|
$autoLoginResult = $rememberMeService->autoLoginFromCookie();
|
||||||
if ($autoLoginResult) {
|
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),
|
// 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.
|
// honour ?return_to= so the user lands on the page they were on.
|
||||||
$returnToParam = trim((string) ($_GET['return_to'] ?? ''));
|
$returnToParam = trim((string) ($_GET['return_to'] ?? ''));
|
||||||
@@ -209,13 +213,13 @@ if (Router::getTemplateAction()) {
|
|||||||
}
|
}
|
||||||
if (ob_get_contents()) {
|
if (ob_get_contents()) {
|
||||||
ob_end_flush();
|
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);
|
trigger_error('MintyPHP template action"' . Router::getTemplateAction() . '" should not send output. Error raised ', E_USER_WARNING);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ob_end_clean();
|
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();
|
Session::end();
|
||||||
DB::close();
|
DB::close();
|
||||||
exit;
|
exit;
|
||||||
@@ -228,13 +232,13 @@ if (Router::getAction()) {
|
|||||||
}
|
}
|
||||||
if (ob_get_contents()) {
|
if (ob_get_contents()) {
|
||||||
ob_end_flush();
|
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);
|
trigger_error('MintyPHP action "' . Router::getAction() . '" should not send output. Error raised ', E_USER_WARNING);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ob_end_clean();
|
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();
|
Session::end();
|
||||||
DB::close();
|
DB::close();
|
||||||
exit;
|
exit;
|
||||||
|
|||||||
Reference in New Issue
Block a user