You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

58 lines
2.0 KiB

  1. import { NextResponse } from 'next/server';
  2. import { mkdir, writeFile, rm } from 'node:fs/promises';
  3. import path from 'node:path';
  4. import crypto from 'node:crypto';
  5. import { checkSystemBin } from '@/lib/system-bins';
  6. import { restoreFromZipFile } from '@/lib/restore-zip';
  7. export const dynamic = 'force-dynamic';
  8. export const maxDuration = 600;
  9. const PROJECT_ROOT = process.cwd();
  10. const UPLOAD_STAGING = path.join(PROJECT_ROOT, '.restore-staging');
  11. export async function POST(request: Request) {
  12. if (!(await checkSystemBin('unzip', '-v'))) {
  13. return NextResponse.json(
  14. { error: "Restore is unavailable: the 'unzip' command is not installed on the server. Ask the administrator to install it." },
  15. { status: 503 },
  16. );
  17. }
  18. const sessionId = crypto.randomUUID();
  19. const sessionDir = path.join(UPLOAD_STAGING, `upload-${sessionId}`);
  20. const zipPath = path.join(sessionDir, 'backup.zip');
  21. try {
  22. const formData = await request.formData();
  23. const file = formData.get('file') as File | null;
  24. if (!file) {
  25. return NextResponse.json(
  26. { error: 'No backup file was received. Choose a .zip backup file before clicking Restore.' },
  27. { status: 400 },
  28. );
  29. }
  30. await mkdir(sessionDir, { recursive: true });
  31. await writeFile(zipPath, Buffer.from(await file.arrayBuffer()));
  32. const result = await restoreFromZipFile(zipPath);
  33. if (!result.ok) {
  34. return NextResponse.json({ error: result.error, detail: result.detail }, { status: result.status });
  35. }
  36. return NextResponse.json({
  37. ok: true,
  38. restored: { cards: result.cards, portals: result.portals },
  39. previousDataBackup: result.previousBackup,
  40. });
  41. } catch (error) {
  42. console.error('Restore error:', error);
  43. return NextResponse.json(
  44. { error: 'Unexpected error during restore. Existing data was not changed. Check the server logs for details and try again.' },
  45. { status: 500 },
  46. );
  47. } finally {
  48. try { await rm(sessionDir, { recursive: true, force: true }); } catch { /* ignore */ }
  49. }
  50. }