Files
api/services/nginx/app/routes/superuserReplicationRoute.php
T

140 lines
5.5 KiB
PHP

<?php
namespace routes;
use classes\authentication;
use classes\replication_manager;
use traits\route_t;
class superuserReplicationRoute
{
use route_t;
private const RETIRED_MANAGEMENT_MESSAGE = 'Replication management has been retired. Use System -> Database, System -> Redis, and System -> MinIO for read-only status.';
public function run(): void
{
$this->get('/superuser/replication', function () {
global $response;
$this->requireClassicSuperuserPermission('superuser_replication_view');
$refresh = $this->toBool($this->getParameter('refresh'), false);
$response->success((new replication_manager())->summary($refresh));
}, [
'superuser_replication_view' => 'View database, Redis, and MinIO replication topology and status',
]);
$this->post('/superuser/replication/databases', function () {
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
'superuser_replication_manage' => 'Add and manage database replication host credentials',
]);
$this->post('/superuser/replication/redis', function () {
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
'superuser_replication_manage' => 'Add and manage Redis replication host credentials',
]);
$this->post('/superuser/replication/minio', function () {
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
'superuser_replication_manage' => 'Add and manage MinIO replication host credentials',
]);
$this->post('/superuser/replication/compose-template', function () {
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
'superuser_replication_manage' => 'Generate Docker Compose templates for replication-ready database, Redis, and MinIO hosts',
]);
$this->post('/superuser/replication/test-credentials', function () {
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
'superuser_replication_manage' => 'Test database, Redis, and MinIO replication host credentials before saving them',
]);
$this->post('/superuser/replication/{kind}/{id}/test', function () {
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
'superuser_replication_manage' => 'Validate database, Redis, and MinIO replication host connectivity and privileges',
]);
$this->post('/superuser/replication/{kind}/{id}/provision', function () {
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
'superuser_replication_manage' => 'Provision a database, Redis, or MinIO host as a replica of the current primary',
]);
$this->post('/superuser/replication/{kind}/{id}/promote', function () {
$this->requireClassicSuperuserPermission('superuser_replication_promote');
$this->rejectRetiredManagement();
}, [
'superuser_replication_promote' => 'Promote a healthy caught-up database, Redis, or MinIO replica to primary',
]);
$this->patch('/superuser/replication/{kind}/{id}', function () {
$this->requireClassicSuperuserPermission('superuser_replication_manage');
$this->rejectRetiredManagement();
}, [
'superuser_replication_manage' => 'Rename database, Redis, and MinIO replication hosts',
]);
$this->delete('/superuser/replication/{kind}/{id}', function () {
$this->requireClassicSuperuserPermission('superuser_replication_remove');
$this->rejectRetiredManagement();
}, [
'superuser_replication_remove' => 'Remove inactive prior hosts and unhealthy database, Redis, or MinIO replicas',
]);
}
/**
* Replication controls alter infrastructure state and must only be used by
* a classic superuser session. Subuser bearer tokens can carry a delegated
* customer context via X-Customer-Number, so do not allow them to fall back
* to plain string user permission checks for these routes.
*/
private function requireClassicSuperuserPermission(string $permission): bool
{
global $response;
if ((new authentication())->get_subuser() !== false) {
$response->error('Subuser sessions cannot manage replication.', 403);
}
return $this->requirePermission($permission);
}
private function rejectRetiredManagement(): void
{
global $response;
$response->error(['message' => self::RETIRED_MANAGEMENT_MESSAGE], 410);
}
private function toBool(mixed $value, bool $default): bool
{
if (is_bool($value)) {
return $value;
}
if ($value === null) {
return $default;
}
$normalized = strtolower(trim((string)$value));
if (in_array($normalized, ['1', 'true', 'yes', 'on'], true)) {
return true;
}
if (in_array($normalized, ['0', 'false', 'no', 'off'], true)) {
return false;
}
return $default;
}
}