[FEATURE] S3 Backup View
This commit is contained in:
parent
1e5aef1038
commit
ccfc1abc8e
9 changed files with 959 additions and 931 deletions
74
lib/controllers/s3-controller.js
Normal file
74
lib/controllers/s3-controller.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
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";
|
||||
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 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 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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue