support snapshots
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import type {
|
||||
AdminDiagnosticsDto,
|
||||
BackupGuidanceDto,
|
||||
AdminPermissionOptionDto,
|
||||
AdminRoleDto,
|
||||
AdminRoleInput,
|
||||
AdminUserDto,
|
||||
AdminUserInput,
|
||||
SupportSnapshotDto,
|
||||
AuditEventDto,
|
||||
} from "@mrp/shared";
|
||||
import fs from "node:fs/promises";
|
||||
@@ -547,3 +549,76 @@ export async function getAdminDiagnostics(): Promise<AdminDiagnosticsDto> {
|
||||
recentAuditEvents: recentAuditEvents.map(mapAuditEvent),
|
||||
};
|
||||
}
|
||||
|
||||
export function getBackupGuidance(): BackupGuidanceDto {
|
||||
return {
|
||||
dataPath: paths.dataDir,
|
||||
databasePath: `${paths.prismaDir}/app.db`,
|
||||
uploadsPath: paths.uploadsDir,
|
||||
recommendedBackupTarget: "/mnt/user/backups/mrp-codex",
|
||||
backupSteps: [
|
||||
{
|
||||
id: "stop-app",
|
||||
label: "Stop writes before copying data",
|
||||
detail: "Stop the container or application process before copying the data directory so SQLite and attachments stay consistent.",
|
||||
},
|
||||
{
|
||||
id: "copy-data",
|
||||
label: "Back up the full data directory",
|
||||
detail: `Copy the full data directory at ${paths.dataDir}, not just the SQLite file, so uploads and attachments are preserved with the database.`,
|
||||
},
|
||||
{
|
||||
id: "retain-metadata",
|
||||
label: "Keep timestamps and structure",
|
||||
detail: "Preserve directory structure, filenames, and timestamps during backup so support recovery remains straightforward.",
|
||||
},
|
||||
{
|
||||
id: "record-build",
|
||||
label: "Record image/version context",
|
||||
detail: "Capture the deployed image tag or commit alongside the backup so schema and runtime expectations are clear during restore.",
|
||||
},
|
||||
],
|
||||
restoreSteps: [
|
||||
{
|
||||
id: "stop-target",
|
||||
label: "Stop the target app before restore",
|
||||
detail: "Do not restore into a running instance. Stop the target container or process before replacing the data directory.",
|
||||
},
|
||||
{
|
||||
id: "replace-data",
|
||||
label: "Restore the full data directory",
|
||||
detail: `Replace the target data directory with the backed-up copy so ${paths.prismaDir}/app.db and uploads come back together.`,
|
||||
},
|
||||
{
|
||||
id: "start-and-migrate",
|
||||
label: "Start the app and let migrations run",
|
||||
detail: "Restart the application after restore and allow the normal startup migration flow to complete before validation.",
|
||||
},
|
||||
{
|
||||
id: "validate-core",
|
||||
label: "Validate login, files, and PDFs",
|
||||
detail: "Confirm admin login, attachment access, and PDF generation after restore to verify the operational surface is healthy.",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export async function getSupportSnapshot(): Promise<SupportSnapshotDto> {
|
||||
const diagnostics = await getAdminDiagnostics();
|
||||
const [users, roles] = await Promise.all([
|
||||
prisma.user.findMany({
|
||||
where: { isActive: true },
|
||||
select: { email: true },
|
||||
orderBy: [{ email: "asc" }],
|
||||
}),
|
||||
prisma.role.count(),
|
||||
]);
|
||||
|
||||
return {
|
||||
generatedAt: new Date().toISOString(),
|
||||
diagnostics,
|
||||
userCount: diagnostics.userCount,
|
||||
roleCount: roles,
|
||||
activeUserEmails: users.map((user) => user.email),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user