feat: Implement admin backup export and import functionality

- Added new endpoints for exporting and importing instance-level backups.
- Introduced user interface components for backup management in the web app.
- Enhanced import/export logic to handle attachments and provide detailed summaries.
- Updated localization files to include new strings related to backup features.
- Improved styling for backup-related UI elements.
This commit is contained in:
shuaiplus
2026-03-08 13:36:51 +08:00
parent 206b0be566
commit eeb477b84c
16 changed files with 1382 additions and 217 deletions
+17 -4
View File
@@ -99,6 +99,10 @@ import {
handleAdminSetUserStatus,
handleAdminDeleteUser,
} from './handlers/admin';
import {
handleAdminExportBackup,
handleAdminImportBackup,
} from './handlers/backup';
function isSameOriginWriteRequest(request: Request): boolean {
const targetOrigin = new URL(request.url).origin;
@@ -269,11 +273,12 @@ export async function handleRequest(request: Request, env: Env): Promise<Respons
try {
// Reject oversized bodies before any path-specific parsing.
// File upload paths enforce their own limits and are exempt here.
const isFileUploadPath =
// Large file/archive upload paths enforce their own limits and are exempt here.
const isLargeUploadPath =
/^\/api\/ciphers\/[a-f0-9-]+\/attachment\/[a-f0-9-]+$/i.test(path) ||
/^\/api\/sends\/[a-f0-9-]+\/file\/[a-f0-9-]+$/i.test(path);
if (!isFileUploadPath) {
/^\/api\/sends\/[a-f0-9-]+\/file\/[a-f0-9-]+$/i.test(path) ||
path === '/api/admin/backup/import';
if (!isLargeUploadPath) {
const contentLength = parseInt(request.headers.get('Content-Length') || '0', 10);
if (contentLength > LIMITS.request.maxBodyBytes) {
return errorResponse('Request body too large', 413);
@@ -771,6 +776,14 @@ export async function handleRequest(request: Request, env: Env): Promise<Respons
return handleAdminListUsers(request, env, currentUser);
}
if (path === '/api/admin/backup/export' && method === 'POST') {
return handleAdminExportBackup(request, env, currentUser);
}
if (path === '/api/admin/backup/import' && method === 'POST') {
return handleAdminImportBackup(request, env, currentUser);
}
if (path === '/api/admin/invites') {
if (method === 'GET') return handleAdminListInvites(request, env, currentUser);
if (method === 'POST') return handleAdminCreateInvite(request, env, currentUser);