diff --git a/src/controllers/backup-controller.ts b/src/controllers/backup-controller.ts index cd23c43..7ae4ba3 100644 --- a/src/controllers/backup-controller.ts +++ b/src/controllers/backup-controller.ts @@ -16,6 +16,7 @@ import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; import { randomUUID } from "crypto"; import { getFile } from "../services/minio"; +import { sendWebSocket } from "../services/socket"; function getEnvVar(environmentName: string) { const environmentValue = process.env[environmentName]; @@ -55,9 +56,9 @@ function jsonParseOrPlainText(str: string) { } @Route("/api/v1/backup") -@Security("keycloak") export class BackupController extends Controller { @Get() + @Security("keycloak") async listBackup() { const data = await fetch( `${WINDMILL_URL}/api/w/${WINDMILL_WORKSPACE}/jobs/run_wait_result/p/${WINDMILL_BACKUP_LIST_SCRIPT_PATH}`, @@ -99,6 +100,7 @@ export class BackupController extends Controller { } @Get("backup-running-list") + @Security("keycloak") async runningBackupStatus() { return await fetch( `${WINDMILL_URL}/api/w/${WINDMILL_WORKSPACE}/jobs/list?running=true&script_path_exact=${WINDMILL_BACKUP_FLOW_PATH}`, @@ -116,6 +118,7 @@ export class BackupController extends Controller { } @Get("restore-running-list") + @Security("keycloak") async runningRestoreStatus() { return await fetch( `${WINDMILL_URL}/api/w/${WINDMILL_WORKSPACE}/jobs/list?running=true&script_path_exact=${WINDMILL_RESTORE_FLOW_PATH}`, @@ -126,7 +129,11 @@ export class BackupController extends Controller { } @Post("create") - async runBackup(@Body() body?: { name?: string }) { + @Security("keycloak") + async runBackup( + @Request() req: Request & { user: { sub: string } }, + @Body() body?: { name?: string }, + ) { const timestamp = Math.round(Date.now() / 1000); const name = body?.name && body.name !== "auto-backup" @@ -148,6 +155,7 @@ export class BackupController extends Controller { "Content-Type": "application/json", }, body: JSON.stringify({ + triggerUserId: req.user.sub, backup_name: name, storage: { s3_source_endpoint: s3TargetUrl, @@ -175,6 +183,7 @@ export class BackupController extends Controller { } @Get("download/{name}") + @Security("keycloak") async downloadBackup( @Request() req: express.Request, @Path() name: string, @@ -188,6 +197,7 @@ export class BackupController extends Controller { } @Post("restore") + @Security("keycloak") async restoreBackup(@Body() body: { name: string }) { const listRunning = await this.runningRestoreStatus(); @@ -230,6 +240,7 @@ export class BackupController extends Controller { } @Delete("delete") + @Security("keycloak") async deleteBackup(@Body() body: { name: string }) { await fetch( `${WINDMILL_URL}/api/w/${WINDMILL_WORKSPACE}/jobs/run/p/${WINDMILL_BACKUP_DELETE_SCRIPT_PATH}`, @@ -253,6 +264,7 @@ export class BackupController extends Controller { } @Get("schedule") + @Security("keycloak") async listSchedule() { const result = await fetch( `${WINDMILL_URL}/api/w/${WINDMILL_WORKSPACE}/schedules/list?path=${WINDMILL_BACKUP_FLOW_PATH}`, @@ -280,6 +292,7 @@ export class BackupController extends Controller { } @Post("schedule") + @Security("keycloak") async createSchedule( @Body() body: { name: string; schedule: string; timezone?: string; startAt?: Date }, ) { @@ -331,6 +344,7 @@ export class BackupController extends Controller { } @Put("schedule/{id}") + @Security("keycloak") async updateSchedule( @Path() id: string, @Body() @@ -401,6 +415,7 @@ export class BackupController extends Controller { } @Post("schedule/{id}/toggle") + @Security("keycloak") async toggleSchedule(@Path() id: string) { return await fetch( `${WINDMILL_URL}/api/w/${WINDMILL_WORKSPACE}/schedules/get/f/backup_schedule/${id}`, @@ -431,6 +446,7 @@ export class BackupController extends Controller { } @Delete("schedule/{id}") + @Security("keycloak") async deleteSchedule(@Path() id: string) { return await fetch( `${WINDMILL_URL}/api/w/${WINDMILL_WORKSPACE}/schedules/delete/f/backup_schedule/${id}`, @@ -443,4 +459,14 @@ export class BackupController extends Controller { }, ).then(async (r) => jsonParseOrPlainText(await r.text())); } + + @Post("notify-backup") + async notifyBackup( + @Body() payload: { message: string; userId?: string | string[]; roles?: string | string[] }, + ) { + sendWebSocket("backup-notification", payload.message, { + roles: payload.roles || [], + userId: payload.userId || [], + }); + } }