164 lines
6.6 KiB
PHP
164 lines
6.6 KiB
PHP
<?php
|
|
|
|
namespace routes;
|
|
|
|
use classes\authentication;
|
|
use classes\backup_store;
|
|
use classes\response;
|
|
use classes\router;
|
|
use objects\logs_o;
|
|
use Throwable;
|
|
use traits\route_t;
|
|
|
|
class moduleBackupsRoute
|
|
{
|
|
use route_t;
|
|
|
|
public function run(): void
|
|
{
|
|
global /** @var response $response */
|
|
/** @var router $router */
|
|
$router, $response;
|
|
|
|
$this->get('/modules/backup/backups', function () {
|
|
global $response;
|
|
$this->requireClassicSuperuserPermission('modules_backup_list');
|
|
try {
|
|
$response->success(
|
|
(new backup_store())->listBackups(
|
|
(int)($this->fromQuery('limit') ?? 50),
|
|
(int)($this->fromQuery('offset') ?? 0)
|
|
)
|
|
);
|
|
} catch (Throwable $throwable) {
|
|
$response->error(['message' => $throwable->getMessage()], 409);
|
|
}
|
|
}, [
|
|
'modules_backup_list' => 'List backup records, components, and legacy metadata',
|
|
]);
|
|
|
|
$this->post('/modules/backup/backups', function () {
|
|
global $response;
|
|
$this->requireClassicSuperuserPermission('modules_backup_create');
|
|
$user_id = $this->actorUserId();
|
|
try {
|
|
$parameters = $this->getParametersAsArray();
|
|
$result = (new backup_store())->enqueueCreateBackup(
|
|
$parameters['name'] ?? null,
|
|
$parameters['description'] ?? null,
|
|
$user_id,
|
|
'manual'
|
|
);
|
|
(new logs_o())->add('modules_backup', 'global', 1, $user_id ?? 0, 'MODULES_BACKUP', 'Queued backup: ' . $result['backup_uuid']);
|
|
$response->success($result);
|
|
} catch (Throwable $throwable) {
|
|
$response->error(['message' => $throwable->getMessage()], 409);
|
|
}
|
|
}, [
|
|
'modules_backup_create' => 'Queue a backup job',
|
|
]);
|
|
|
|
$this->get('/modules/backup/jobs/{id}', function () {
|
|
global $response;
|
|
$this->requireClassicSuperuserPermission('modules_backup_list');
|
|
$job_id = (int)$this->fromRoute('id');
|
|
$job = (new backup_store())->getJob($job_id);
|
|
if ($job === null) {
|
|
$response->error('Backup job not found.', 404);
|
|
}
|
|
$response->success($job);
|
|
}, [
|
|
'modules_backup_list' => 'View backup job status',
|
|
]);
|
|
|
|
$this->post('/modules/backup/backups/{backup_uuid}/verify', function () {
|
|
global $response;
|
|
$this->requireClassicSuperuserPermission('modules_backup_verify');
|
|
try {
|
|
$backup_uuid = (string)$this->fromRoute('backup_uuid');
|
|
$result = (new backup_store())->enqueueVerifyBackup($backup_uuid, $this->actorUserId());
|
|
(new logs_o())->add('modules_backup', 'global', 1, $this->actorUserId() ?? 0, 'MODULES_BACKUP_VERIFY', 'Queued backup verification: ' . $backup_uuid);
|
|
$response->success($result);
|
|
} catch (Throwable $throwable) {
|
|
$response->error(['message' => $throwable->getMessage()], 409);
|
|
}
|
|
}, [
|
|
'modules_backup_verify' => 'Verify a backup',
|
|
]);
|
|
|
|
$this->post('/modules/backup/backups/{backup_uuid}/restore/preview', function () {
|
|
global $response;
|
|
$this->requireClassicSuperuserPermission('modules_backup_restore');
|
|
try {
|
|
$backup_uuid = (string)$this->fromRoute('backup_uuid');
|
|
$result = (new backup_store())->previewRestore($backup_uuid, $this->actorUserId());
|
|
(new logs_o())->add('modules_backup', 'global', 1, $this->actorUserId() ?? 0, 'MODULES_BACKUP_RESTORE_PREVIEW', 'Previewed backup restore: ' . $backup_uuid);
|
|
$response->success($result);
|
|
} catch (Throwable $throwable) {
|
|
$response->error(['message' => $throwable->getMessage()], 409);
|
|
}
|
|
}, [
|
|
'modules_backup_restore' => 'Preview production restore from a backup',
|
|
]);
|
|
|
|
$this->post('/modules/backup/backups/{backup_uuid}/restore', function () {
|
|
global $response;
|
|
$this->requireClassicSuperuserPermission('modules_backup_restore');
|
|
try {
|
|
$parameters = $this->getParametersAsArray();
|
|
$backup_uuid = (string)$this->fromRoute('backup_uuid');
|
|
$result = (new backup_store())->enqueueRestore(
|
|
$backup_uuid,
|
|
(int)($parameters['preview_id'] ?? 0),
|
|
(string)($parameters['confirmation_phrase'] ?? ''),
|
|
(string)($parameters['reason'] ?? ''),
|
|
$this->actorUserId(),
|
|
[
|
|
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
|
|
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
|
|
]
|
|
);
|
|
(new logs_o())->add('modules_backup', 'global', 1, $this->actorUserId() ?? 0, 'MODULES_BACKUP_RESTORE', 'Queued backup restore: ' . $backup_uuid);
|
|
$response->success($result);
|
|
} catch (Throwable $throwable) {
|
|
$response->error(['message' => $throwable->getMessage()], 409);
|
|
}
|
|
}, [
|
|
'modules_backup_restore' => 'Execute production restore from a backup',
|
|
]);
|
|
|
|
$this->get('/modules/backup/restore-audit', function () {
|
|
global $response;
|
|
$this->requireClassicSuperuserPermission('modules_backup_restore');
|
|
try {
|
|
$response->success((new backup_store())->restoreAudit((int)($this->fromQuery('limit') ?? 50)));
|
|
} catch (Throwable $throwable) {
|
|
$response->error(['message' => $throwable->getMessage()], 409);
|
|
}
|
|
}, [
|
|
'modules_backup_restore' => 'View backup restore audit log',
|
|
]);
|
|
}
|
|
|
|
private function requireClassicSuperuserPermission(string $permission): bool
|
|
{
|
|
global $response;
|
|
|
|
if ((new authentication())->get_subuser() !== false) {
|
|
$response->error('Subuser sessions cannot manage backup disaster recovery.', 403);
|
|
}
|
|
|
|
return $this->requirePermission($permission);
|
|
}
|
|
|
|
private function actorUserId(): ?int
|
|
{
|
|
try {
|
|
$user = (new authentication())->get_user();
|
|
return $user !== false && isset($user->id) ? (int)$user->id : null;
|
|
} catch (Throwable) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|