improved restic repository operations log (prune, check, repair index etc.)
This commit is contained in:
3 files changed
+224
-85
No files matched your search
@@ -1,16 +1,17 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
import { authorize } from '$lib/server/authorize';
|
||||
import { requireBackups } from '$lib/server/backups/route-guards';
|
||||
import { auditBackupDestination } from '$lib/server/audit';
|
||||
import { getBackupDestination, getBackupConfigs } from '$lib/server/db';
|
||||
import { runRepoTask } from '$lib/server/backups';
|
||||
import { createJobResponse } from '$lib/server/sse';
|
||||
|
||||
export const POST: RequestHandler = async (event) => {
|
||||
const { params, request, cookies } = event;
|
||||
const auth = await authorize(cookies);
|
||||
if (auth.authEnabled && !await auth.can('backups', 'manage')) {
|
||||
return json({ error: 'Permission denied' }, { status: 403 });
|
||||
}
|
||||
const denied = await requireBackups(auth, 'manage');
|
||||
if (denied) return denied;
|
||||
|
||||
const destId = parseInt(params.id);
|
||||
if (isNaN(destId)) return json({ error: 'Invalid destination ID' }, { status: 400 });
|
||||
@@ -41,20 +42,33 @@ export const POST: RequestHandler = async (event) => {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// `task` is validated against the allowed list above.
|
||||
const result = await runRepoTask(destId, task as import('$lib/server/backups').RepoTask);
|
||||
// 'prune' and 'check' map to canonical audit actions; the rest land on
|
||||
// 'update' so they're still recoverable from the log.
|
||||
const action = task === 'prune' ? 'prune' : task === 'check' ? 'verify' : 'update';
|
||||
// 'prune' and 'check' map to canonical audit actions; the rest land on
|
||||
// 'update' so they're still recoverable from the log.
|
||||
const action = task === 'prune' ? 'prune' : task === 'check' ? 'verify' : 'update';
|
||||
|
||||
// Stream restic output live into the shared job/log modal (same channel as
|
||||
// backup/restore). Guards above (auth, env-scope, allowlist) already ran; only
|
||||
// the restic run is wrapped. `createJobResponse` keeps the backward-compat
|
||||
// synchronous JSON path for `Accept: application/json` callers (tests/CLI).
|
||||
return createJobResponse(async (send) => {
|
||||
let result: Awaited<ReturnType<typeof runRepoTask>>;
|
||||
try {
|
||||
// `task` is validated against the allowed list above.
|
||||
result = await runRepoTask(destId, task as import('$lib/server/backups').RepoTask, {
|
||||
onProgress: (message) => send('progress', { message })
|
||||
});
|
||||
} catch (error) {
|
||||
// A genuine throw (unexpected). Audit as failed, then rethrow so the job
|
||||
// ends in 'error' state.
|
||||
const msg = error instanceof Error ? error.message : String(error);
|
||||
await auditBackupDestination(event, 'update', destId, dest.name, { task, success: false, error: msg });
|
||||
throw error instanceof Error ? error : new Error(msg);
|
||||
}
|
||||
// runRepoTask can resolve with { success: false, error } WITHOUT throwing
|
||||
// (e.g. repo unreachable / needs init). Derive the audited success and
|
||||
// error from the result rather than hardcoding success (audit #53).
|
||||
// (e.g. repo unreachable / needs init). Derive the audited success/error
|
||||
// from the result rather than hardcoding success (audit #53).
|
||||
await auditBackupDestination(event, action, destId, dest.name, { task, success: result.success, error: result.error });
|
||||
return json(result, { status: result.success ? 200 : 500 });
|
||||
} catch (error) {
|
||||
const msg = error instanceof Error ? error.message : String(error);
|
||||
await auditBackupDestination(event, 'update', destId, dest.name, { task, success: false, error: msg });
|
||||
return json({ error: msg }, { status: 500 });
|
||||
}
|
||||
send('result', result);
|
||||
if (!result.success) throw new Error(result.error || `${task} failed`);
|
||||
}, request);
|
||||
};
|
||||
Reference in new issue
Block a user