Adds initial support for maintenance mode
parent
315b68f928
commit
08953c6272
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Core;
|
||||||
|
|
||||||
|
class Maintenance
|
||||||
|
{
|
||||||
|
public const FLAG_PATH = __DIR__ . '/../../storage/maintenance.flag';
|
||||||
|
|
||||||
|
public static function isEnabled(): bool
|
||||||
|
{
|
||||||
|
return file_exists(self::FLAG_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function enable(string $message = ''): bool
|
||||||
|
{
|
||||||
|
$dir = dirname(self::FLAG_PATH);
|
||||||
|
if (!is_dir($dir)) {
|
||||||
|
mkdir($dir, 0755, true);
|
||||||
|
}
|
||||||
|
$content = $message !== '' ? $message : 'Site is under maintenance';
|
||||||
|
return file_put_contents(self::FLAG_PATH, $content) !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function disable(): bool
|
||||||
|
{
|
||||||
|
if (file_exists(self::FLAG_PATH)) {
|
||||||
|
return unlink(self::FLAG_PATH);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getMessage(): string
|
||||||
|
{
|
||||||
|
if (!self::isEnabled()) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
$msg = @file_get_contents(self::FLAG_PATH);
|
||||||
|
return is_string($msg) ? trim($msg) : '';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Maintenance mode page
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<div class="container mt-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card border-warning">
|
||||||
|
<div class="card-header bg-warning text-dark">
|
||||||
|
<strong>Maintenance mode</strong>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="lead">The site is temporarily unavailable due to maintenance.</p>
|
||||||
|
<p class="text-muted">Please try again later.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -26,11 +26,29 @@ php scripts/migrate.php up
|
||||||
3. Typical deployment steps
|
3. Typical deployment steps
|
||||||
|
|
||||||
- Pull new code from git.
|
- Pull new code from git.
|
||||||
- Put the site in maintenance mode (optional, recommended for sensitive changes).
|
- Put the site in maintenance mode (recommended): `php scripts/maintenance.php on "Upgrading database"`.
|
||||||
- Run `php scripts/migrate.php status`.
|
- Run `php scripts/migrate.php status`.
|
||||||
- If there are pending migrations, run `php scripts/migrate.php up`.
|
- If there are pending migrations, run `php scripts/migrate.php up`.
|
||||||
|
- Disable maintenance mode: `php scripts/maintenance.php off`.
|
||||||
- Clear opcache if applicable and resume traffic.
|
- Clear opcache if applicable and resume traffic.
|
||||||
|
|
||||||
|
## Maintenance mode
|
||||||
|
|
||||||
|
Enable maintenance mode to temporarily block non-admin traffic during upgrades. Superusers (user ID 1 or with `superuser` right) can still access the site.
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Turn on with optional message
|
||||||
|
php scripts/maintenance.php on "Upgrading database"
|
||||||
|
|
||||||
|
# Turn off
|
||||||
|
php scripts/maintenance.php off
|
||||||
|
|
||||||
|
# Status
|
||||||
|
php scripts/maintenance.php status
|
||||||
|
```
|
||||||
|
|
||||||
## Authoring new migrations
|
## Authoring new migrations
|
||||||
|
|
||||||
1. Create a new SQL file in `doc/database/migrations/`, e.g.:
|
1. Create a new SQL file in `doc/database/migrations/`, e.g.:
|
||||||
|
|
|
@ -229,6 +229,30 @@ if (!$pipeline->run()) {
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maintenance mode: show maintenance page to non-superusers
|
||||||
|
try {
|
||||||
|
require_once __DIR__ . '/../app/core/Maintenance.php';
|
||||||
|
if (\App\Core\Maintenance::isEnabled()) {
|
||||||
|
$isSuperuser = false;
|
||||||
|
if ($validSession && isset($userId) && isset($userObject) && method_exists($userObject, 'hasRight')) {
|
||||||
|
// user 1 is always superuser per implementation, but also check explicit right
|
||||||
|
$isSuperuser = ($userId === 1) || (bool)$userObject->hasRight($userId, 'superuser');
|
||||||
|
}
|
||||||
|
if (!$isSuperuser) {
|
||||||
|
http_response_code(503);
|
||||||
|
// Show themed maintenance page
|
||||||
|
\App\Helpers\Theme::include('page-header');
|
||||||
|
\App\Helpers\Theme::include('page-menu');
|
||||||
|
include __DIR__ . '/../app/templates/maintenance.php';
|
||||||
|
\App\Helpers\Theme::include('page-footer');
|
||||||
|
ob_end_flush();
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
// Do not break app if maintenance check fails
|
||||||
|
}
|
||||||
|
|
||||||
// Apply per-user theme from DB into session (without persisting) once user is known
|
// Apply per-user theme from DB into session (without persisting) once user is known
|
||||||
if ($validSession && isset($userId) && isset($userObject) && is_object($userObject) && method_exists($userObject, 'getUserTheme')) {
|
if ($validSession && isset($userId) && isset($userObject) && is_object($userObject) && method_exists($userObject, 'getUserTheme')) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../app/core/Maintenance.php';
|
||||||
|
|
||||||
|
use App\Core\Maintenance;
|
||||||
|
|
||||||
|
function usage()
|
||||||
|
{
|
||||||
|
echo "\nJilo Web - Maintenance Mode\n";
|
||||||
|
echo "Usage:\n";
|
||||||
|
echo " php scripts/maintenance.php on [message] # Enable maintenance mode with optional message\n";
|
||||||
|
echo " php scripts/maintenance.php off # Disable maintenance mode\n";
|
||||||
|
echo " php scripts/maintenance.php status # Show maintenance status\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$cmd = $argv[1] ?? 'status';
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch ($cmd) {
|
||||||
|
case 'on':
|
||||||
|
$message = $argv[2] ?? '';
|
||||||
|
if (Maintenance::enable($message)) {
|
||||||
|
echo "Maintenance mode ENABLED" . ($message ? ": $message" : '') . "\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
fwrite(STDERR, "Failed to enable maintenance mode\n");
|
||||||
|
exit(1);
|
||||||
|
case 'off':
|
||||||
|
if (Maintenance::disable()) {
|
||||||
|
echo "Maintenance mode DISABLED\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
fwrite(STDERR, "Failed to disable maintenance mode\n");
|
||||||
|
exit(1);
|
||||||
|
case 'status':
|
||||||
|
default:
|
||||||
|
if (Maintenance::isEnabled()) {
|
||||||
|
$msg = Maintenance::getMessage();
|
||||||
|
echo "Maintenance: ON" . ($msg ? " - $msg" : '') . "\n";
|
||||||
|
} else {
|
||||||
|
echo "Maintenance: OFF\n";
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
fwrite(STDERR, "Error: " . $e->getMessage() . "\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
Loading…
Reference in New Issue