mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
feat: Working on storage modal in database page in order to add multiple backend storages. Adding a system to manage independently channels from organizations and from system admin.
This commit is contained in:
+3
-1
@@ -13,6 +13,7 @@ import * as organizationNotificationChannel from "./schema/09_notification-chann
|
||||
import * as alertPolicy from "./schema/10_alert-policy";
|
||||
import * as notificationLog from "./schema/11_notification-log";
|
||||
import * as storageChannel from "./schema/12_storage-channel";
|
||||
import * as storagePolicy from "@/db/schema/13_storage-policy";
|
||||
|
||||
|
||||
import {Pool} from "pg";
|
||||
@@ -42,7 +43,8 @@ export const schemas = {
|
||||
...organizationNotificationChannel,
|
||||
...alertPolicy,
|
||||
...notificationLog,
|
||||
...storageChannel
|
||||
...storageChannel,
|
||||
...storagePolicy
|
||||
};
|
||||
|
||||
export const db = drizzle({
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
CREATE TYPE "public"."backup_storage_status" AS ENUM('pending', 'success', 'failed');--> statement-breakpoint
|
||||
CREATE TABLE "backup_storage" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"backup_id" uuid NOT NULL,
|
||||
"storage_channel_id" uuid NOT NULL,
|
||||
"status" "backup_storage_status" DEFAULT 'pending' NOT NULL,
|
||||
"path" text,
|
||||
"size" integer,
|
||||
"checksum" text,
|
||||
"updated_at" timestamp,
|
||||
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||
"deleted_at" timestamp
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "backup_storage" ADD CONSTRAINT "backup_storage_backup_id_backups_id_fk" FOREIGN KEY ("backup_id") REFERENCES "public"."backups"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "backup_storage" ADD CONSTRAINT "backup_storage_storage_channel_id_storage_channel_id_fk" FOREIGN KEY ("storage_channel_id") REFERENCES "public"."storage_channel"("id") ON DELETE cascade ON UPDATE no action;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE "storage_channel" ADD COLUMN "organization_id" uuid;--> statement-breakpoint
|
||||
ALTER TABLE "storage_channel" ADD CONSTRAINT "storage_channel_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE "notification_channel" ADD COLUMN "organization_id" uuid;--> statement-breakpoint
|
||||
ALTER TABLE "notification_channel" ADD CONSTRAINT "notification_channel_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -155,6 +155,27 @@
|
||||
"when": 1768337434929,
|
||||
"tag": "0021_soft_blockbuster",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"version": "7",
|
||||
"when": 1768379186747,
|
||||
"tag": "0022_purple_retro_girl",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"version": "7",
|
||||
"when": 1768412730102,
|
||||
"tag": "0023_common_the_captain",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"version": "7",
|
||||
"when": 1768412750113,
|
||||
"tag": "0024_lush_blindfold",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import {z} from "zod";
|
||||
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} from "@/db/schema/14_storage-backup";
|
||||
|
||||
export const database = pgTable("databases", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
@@ -41,7 +42,6 @@ export const backup = pgTable(
|
||||
.references(() => database.id, {onDelete: "cascade"}),
|
||||
...timestamps
|
||||
},
|
||||
// (table) => [uniqueIndex("database_id_status_unique").on(table.databaseId, table.status)]
|
||||
);
|
||||
|
||||
export const retentionPolicyType = pgEnum("retention_policy_type", ["count", "days", "gfs"]);
|
||||
@@ -87,6 +87,7 @@ export const databaseRelations = relations(database, ({one, many}) => ({
|
||||
export const backupRelations = relations(backup, ({one, many}) => ({
|
||||
database: one(database, {fields: [backup.databaseId], references: [database.id]}),
|
||||
restorations: many(restoration),
|
||||
storages: many(backupStorage),
|
||||
}));
|
||||
|
||||
export const restorationRelations = relations(restoration, ({one}) => ({
|
||||
|
||||
@@ -12,6 +12,7 @@ export const providerKindEnum = pgEnum('provider_kind', ['slack', 'smtp', 'disco
|
||||
export const notificationChannel = pgTable('notification_channel', {
|
||||
id: uuid("id").defaultRandom().primaryKey(),
|
||||
provider: providerKindEnum('provider').notNull(),
|
||||
organizationId: uuid("organization_id").references(() => organization.id, {onDelete: "cascade"}),
|
||||
name: varchar('name', {length: 255}).notNull(),
|
||||
config: jsonb('config').notNull(),
|
||||
enabled: boolean('enabled').default(false).notNull(),
|
||||
|
||||
@@ -4,12 +4,14 @@ import {organization} from "@/db/schema/03_organization";
|
||||
import {relations} from "drizzle-orm";
|
||||
import {createSelectSchema} from "drizzle-zod";
|
||||
import {z} from "zod";
|
||||
import {database} from "@/db/schema/07_database";
|
||||
|
||||
|
||||
export const providerStorageKindEnum = pgEnum('provider_storage_kind', ['local', 's3']);
|
||||
|
||||
export const storageChannel = pgTable('storage_channel', {
|
||||
id: uuid("id").defaultRandom().primaryKey(),
|
||||
organizationId: uuid("organization_id").references(() => organization.id, {onDelete: "cascade"}),
|
||||
provider: providerStorageKindEnum('provider').notNull(),
|
||||
name: varchar('name', {length: 255}).notNull(),
|
||||
config: jsonb('config').notNull(),
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { pgTable, uuid, text, integer, pgEnum } from "drizzle-orm/pg-core";
|
||||
import { timestamps } from "@/db/schema/00_common";
|
||||
import { storageChannel } from "@/db/schema/12_storage-channel";
|
||||
import {backup} from "@/db/schema/07_database";
|
||||
import {relations} from "drizzle-orm";
|
||||
|
||||
export const backupStorageStatusEnum = pgEnum("backup_storage_status", [
|
||||
"pending",
|
||||
"success",
|
||||
"failed",
|
||||
]);
|
||||
|
||||
export const backupStorage = pgTable("backup_storage", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
backupId: uuid("backup_id")
|
||||
.notNull()
|
||||
.references(() => backup.id, { onDelete: "cascade" }),
|
||||
storageChannelId: uuid("storage_channel_id")
|
||||
.notNull()
|
||||
.references(() => storageChannel.id, { onDelete: "cascade" }),
|
||||
status: backupStorageStatusEnum("status").notNull().default("pending"),
|
||||
path: text("path"),
|
||||
size: integer("size"),
|
||||
checksum: text("checksum"),
|
||||
...timestamps,
|
||||
});
|
||||
|
||||
|
||||
export const backupStorageRelations = relations(backupStorage, ({ one }) => ({
|
||||
backup: one(backup, {
|
||||
fields: [backupStorage.backupId],
|
||||
references: [backup.id],
|
||||
}),
|
||||
storageChannel: one(storageChannel, {
|
||||
fields: [backupStorage.storageChannelId],
|
||||
references: [storageChannel.id],
|
||||
}),
|
||||
}));
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
notificationChannel,
|
||||
organizationNotificationChannel
|
||||
} from "@/db/schema/09_notification-channel";
|
||||
import {storageChannel} from "@/db/schema/12_storage-channel";
|
||||
|
||||
export async function getOrganizationChannels(organizationId: string) {
|
||||
return await db
|
||||
@@ -17,6 +18,7 @@ export async function getOrganizationChannels(organizationId: string) {
|
||||
updatedAt: notificationChannel.updatedAt,
|
||||
createdAt: notificationChannel.createdAt,
|
||||
deletedAt: notificationChannel.deletedAt,
|
||||
organizationId: notificationChannel.organizationId
|
||||
})
|
||||
.from(organizationNotificationChannel)
|
||||
.innerJoin(
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import {desc, eq} from "drizzle-orm";
|
||||
import {db} from "@/db";
|
||||
import {organizationStorageChannel, StorageChannel, storageChannel} from "@/db/schema/12_storage-channel";
|
||||
|
||||
export async function getOrganizationStorageChannels(organizationId: string) {
|
||||
return await db
|
||||
.select({
|
||||
id: storageChannel.id,
|
||||
name: storageChannel.name,
|
||||
provider: storageChannel.provider,
|
||||
organizationId: storageChannel.organizationId,
|
||||
config: storageChannel.config,
|
||||
enabled: storageChannel.enabled,
|
||||
updatedAt: storageChannel.updatedAt,
|
||||
createdAt: storageChannel.createdAt,
|
||||
deletedAt: storageChannel.deletedAt,
|
||||
})
|
||||
.from(organizationStorageChannel)
|
||||
.innerJoin(
|
||||
storageChannel,
|
||||
eq(organizationStorageChannel.storageChannelId, storageChannel.id)
|
||||
)
|
||||
.orderBy(desc(storageChannel.createdAt))
|
||||
.where(eq(organizationStorageChannel.organizationId, organizationId)) as unknown as StorageChannel[];
|
||||
}
|
||||
Reference in New Issue
Block a user