mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
refactor: API route for backup/restore
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {toast} from "sonner";
|
||||
|
||||
import {FormControl, FormField, FormItem, FormLabel, FormMessage, useZodForm} from "@/components/ui/form";
|
||||
import {Input} from "@/components/ui/input";
|
||||
import {Form} from "@/components/ui/form";
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import {useRouter} from "next/navigation";
|
||||
import {Info} from "lucide-react";
|
||||
import {useMutation} from "@tanstack/react-query";
|
||||
import {toast} from "sonner";
|
||||
|
||||
import {Card, CardContent, CardHeader} from "@/components/ui/card";
|
||||
import {FormControl, FormField, FormItem, FormLabel, FormMessage, useZodForm} from "@/components/ui/form";
|
||||
import {Input} from "@/components/ui/input";
|
||||
import {CardContent, CardHeader} from "@/components/ui/card";
|
||||
import {Form} from "@/components/ui/form";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {TooltipProvider, TooltipTrigger, Tooltip, TooltipContent} from "@/components/ui/tooltip";
|
||||
import {RegisterSchema, RegisterType} from "@/components/wrappers/auth/register/register-form/register-form.schema";
|
||||
import {PasswordInput} from "@/components/ui/password-input";
|
||||
import {signUp} from "@/lib/auth/auth-client";
|
||||
import Link from "next/link";
|
||||
import {useZodForm} from "@/components/ui/form";
|
||||
import {CardAuth} from "@/features/layout/card-auth";
|
||||
import {FormField} from "@/components/ui/form";
|
||||
import {FormItem} from "@/components/ui/form";
|
||||
import {FormLabel} from "@/components/ui/form";
|
||||
import {FormControl} from "@/components/ui/form";
|
||||
import {FormMessage} from "@/components/ui/form";
|
||||
import {Input} from "@/components/ui/input";
|
||||
import {PasswordInput} from "@/components/ui/password-input";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import Link from "next/link";
|
||||
import {Info} from "lucide-react";
|
||||
|
||||
export type registerFormProps = {
|
||||
defaultValues?: RegisterType;
|
||||
@@ -26,9 +30,11 @@ export const RegisterForm = (props: registerFormProps) => {
|
||||
const form = useZodForm({
|
||||
schema: RegisterSchema,
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const mutation = useMutation({
|
||||
mutationFn: async (values: RegisterType) => {
|
||||
// @ts-ignore
|
||||
await signUp.email(values, {
|
||||
onSuccess: () => {
|
||||
toast.success(`Account successfully created`);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"use client"
|
||||
import {BackupWith} from "@/db/schema/07_database";
|
||||
import {BackupWith, Restoration} from "@/db/schema/07_database";
|
||||
import React, {useState} from "react";
|
||||
import {Swiper, SwiperSlide} from "swiper/react";
|
||||
|
||||
@@ -7,7 +7,7 @@ import "swiper/css";
|
||||
import "swiper/css/pagination";
|
||||
|
||||
import {Pagination, Mousewheel} from "swiper/modules";
|
||||
import {DatabaseActionKind} from "@/components/wrappers/dashboard/database/backup/backup-modal-context";
|
||||
import {DatabaseActionKind, useBackupModal} from "@/components/wrappers/dashboard/database/backup/backup-modal-context";
|
||||
import {Form, FormControl, FormField, FormItem, FormLabel, FormMessage, useZodForm} from "@/components/ui/form";
|
||||
import {
|
||||
BackupActionsSchema,
|
||||
@@ -22,8 +22,14 @@ import {truncateWords} from "@/utils/text";
|
||||
import {useIsMobile} from "@/hooks/use-mobile";
|
||||
import {Badge} from "@/components/ui/badge";
|
||||
import {getStatusColor, getStatusIcon} from "@/components/wrappers/dashboard/admin/notifications/logs/columns";
|
||||
import {downloadBackupAction} from "@/components/wrappers/dashboard/database/backup/actions/backup-actions.action";
|
||||
import {
|
||||
createRestorationBackupAction,
|
||||
downloadBackupAction
|
||||
} from "@/components/wrappers/dashboard/database/backup/actions/backup-actions.action";
|
||||
import {toast} from "sonner";
|
||||
import {SafeActionResult} from "next-safe-action";
|
||||
import {ServerActionResult} from "@/types/action-type";
|
||||
import {ZodString} from "zod";
|
||||
|
||||
type BackupActionsFormProps = {
|
||||
backup: BackupWith;
|
||||
@@ -32,6 +38,7 @@ type BackupActionsFormProps = {
|
||||
|
||||
export const BackupActionsForm = ({backup, action}: BackupActionsFormProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
const {closeModal} = useBackupModal();
|
||||
|
||||
const form = useZodForm({
|
||||
schema: BackupActionsSchema,
|
||||
@@ -39,18 +46,38 @@ export const BackupActionsForm = ({backup, action}: BackupActionsFormProps) => {
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: async (values: BackupActionsType) => {
|
||||
// implement your mutation logic here
|
||||
console.log(values);
|
||||
|
||||
const result = await downloadBackupAction({backupStorageId: values.backupStorageId})
|
||||
let result: SafeActionResult<string, ZodString, readonly [], {
|
||||
_errors?: string[] | undefined;
|
||||
}, readonly [], ServerActionResult<string | Restoration>, object> | undefined
|
||||
|
||||
|
||||
if (action === "download") {
|
||||
result = await downloadBackupAction({backupStorageId: values.backupStorageId})
|
||||
} else if (action === "restore") {
|
||||
result = await createRestorationBackupAction({
|
||||
databaseId: backup.databaseId,
|
||||
backupStorageId: values.backupStorageId,
|
||||
backupId: backup.id
|
||||
})
|
||||
}
|
||||
|
||||
const inner = result?.data;
|
||||
|
||||
console.log(inner);
|
||||
|
||||
|
||||
if (inner?.success) {
|
||||
toast.success(inner.actionSuccess?.message);
|
||||
|
||||
if (action === "download") {
|
||||
console.log(inner.value)
|
||||
const url = inner.value
|
||||
if (typeof url === "string") {
|
||||
window.open(url, "_self");
|
||||
}
|
||||
closeModal()
|
||||
} else if (action === "restore") {
|
||||
closeModal()
|
||||
}
|
||||
|
||||
} else {
|
||||
toast.error(inner?.actionError?.message);
|
||||
}
|
||||
@@ -146,7 +173,8 @@ export const BackupActionsForm = ({backup, action}: BackupActionsFormProps) => {
|
||||
)}
|
||||
/>
|
||||
<div className="flex flex-col items-center gap-y-6 w-full">
|
||||
<ButtonWithLoading className="mt-2 w-full" isPending={mutation.isPending} disabled={mutation.isPending }>
|
||||
<ButtonWithLoading className="mt-2 w-full" isPending={mutation.isPending}
|
||||
disabled={mutation.isPending}>
|
||||
Confirm
|
||||
</ButtonWithLoading>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@ import {dispatchStorage} from "@/features/storages/dispatch";
|
||||
import {db} from "@/db";
|
||||
import {eq} from "drizzle-orm";
|
||||
import * as drizzleDb from "@/db";
|
||||
import {Restoration} from "@/db/schema/07_database";
|
||||
|
||||
|
||||
export const downloadBackupAction = userAction.schema(
|
||||
@@ -32,9 +33,6 @@ export const downloadBackupAction = userAction.schema(
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
console.log(backupStorage);
|
||||
|
||||
if (backupStorage.status != "success" || !backupStorage.path) {
|
||||
return {
|
||||
success: false,
|
||||
@@ -56,8 +54,6 @@ export const downloadBackupAction = userAction.schema(
|
||||
|
||||
const result = await dispatchStorage(input, undefined, backupStorage.storageChannelId);
|
||||
|
||||
console.log(result);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: result.url,
|
||||
@@ -78,4 +74,49 @@ export const downloadBackupAction = userAction.schema(
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
export const createRestorationBackupAction = userAction
|
||||
.schema(
|
||||
z.object({
|
||||
backupId: z.string(),
|
||||
databaseId: z.string(),
|
||||
backupStorageId: z.string(),
|
||||
})
|
||||
)
|
||||
.action(async ({parsedInput}): Promise<ServerActionResult<Restoration>> => {
|
||||
try {
|
||||
const restorationData = await db
|
||||
.insert(drizzleDb.schemas.restoration)
|
||||
.values({
|
||||
databaseId: parsedInput.databaseId,
|
||||
backupId: parsedInput.backupId,
|
||||
backupStorageId: parsedInput.backupStorageId,
|
||||
status: "waiting",
|
||||
})
|
||||
.returning()
|
||||
.execute();
|
||||
|
||||
const createdRestoration = restorationData[0];
|
||||
|
||||
return {
|
||||
success: true,
|
||||
value: createdRestoration,
|
||||
actionSuccess: {
|
||||
message: "Restoration has been successfully created.",
|
||||
messageParams: {restorationId: createdRestoration.id},
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
actionError: {
|
||||
message: "Failed to create restoration.",
|
||||
status: 500,
|
||||
cause: error instanceof Error ? error.message : "Unknown error",
|
||||
messageParams: {message: "Error creating the restoration"},
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE "restorations" ADD COLUMN "backup_storage_id" uuid;--> statement-breakpoint
|
||||
ALTER TABLE "restorations" ADD CONSTRAINT "restorations_backup_storage_id_backup_storage_id_fk" FOREIGN KEY ("backup_storage_id") REFERENCES "public"."backup_storage"("id") ON DELETE cascade ON UPDATE no action;
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "2767f202-1e4b-42b1-8be0-1fa9dcd48cbb",
|
||||
"prevId": "a9aa4c81-9ca9-413f-89cb-37361d26927c",
|
||||
"id": "5d244170-557d-433b-8acd-742ead8246c8",
|
||||
"prevId": "2767f202-1e4b-42b1-8be0-1fa9dcd48cbb",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
@@ -114,25 +114,25 @@
|
||||
"settings_default_storage_channel_id_storage_channel_id_fk": {
|
||||
"name": "settings_default_storage_channel_id_storage_channel_id_fk",
|
||||
"tableFrom": "settings",
|
||||
"tableTo": "storage_channel",
|
||||
"columnsFrom": [
|
||||
"default_storage_channel_id"
|
||||
],
|
||||
"tableTo": "storage_channel",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "set null"
|
||||
"onDelete": "set null",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"settings_name_unique": {
|
||||
"name": "settings_name_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"name"
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
@@ -235,15 +235,15 @@
|
||||
"account_user_id_user_id_fk": {
|
||||
"name": "account_user_id_user_id_fk",
|
||||
"tableFrom": "account",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"tableTo": "user",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -336,15 +336,15 @@
|
||||
"passkey_userId_user_id_fk": {
|
||||
"name": "passkey_userId_user_id_fk",
|
||||
"tableFrom": "passkey",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"userId"
|
||||
],
|
||||
"tableTo": "user",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -431,25 +431,25 @@
|
||||
"session_user_id_user_id_fk": {
|
||||
"name": "session_user_id_user_id_fk",
|
||||
"tableFrom": "session",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"tableTo": "user",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"session_token_unique": {
|
||||
"name": "session_token_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"token"
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
@@ -491,15 +491,15 @@
|
||||
"two_factor_user_id_user_id_fk": {
|
||||
"name": "two_factor_user_id_user_id_fk",
|
||||
"tableFrom": "two_factor",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"tableTo": "user",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -614,10 +614,10 @@
|
||||
"uniqueConstraints": {
|
||||
"user_email_unique": {
|
||||
"name": "user_email_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"email"
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
@@ -742,10 +742,10 @@
|
||||
"uniqueConstraints": {
|
||||
"organization_slug_unique": {
|
||||
"name": "organization_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"slug"
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
@@ -806,28 +806,28 @@
|
||||
"member_organization_id_organization_id_fk": {
|
||||
"name": "member_organization_id_organization_id_fk",
|
||||
"tableFrom": "member",
|
||||
"tableTo": "organization",
|
||||
"columnsFrom": [
|
||||
"organization_id"
|
||||
],
|
||||
"tableTo": "organization",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"member_user_id_user_id_fk": {
|
||||
"name": "member_user_id_user_id_fk",
|
||||
"tableFrom": "member",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"tableTo": "user",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -908,28 +908,28 @@
|
||||
"invitation_organization_id_organization_id_fk": {
|
||||
"name": "invitation_organization_id_organization_id_fk",
|
||||
"tableFrom": "invitation",
|
||||
"tableTo": "organization",
|
||||
"columnsFrom": [
|
||||
"organization_id"
|
||||
],
|
||||
"tableTo": "organization",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"invitation_inviter_id_user_id_fk": {
|
||||
"name": "invitation_inviter_id_user_id_fk",
|
||||
"tableFrom": "invitation",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"inviter_id"
|
||||
],
|
||||
"tableTo": "user",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -999,25 +999,25 @@
|
||||
"projects_organization_id_organization_id_fk": {
|
||||
"name": "projects_organization_id_organization_id_fk",
|
||||
"tableFrom": "projects",
|
||||
"tableTo": "organization",
|
||||
"columnsFrom": [
|
||||
"organization_id"
|
||||
],
|
||||
"tableTo": "organization",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"projects_slug_unique": {
|
||||
"name": "projects_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"slug"
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
@@ -1086,15 +1086,15 @@
|
||||
"backups_database_id_databases_id_fk": {
|
||||
"name": "backups_database_id_databases_id_fk",
|
||||
"tableFrom": "backups",
|
||||
"tableTo": "databases",
|
||||
"columnsFrom": [
|
||||
"database_id"
|
||||
],
|
||||
"tableTo": "databases",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -1202,28 +1202,28 @@
|
||||
"databases_agent_id_agents_id_fk": {
|
||||
"name": "databases_agent_id_agents_id_fk",
|
||||
"tableFrom": "databases",
|
||||
"tableTo": "agents",
|
||||
"columnsFrom": [
|
||||
"agent_id"
|
||||
],
|
||||
"tableTo": "agents",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"databases_project_id_projects_id_fk": {
|
||||
"name": "databases_project_id_projects_id_fk",
|
||||
"tableFrom": "databases",
|
||||
"tableTo": "projects",
|
||||
"columnsFrom": [
|
||||
"project_id"
|
||||
],
|
||||
"tableTo": "projects",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "no action"
|
||||
"onDelete": "no action",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -1251,6 +1251,12 @@
|
||||
"notNull": true,
|
||||
"default": "'waiting'"
|
||||
},
|
||||
"backup_storage_id": {
|
||||
"name": "backup_storage_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"backup_id": {
|
||||
"name": "backup_id",
|
||||
"type": "uuid",
|
||||
@@ -1285,31 +1291,44 @@
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"restorations_backup_id_backups_id_fk": {
|
||||
"name": "restorations_backup_id_backups_id_fk",
|
||||
"restorations_backup_storage_id_backup_storage_id_fk": {
|
||||
"name": "restorations_backup_storage_id_backup_storage_id_fk",
|
||||
"tableFrom": "restorations",
|
||||
"tableTo": "backup_storage",
|
||||
"columnsFrom": [
|
||||
"backup_id"
|
||||
"backup_storage_id"
|
||||
],
|
||||
"tableTo": "backups",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"restorations_backup_id_backups_id_fk": {
|
||||
"name": "restorations_backup_id_backups_id_fk",
|
||||
"tableFrom": "restorations",
|
||||
"tableTo": "backups",
|
||||
"columnsFrom": [
|
||||
"backup_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"restorations_database_id_databases_id_fk": {
|
||||
"name": "restorations_database_id_databases_id_fk",
|
||||
"tableFrom": "restorations",
|
||||
"tableTo": "databases",
|
||||
"columnsFrom": [
|
||||
"database_id"
|
||||
],
|
||||
"tableTo": "databases",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -1409,15 +1428,15 @@
|
||||
"retention_policies_database_id_databases_id_fk": {
|
||||
"name": "retention_policies_database_id_databases_id_fk",
|
||||
"tableFrom": "retention_policies",
|
||||
"tableTo": "databases",
|
||||
"columnsFrom": [
|
||||
"database_id"
|
||||
],
|
||||
"tableTo": "databases",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -1500,10 +1519,10 @@
|
||||
"uniqueConstraints": {
|
||||
"agents_slug_unique": {
|
||||
"name": "agents_slug_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"slug"
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
@@ -1578,15 +1597,15 @@
|
||||
"notification_channel_organization_id_organization_id_fk": {
|
||||
"name": "notification_channel_organization_id_organization_id_fk",
|
||||
"tableFrom": "notification_channel",
|
||||
"tableTo": "organization",
|
||||
"columnsFrom": [
|
||||
"organization_id"
|
||||
],
|
||||
"tableTo": "organization",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -1617,39 +1636,39 @@
|
||||
"organization_notification_channels_organization_id_organization_id_fk": {
|
||||
"name": "organization_notification_channels_organization_id_organization_id_fk",
|
||||
"tableFrom": "organization_notification_channels",
|
||||
"tableTo": "organization",
|
||||
"columnsFrom": [
|
||||
"organization_id"
|
||||
],
|
||||
"tableTo": "organization",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"organization_notification_channels_notification_channel_id_notification_channel_id_fk": {
|
||||
"name": "organization_notification_channels_notification_channel_id_notification_channel_id_fk",
|
||||
"tableFrom": "organization_notification_channels",
|
||||
"tableTo": "notification_channel",
|
||||
"columnsFrom": [
|
||||
"notification_channel_id"
|
||||
],
|
||||
"tableTo": "notification_channel",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"organization_notification_channels_organization_id_notification_channel_id_unique": {
|
||||
"name": "organization_notification_channels_organization_id_notification_channel_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"organization_id",
|
||||
"notification_channel_id"
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
@@ -1718,28 +1737,28 @@
|
||||
"alert_policy_notification_channel_id_notification_channel_id_fk": {
|
||||
"name": "alert_policy_notification_channel_id_notification_channel_id_fk",
|
||||
"tableFrom": "alert_policy",
|
||||
"tableTo": "notification_channel",
|
||||
"columnsFrom": [
|
||||
"notification_channel_id"
|
||||
],
|
||||
"tableTo": "notification_channel",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"alert_policy_database_id_databases_id_fk": {
|
||||
"name": "alert_policy_database_id_databases_id_fk",
|
||||
"tableFrom": "alert_policy",
|
||||
"tableTo": "databases",
|
||||
"columnsFrom": [
|
||||
"database_id"
|
||||
],
|
||||
"tableTo": "databases",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -1895,39 +1914,39 @@
|
||||
"organization_storage_channels_organization_id_organization_id_fk": {
|
||||
"name": "organization_storage_channels_organization_id_organization_id_fk",
|
||||
"tableFrom": "organization_storage_channels",
|
||||
"tableTo": "organization",
|
||||
"columnsFrom": [
|
||||
"organization_id"
|
||||
],
|
||||
"tableTo": "organization",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"organization_storage_channels_storage_channel_id_storage_channel_id_fk": {
|
||||
"name": "organization_storage_channels_storage_channel_id_storage_channel_id_fk",
|
||||
"tableFrom": "organization_storage_channels",
|
||||
"tableTo": "storage_channel",
|
||||
"columnsFrom": [
|
||||
"storage_channel_id"
|
||||
],
|
||||
"tableTo": "storage_channel",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"organization_storage_channels_organization_id_storage_channel_id_unique": {
|
||||
"name": "organization_storage_channels_organization_id_storage_channel_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"organization_id",
|
||||
"storage_channel_id"
|
||||
],
|
||||
"nullsNotDistinct": false
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
@@ -2002,15 +2021,15 @@
|
||||
"storage_channel_organization_id_organization_id_fk": {
|
||||
"name": "storage_channel_organization_id_organization_id_fk",
|
||||
"tableFrom": "storage_channel",
|
||||
"tableTo": "organization",
|
||||
"columnsFrom": [
|
||||
"organization_id"
|
||||
],
|
||||
"tableTo": "organization",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -2074,28 +2093,28 @@
|
||||
"storage_policy_storage_channel_id_storage_channel_id_fk": {
|
||||
"name": "storage_policy_storage_channel_id_storage_channel_id_fk",
|
||||
"tableFrom": "storage_policy",
|
||||
"tableTo": "storage_channel",
|
||||
"columnsFrom": [
|
||||
"storage_channel_id"
|
||||
],
|
||||
"tableTo": "storage_channel",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"storage_policy_database_id_databases_id_fk": {
|
||||
"name": "storage_policy_database_id_databases_id_fk",
|
||||
"tableFrom": "storage_policy",
|
||||
"tableTo": "databases",
|
||||
"columnsFrom": [
|
||||
"database_id"
|
||||
],
|
||||
"tableTo": "databases",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -2178,28 +2197,28 @@
|
||||
"backup_storage_backup_id_backups_id_fk": {
|
||||
"name": "backup_storage_backup_id_backups_id_fk",
|
||||
"tableFrom": "backup_storage",
|
||||
"tableTo": "backups",
|
||||
"columnsFrom": [
|
||||
"backup_id"
|
||||
],
|
||||
"tableTo": "backups",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"backup_storage_storage_channel_id_storage_channel_id_fk": {
|
||||
"name": "backup_storage_storage_channel_id_storage_channel_id_fk",
|
||||
"tableFrom": "backup_storage",
|
||||
"tableTo": "storage_channel",
|
||||
"columnsFrom": [
|
||||
"storage_channel_id"
|
||||
],
|
||||
"tableTo": "storage_channel",
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onUpdate": "no action",
|
||||
"onDelete": "cascade"
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
@@ -2306,10 +2325,10 @@
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"views": {},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
|
||||
@@ -183,6 +183,13 @@
|
||||
"when": 1768424936753,
|
||||
"tag": "0025_past_franklin_richards",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"version": "7",
|
||||
"when": 1768665081232,
|
||||
"tag": "0026_demonic_santa_claus",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import {timestamps} from "@/db/schema/00_common";
|
||||
import {AlertPolicy, alertPolicy} from "@/db/schema/10_alert-policy";
|
||||
import {StoragePolicy, storagePolicy} from "@/db/schema/13_storage-policy";
|
||||
import {BackupStorage, backupStorage} from "@/db/schema/14_storage-backup";
|
||||
import {storageChannel} from "@/db/schema/12_storage-channel";
|
||||
|
||||
export const database = pgTable("databases", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
@@ -63,6 +64,8 @@ export const retentionPolicy = pgTable("retention_policies", {
|
||||
export const restoration = pgTable("restorations", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
status: statusEnum("status").default("waiting").notNull(),
|
||||
backupStorageId: uuid("backup_storage_id")
|
||||
.references(() => backupStorage.id, {onDelete: "cascade"}),
|
||||
backupId: uuid("backup_id")
|
||||
.notNull()
|
||||
.references(() => backup.id, {onDelete: "cascade"}),
|
||||
@@ -93,6 +96,7 @@ export const backupRelations = relations(backup, ({one, many}) => ({
|
||||
export const restorationRelations = relations(restoration, ({one}) => ({
|
||||
backup: one(backup, {fields: [restoration.backupId], references: [backup.id]}),
|
||||
database: one(database, {fields: [restoration.databaseId], references: [database.id]}),
|
||||
backupStorage: one(backupStorage, {fields: [restoration.backupStorageId], references: [backupStorage.id]}),
|
||||
}));
|
||||
|
||||
|
||||
|
||||
@@ -49,11 +49,18 @@ export async function getLocal(
|
||||
const expiresAt = Date.now() + 60 * 1000;
|
||||
const token = crypto.createHash("sha256").update(`${fileName}${expiresAt}`).digest("hex");
|
||||
|
||||
const params = new URLSearchParams({
|
||||
path: input.data.path,
|
||||
token,
|
||||
expires: expiresAt.toString(),
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
success: true,
|
||||
provider: 'local',
|
||||
file: file,
|
||||
url: `${baseUrl}/api/files/${fileName}?token=${token}&expires=${expiresAt}`,
|
||||
url: `${baseUrl}/api/files/?${params.toString()}`,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user