mirror of
https://github.com/nicotsx/zerobyte.git
synced 2026-06-12 18:39:24 -04:00
fix: force recovery key redownload after possible truncated download
This commit is contained in:
@@ -59,9 +59,9 @@ export function DownloadRecoveryKeyPage() {
|
||||
<AlertTriangle className="size-5" />
|
||||
<AlertTitle>Important: Save This File Securely</AlertTitle>
|
||||
<AlertDescription>
|
||||
Your Restic password is essential for recovering your backup data. If you lose access to this server
|
||||
without this file, your backups will be unrecoverable. Store it in a password manager or encrypted
|
||||
storage.
|
||||
Your Restic password is essential for recovering your backup data. If you previously downloaded this
|
||||
file, replace that saved copy with the new download. If you lose access to this server without this
|
||||
file, your backups will be unrecoverable. Store it in a password manager or encrypted storage.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { createServerFn } from "@tanstack/react-start";
|
||||
import { getCookie, getRequestHeaders } from "@tanstack/react-start/server";
|
||||
import { Layout } from "~/client/components/layout";
|
||||
@@ -39,6 +39,10 @@ export const Route = createFileRoute("/(dashboard)")({
|
||||
}),
|
||||
]);
|
||||
|
||||
if (authContext.user && !authContext.user.hasDownloadedResticPassword) {
|
||||
throw redirect({ to: "/download-recovery-key" });
|
||||
}
|
||||
|
||||
return authContext;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import { v00003 } from "./migrations/00003-assign-organization";
|
||||
import { v00004 } from "./migrations/00004-concat-path-name";
|
||||
import { v00005 } from "./migrations/00005-split-backup-include-paths";
|
||||
import { v00006 } from "./migrations/00006-map-smb-files-to-container-uid-gid";
|
||||
import { v00007 } from "./migrations/00007-require-recovery-key-redownload";
|
||||
import { sql } from "drizzle-orm";
|
||||
import { appMetadataTable, usersTable } from "../../db/schema";
|
||||
import { db } from "../../db/db";
|
||||
@@ -17,7 +18,12 @@ const recordMigrationCheckpoint = async (version: string): Promise<void> => {
|
||||
|
||||
await db
|
||||
.insert(appMetadataTable)
|
||||
.values({ key, value: JSON.stringify({ completedAt: new Date().toISOString() }), createdAt: now, updatedAt: now })
|
||||
.values({
|
||||
key,
|
||||
value: JSON.stringify({ completedAt: new Date().toISOString() }),
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: appMetadataTable.key,
|
||||
set: { value: JSON.stringify({ completedAt: new Date().toISOString() }), updatedAt: now },
|
||||
@@ -39,7 +45,7 @@ type MigrationEntity = {
|
||||
dependsOn?: string[];
|
||||
};
|
||||
|
||||
const registry: MigrationEntity[] = [v00001, v00002, v00003, v00004, v00005, v00006];
|
||||
const registry: MigrationEntity[] = [v00001, v00002, v00003, v00004, v00005, v00006, v00007];
|
||||
|
||||
export const runMigrations = async () => {
|
||||
const userCount = await db.select({ count: sql<number>`count(*)` }).from(usersTable);
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { and, eq, inArray } from "drizzle-orm";
|
||||
import { logger } from "@zerobyte/core/node";
|
||||
import { db } from "../../../db/db";
|
||||
import { account, member, usersTable } from "../../../db/schema";
|
||||
import { toMessage } from "~/server/utils/errors";
|
||||
|
||||
const execute = async () => {
|
||||
const errors: Array<{ name: string; error: string }> = [];
|
||||
|
||||
try {
|
||||
const affectedUsers = await db
|
||||
.select({ id: usersTable.id })
|
||||
.from(usersTable)
|
||||
.innerJoin(account, and(eq(account.userId, usersTable.id), eq(account.providerId, "credential")))
|
||||
.innerJoin(member, and(eq(member.userId, usersTable.id), inArray(member.role, ["owner", "admin"])))
|
||||
.where(eq(usersTable.hasDownloadedResticPassword, true));
|
||||
const affectedUserIds = [...new Set(affectedUsers.map((user) => user.id))];
|
||||
|
||||
if (affectedUserIds.length > 0) {
|
||||
await db
|
||||
.update(usersTable)
|
||||
.set({ hasDownloadedResticPassword: false })
|
||||
.where(inArray(usersTable.id, affectedUserIds));
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Migration 00007-require-recovery-key-redownload marked ${affectedUserIds.length} users for recovery key re-download.`,
|
||||
);
|
||||
} catch (error) {
|
||||
errors.push({
|
||||
name: "recovery-key-redownload",
|
||||
error: toMessage(error),
|
||||
});
|
||||
}
|
||||
|
||||
return { success: errors.length === 0, errors };
|
||||
};
|
||||
|
||||
export const v00007 = {
|
||||
execute,
|
||||
id: "00007-require-recovery-key-redownload",
|
||||
type: "maintenance" as const,
|
||||
};
|
||||
Reference in New Issue
Block a user