import { S3, GetObjectCommand } from "@aws-sdk/client-s3"; import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; import { basename } from "node:path"; import { getServerEntry } from "../database/queries/server-queries.js"; import { ERR } from "../util/logging.js"; import { checkAuthorization } from "../database/queries/server-queries.js"; const s3Region = "us-east-1"; async function getS3BackupData(serverId) { const serverEntry = await getServerEntry(serverId); if (!serverEntry?.backupHost) return undefined; const s3Config = { credentials: { accessKeyId: serverEntry.backupId, secretAccessKey: serverEntry.backupKey, }, endpoint: `https://${serverEntry.backupHost}`, forcePathStyle: true, region: s3Region, }; const pathParts = serverEntry.backupPath.split("/"); if (pathParts[0] === "") pathParts.shift(); const bucket = pathParts.shift(); const backupPrefix = pathParts.join("/"); return { s3Config, bucket, backupPrefix }; } export async function listS3Backups(req, res) { const serverSpec = req.body; if (!serverSpec.id) return res.status(400).send("Server id missing!"); const authorized = await checkAuthorization(serverSpec.id, req.cairoId); if (!authorized) return res .status(403) .send("You do not have permission to access that server!"); const s3Data = await getS3BackupData(serverSpec.id); if (!s3Data) return res.status(409).send("Backup not configured!"); const { s3Config, bucket, backupPrefix } = s3Data; const s3Client = new S3(s3Config); try { const listResponse = await s3Client.listObjectsV2({ Bucket: bucket, Prefix: backupPrefix, }); const files = listResponse.Contents?.map((f) => ({ name: basename(f.Key), lastModified: f.LastModified, path: f.Key, size: f.Size, })) ?? []; res.json(files); } catch (e) { ERR("S3", e); res.sendStatus(500); } } export async function getS3BackupUrl(req, res) { const serverSpec = req.body; if (!serverSpec.id) return res.status(400).send("Server id missing!"); if (!serverSpec.backupPath) return res.status(400).send("Backup path missing!"); const authorized = await checkAuthorization(serverSpec.id, req.cairoId); if (!authorized) return res .status(403) .send("You do not have permission to access that server!"); const s3Data = await getS3BackupData(serverSpec.id); if (!s3Data) return res.status(409).send("Backup not configured!"); const { s3Config, bucket } = s3Data; const s3Client = new S3(s3Config); try { const command = new GetObjectCommand({ Bucket: bucket, Key: serverSpec.backupPath, }); const url = await getSignedUrl(s3Client, command, { expiresIn: 3600 }); res.json({ url }); } catch (e) { ERR("S3", e); res.sendStatus(500); } }