feat(maintenance): per-message choke to freeze non-admins during platform maintenance
Read the shared platform:maintenance DB-cache flag at controll_message (after
auth resolves) and refuse every controller event for non-admins with
{message, maintenance:true}, so a host app can run a deploy / write-locking
migration without clients mutating state. Admins bypass to smoke-test. The key
is hardcoded to match App\Support\Maintenance::CACHE_KEY and dodge the
fork-child package-config-merge gap; cache reads are guarded so a hiccup can
never wedge the socket.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ed15ef8c23
commit
b678a25a3c
|
|
@ -51,6 +51,34 @@ class Controller
|
||||||
*/
|
*/
|
||||||
public function unboot(): void {}
|
public function unboot(): void {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared platform-maintenance flag, read from the same DB-cache key the host
|
||||||
|
* app writes via App\Support\Maintenance::CACHE_KEY. Hardcoded (not config)
|
||||||
|
* to dodge the fork-child package-config-merge gap, and wrapped so a cache
|
||||||
|
* hiccup can never wedge the socket. Keep the key string in sync with the app.
|
||||||
|
*/
|
||||||
|
protected static function maintenanceActive(): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return (bool) cache()->get('platform:maintenance', false);
|
||||||
|
} catch (\Throwable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function maintenanceMessage(): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$message = cache()->get('platform:maintenance:message');
|
||||||
|
} catch (\Throwable) {
|
||||||
|
$message = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_string($message) && $message !== ''
|
||||||
|
? $message
|
||||||
|
: 'We are performing scheduled maintenance and will be back shortly.';
|
||||||
|
}
|
||||||
|
|
||||||
public static function controll_message(
|
public static function controll_message(
|
||||||
ConnectionInterface $connection,
|
ConnectionInterface $connection,
|
||||||
PrivateChannel|Channel|PresenceChannel $channel,
|
PrivateChannel|Channel|PresenceChannel $channel,
|
||||||
|
|
@ -133,6 +161,21 @@ class Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Platform maintenance freeze. Once auth (incl. the self-heal above)
|
||||||
|
// has resolved the user, refuse every controller event for non-admins
|
||||||
|
// so a deploy/migration can run without clients mutating state. Admins
|
||||||
|
// bypass to smoke-test. The `auth` handshake + channel introspection
|
||||||
|
// are single-part events handled earlier, so a maintainer can still
|
||||||
|
// authenticate to obtain the bypass.
|
||||||
|
if (self::maintenanceActive() && ! ($connection->user?->is_admin ?? false)) {
|
||||||
|
$controller->error([
|
||||||
|
'message' => self::maintenanceMessage(),
|
||||||
|
'maintenance' => true,
|
||||||
|
]);
|
||||||
|
$controller->unboot();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (! method_exists($controllerClass, $method)) {
|
if (! method_exists($controllerClass, $method)) {
|
||||||
$controller->error('Event could not be handled');
|
$controller->error('Event could not be handled');
|
||||||
$controller->unboot();
|
$controller->unboot();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue