KI-AGENT: Mandantenbezogenen IMAP-Dokumentenimport umsetzen
This commit is contained in:
69
backend/db/migrations/0060_document_import_sources.sql
Normal file
69
backend/db/migrations/0060_document_import_sources.sql
Normal file
@@ -0,0 +1,69 @@
|
||||
CREATE TABLE "document_import_sources" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"tenant_id" bigint NOT NULL,
|
||||
"created_by" uuid,
|
||||
"name" text NOT NULL,
|
||||
"provider" text DEFAULT 'imap' NOT NULL,
|
||||
"enabled" boolean DEFAULT true NOT NULL,
|
||||
"mailbox_address_encrypted" jsonb,
|
||||
"password_encrypted" jsonb,
|
||||
"imap_host_encrypted" jsonb,
|
||||
"imap_port" integer DEFAULT 993 NOT NULL,
|
||||
"imap_secure" boolean DEFAULT true NOT NULL,
|
||||
"mailbox_path" text DEFAULT 'INBOX' NOT NULL,
|
||||
"target_folder_id" uuid,
|
||||
"default_filetype_id" uuid,
|
||||
"mark_as_seen" boolean DEFAULT true NOT NULL,
|
||||
"last_synced_at" timestamp with time zone,
|
||||
"last_error" text,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "document_import_states" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"source_id" uuid NOT NULL,
|
||||
"mailbox_path" text NOT NULL,
|
||||
"uid_validity" bigint,
|
||||
"highest_uid" bigint DEFAULT 0 NOT NULL,
|
||||
"delta_link_encrypted" jsonb,
|
||||
"updated_at" timestamp with time zone
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "document_import_items" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"tenant_id" bigint NOT NULL,
|
||||
"source_id" uuid NOT NULL,
|
||||
"remote_message_id" text NOT NULL,
|
||||
"attachment_key" text NOT NULL,
|
||||
"attachment_checksum" text NOT NULL,
|
||||
"filename" text,
|
||||
"status" text NOT NULL,
|
||||
"error" text,
|
||||
"file_id" uuid,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "document_import_sources" ADD CONSTRAINT "document_import_sources_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE cascade;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "document_import_sources" ADD CONSTRAINT "document_import_sources_created_by_auth_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."auth_users"("id") ON DELETE set null;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "document_import_sources" ADD CONSTRAINT "document_import_sources_target_folder_id_folders_id_fk" FOREIGN KEY ("target_folder_id") REFERENCES "public"."folders"("id") ON DELETE set null;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "document_import_sources" ADD CONSTRAINT "document_import_sources_default_filetype_id_filetags_id_fk" FOREIGN KEY ("default_filetype_id") REFERENCES "public"."filetags"("id") ON DELETE set null;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "document_import_states" ADD CONSTRAINT "document_import_states_source_id_document_import_sources_id_fk" FOREIGN KEY ("source_id") REFERENCES "public"."document_import_sources"("id") ON DELETE cascade ON UPDATE cascade;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "document_import_items" ADD CONSTRAINT "document_import_items_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE cascade;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "document_import_items" ADD CONSTRAINT "document_import_items_source_id_document_import_sources_id_fk" FOREIGN KEY ("source_id") REFERENCES "public"."document_import_sources"("id") ON DELETE cascade ON UPDATE cascade;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "document_import_items" ADD CONSTRAINT "document_import_items_file_id_files_id_fk" FOREIGN KEY ("file_id") REFERENCES "public"."files"("id") ON DELETE set null;
|
||||
--> statement-breakpoint
|
||||
CREATE INDEX "document_import_sources_tenant_idx" ON "document_import_sources" USING btree ("tenant_id");
|
||||
--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "document_import_states_source_mailbox_key" ON "document_import_states" USING btree ("source_id", "mailbox_path");
|
||||
--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "document_import_items_remote_attachment_key" ON "document_import_items" USING btree ("source_id", "remote_message_id", "attachment_key");
|
||||
--> statement-breakpoint
|
||||
CREATE INDEX "document_import_items_checksum_idx" ON "document_import_items" USING btree ("source_id", "attachment_checksum");
|
||||
84
backend/db/schema/document_imports.ts
Normal file
84
backend/db/schema/document_imports.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import {
|
||||
bigint,
|
||||
boolean,
|
||||
index,
|
||||
integer,
|
||||
jsonb,
|
||||
pgTable,
|
||||
text,
|
||||
timestamp,
|
||||
uniqueIndex,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core"
|
||||
|
||||
import { tenants } from "./tenants"
|
||||
import { authUsers } from "./auth_users"
|
||||
import { files } from "./files"
|
||||
import { folders } from "./folders"
|
||||
import { filetags } from "./filetags"
|
||||
|
||||
export const documentImportSources = pgTable("document_import_sources", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: "cascade", onUpdate: "cascade" }),
|
||||
createdBy: uuid("created_by").references(() => authUsers.id, { onDelete: "set null" }),
|
||||
name: text("name").notNull(),
|
||||
provider: text("provider").notNull().default("imap"),
|
||||
enabled: boolean("enabled").notNull().default(true),
|
||||
mailboxAddressEncrypted: jsonb("mailbox_address_encrypted"),
|
||||
passwordEncrypted: jsonb("password_encrypted"),
|
||||
imapHostEncrypted: jsonb("imap_host_encrypted"),
|
||||
imapPort: integer("imap_port").notNull().default(993),
|
||||
imapSecure: boolean("imap_secure").notNull().default(true),
|
||||
mailboxPath: text("mailbox_path").notNull().default("INBOX"),
|
||||
targetFolderId: uuid("target_folder_id").references(() => folders.id, { onDelete: "set null" }),
|
||||
defaultFiletypeId: uuid("default_filetype_id").references(() => filetags.id, { onDelete: "set null" }),
|
||||
markAsSeen: boolean("mark_as_seen").notNull().default(true),
|
||||
lastSyncedAt: timestamp("last_synced_at", { withTimezone: true }),
|
||||
lastError: text("last_error"),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
}, (table) => ({
|
||||
tenantIdx: index("document_import_sources_tenant_idx").on(table.tenantId),
|
||||
}))
|
||||
|
||||
export const documentImportStates = pgTable("document_import_states", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
sourceId: uuid("source_id")
|
||||
.notNull()
|
||||
.references(() => documentImportSources.id, { onDelete: "cascade", onUpdate: "cascade" }),
|
||||
mailboxPath: text("mailbox_path").notNull(),
|
||||
uidValidity: bigint("uid_validity", { mode: "number" }),
|
||||
highestUid: bigint("highest_uid", { mode: "number" }).notNull().default(0),
|
||||
deltaLinkEncrypted: jsonb("delta_link_encrypted"),
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }),
|
||||
}, (table) => ({
|
||||
sourceMailboxKey: uniqueIndex("document_import_states_source_mailbox_key")
|
||||
.on(table.sourceId, table.mailboxPath),
|
||||
}))
|
||||
|
||||
export const documentImportItems = pgTable("document_import_items", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
tenantId: bigint("tenant_id", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: "cascade", onUpdate: "cascade" }),
|
||||
sourceId: uuid("source_id")
|
||||
.notNull()
|
||||
.references(() => documentImportSources.id, { onDelete: "cascade", onUpdate: "cascade" }),
|
||||
remoteMessageId: text("remote_message_id").notNull(),
|
||||
attachmentKey: text("attachment_key").notNull(),
|
||||
attachmentChecksum: text("attachment_checksum").notNull(),
|
||||
filename: text("filename"),
|
||||
status: text("status").notNull(),
|
||||
error: text("error"),
|
||||
fileId: uuid("file_id").references(() => files.id, { onDelete: "set null" }),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
}, (table) => ({
|
||||
remoteAttachmentKey: uniqueIndex("document_import_items_remote_attachment_key")
|
||||
.on(table.sourceId, table.remoteMessageId, table.attachmentKey),
|
||||
checksumIdx: index("document_import_items_checksum_idx")
|
||||
.on(table.sourceId, table.attachmentChecksum),
|
||||
}))
|
||||
|
||||
export type DocumentImportSource = typeof documentImportSources.$inferSelect
|
||||
@@ -28,6 +28,7 @@ export * from "./customerspaces"
|
||||
export * from "./customerinventoryitems"
|
||||
export * from "./devices"
|
||||
export * from "./documentboxes"
|
||||
export * from "./document_imports"
|
||||
export * from "./emails"
|
||||
export * from "./enums"
|
||||
export * from "./events"
|
||||
|
||||
Reference in New Issue
Block a user