From f7a3e3f0f87298cb0ac2c5efb222c3d0f39894bc Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Fri, 24 Oct 2025 02:08:25 +0200 Subject: [PATCH] compose --- .../down.sql | 11 - .../202402240001_create_initial_schema/up.sql | 77 ------ .../20240902000123_create_tenants/down.sql | 1 - .../20240902000123_create_tenants/up.sql | 10 - .../down.sql | 2 - .../20240902003000_seed_default_tenant/up.sql | 10 - .../down.sql | 1 - .../up.sql | 12 - .../down.sql | 7 - .../up.sql | 7 - .../20240902013000_drop_user_role/down.sql | 2 - .../20240902013000_drop_user_role/up.sql | 2 - .../20240902014000_add_tenant_id/down.sql | 47 ---- .../20240902014000_add_tenant_id/up.sql | 120 --------- .../20240902150000_rename_tenants_id/down.sql | 1 - .../20240902150000_rename_tenants_id/up.sql | 1 - .../down.sql | 2 - .../up.sql | 7 - .../down.sql | 1 - .../up.sql | 3 - .../202502130001_create_jobs/down.sql | 5 - .../202502130001_create_jobs/up.sql | 28 -- .../down.sql | 3 - .../up.sql | 15 -- .../down.sql | 4 - .../up.sql | 5 - .../down.sql | 2 - .../up.sql | 2 - .../down.sql | 2 - .../202503090002_add_name_to_documents/up.sql | 11 - .../down.sql | 2 - .../202503090003_rename_name_to_title/up.sql | 2 - .../down.sql | 1 - .../202503090004_create_refresh_tokens/up.sql | 13 - .../down.sql | 13 - .../202503120001_drop_asset_dimensions/up.sql | 15 -- .../202503120003_use_version_uuid/down.sql | 17 -- .../202503120003_use_version_uuid/up.sql | 21 -- .../202503200001_add_correspondents/down.sql | 5 - .../202503200001_add_correspondents/up.sql | 27 -- .../down.sql | 2 - .../up.sql | 13 - .../down.sql | 16 -- .../202503240002_unique_document_names/up.sql | 18 -- .../down.sql | 2 - .../up.sql | 2 - .../down.sql | 2 - .../up.sql | 2 - .../down.sql | 34 --- .../up.sql | 54 ---- .../202503260001_initial_schema/down.sql | 21 ++ .../202503260001_initial_schema/up.sql | 244 ++++++++++++++++++ docker-compose.test.yml | 47 +++- docker-compose.yml | 41 ++- 54 files changed, 333 insertions(+), 682 deletions(-) delete mode 100644 backend/migrations/202402240001_create_initial_schema/down.sql delete mode 100644 backend/migrations/202402240001_create_initial_schema/up.sql delete mode 100644 backend/migrations/20240902000123_create_tenants/down.sql delete mode 100644 backend/migrations/20240902000123_create_tenants/up.sql delete mode 100644 backend/migrations/20240902003000_seed_default_tenant/down.sql delete mode 100644 backend/migrations/20240902003000_seed_default_tenant/up.sql delete mode 100644 backend/migrations/20240902011000_create_user_memberships/down.sql delete mode 100644 backend/migrations/20240902011000_create_user_memberships/up.sql delete mode 100644 backend/migrations/20240902011500_seed_admin_membership/down.sql delete mode 100644 backend/migrations/20240902011500_seed_admin_membership/up.sql delete mode 100644 backend/migrations/20240902013000_drop_user_role/down.sql delete mode 100644 backend/migrations/20240902013000_drop_user_role/up.sql delete mode 100644 backend/migrations/20240902014000_add_tenant_id/down.sql delete mode 100644 backend/migrations/20240902014000_add_tenant_id/up.sql delete mode 100644 backend/migrations/20240902150000_rename_tenants_id/down.sql delete mode 100644 backend/migrations/20240902150000_rename_tenants_id/up.sql delete mode 100644 backend/migrations/20240902160000_add_tenant_unique_constraints/down.sql delete mode 100644 backend/migrations/20240902160000_add_tenant_unique_constraints/up.sql delete mode 100644 backend/migrations/20240902164000_drop_users_tenant_id/down.sql delete mode 100644 backend/migrations/20240902164000_drop_users_tenant_id/up.sql delete mode 100644 backend/migrations/202502130001_create_jobs/down.sql delete mode 100644 backend/migrations/202502130001_create_jobs/up.sql delete mode 100644 backend/migrations/202502130002_create_document_assets/down.sql delete mode 100644 backend/migrations/202502130002_create_document_assets/up.sql delete mode 100644 backend/migrations/202503040001_enforce_unique_folder_names/down.sql delete mode 100644 backend/migrations/202503040001_enforce_unique_folder_names/up.sql delete mode 100644 backend/migrations/202503090001_add_issued_at_to_documents/down.sql delete mode 100644 backend/migrations/202503090001_add_issued_at_to_documents/up.sql delete mode 100644 backend/migrations/202503090002_add_name_to_documents/down.sql delete mode 100644 backend/migrations/202503090002_add_name_to_documents/up.sql delete mode 100644 backend/migrations/202503090003_rename_name_to_title/down.sql delete mode 100644 backend/migrations/202503090003_rename_name_to_title/up.sql delete mode 100644 backend/migrations/202503090004_create_refresh_tokens/down.sql delete mode 100644 backend/migrations/202503090004_create_refresh_tokens/up.sql delete mode 100644 backend/migrations/202503120001_drop_asset_dimensions/down.sql delete mode 100644 backend/migrations/202503120001_drop_asset_dimensions/up.sql delete mode 100644 backend/migrations/202503120003_use_version_uuid/down.sql delete mode 100644 backend/migrations/202503120003_use_version_uuid/up.sql delete mode 100644 backend/migrations/202503200001_add_correspondents/down.sql delete mode 100644 backend/migrations/202503200001_add_correspondents/up.sql delete mode 100644 backend/migrations/202503240001_index_documents_by_folder_title/down.sql delete mode 100644 backend/migrations/202503240001_index_documents_by_folder_title/up.sql delete mode 100644 backend/migrations/202503240002_unique_document_names/down.sql delete mode 100644 backend/migrations/202503240002_unique_document_names/up.sql delete mode 100644 backend/migrations/202503240003_add_metadata_to_document_versions/down.sql delete mode 100644 backend/migrations/202503240003_add_metadata_to_document_versions/up.sql delete mode 100644 backend/migrations/202503240004_drop_folder_path_cache/down.sql delete mode 100644 backend/migrations/202503240004_drop_folder_path_cache/up.sql delete mode 100644 backend/migrations/202503240005_create_document_asset_objects/down.sql delete mode 100644 backend/migrations/202503240005_create_document_asset_objects/up.sql create mode 100644 backend/migrations/202503260001_initial_schema/down.sql create mode 100644 backend/migrations/202503260001_initial_schema/up.sql diff --git a/backend/migrations/202402240001_create_initial_schema/down.sql b/backend/migrations/202402240001_create_initial_schema/down.sql deleted file mode 100644 index 1ca967a..0000000 --- a/backend/migrations/202402240001_create_initial_schema/down.sql +++ /dev/null @@ -1,11 +0,0 @@ -DROP INDEX IF EXISTS idx_document_tags_tag; -DROP TABLE IF EXISTS document_tags; -DROP INDEX IF EXISTS idx_document_versions_document; -DROP TABLE IF EXISTS document_versions; -DROP INDEX IF EXISTS idx_documents_deleted_at; -DROP INDEX IF EXISTS idx_documents_folder; -DROP TABLE IF EXISTS documents; -DROP INDEX IF EXISTS idx_folders_parent; -DROP TABLE IF EXISTS folders; -DROP TABLE IF EXISTS tags; -DROP TABLE IF EXISTS users; diff --git a/backend/migrations/202402240001_create_initial_schema/up.sql b/backend/migrations/202402240001_create_initial_schema/up.sql deleted file mode 100644 index c8eb4d7..0000000 --- a/backend/migrations/202402240001_create_initial_schema/up.sql +++ /dev/null @@ -1,77 +0,0 @@ -CREATE EXTENSION IF NOT EXISTS "pgcrypto"; - -CREATE TABLE users ( - id UUID PRIMARY KEY, - username VARCHAR(100) NOT NULL UNIQUE, - password_hash VARCHAR(255) NOT NULL, - role VARCHAR(16) NOT NULL, - created_at TIMESTAMPTZ NOT NULL DEFAULT now(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT now() -); - -CREATE TABLE folders ( - id UUID PRIMARY KEY, - name VARCHAR(255) NOT NULL, - parent_id UUID REFERENCES folders(id) ON DELETE SET NULL, - path_cache VARCHAR(1000), - created_at TIMESTAMPTZ NOT NULL DEFAULT now(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), - CONSTRAINT folders_parent_name_unique UNIQUE (parent_id, name) -); - -CREATE INDEX idx_folders_parent ON folders(parent_id); - -CREATE TABLE documents ( - id UUID PRIMARY KEY, - filename VARCHAR(255) NOT NULL, - original_name VARCHAR(255) NOT NULL, - content_type VARCHAR(100), - folder_id UUID REFERENCES folders(id) ON DELETE SET NULL, - current_version INTEGER NOT NULL, - uploaded_at TIMESTAMPTZ NOT NULL DEFAULT now(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), - deleted_at TIMESTAMPTZ, - metadata JSONB NOT NULL DEFAULT '{}'::jsonb -); - -CREATE INDEX idx_documents_folder ON documents(folder_id); -CREATE INDEX idx_documents_deleted_at ON documents(deleted_at); - -CREATE TABLE document_versions ( - id UUID PRIMARY KEY, - document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE, - version_number INTEGER NOT NULL, - s3_key VARCHAR(500) NOT NULL, - size_bytes BIGINT NOT NULL, - checksum VARCHAR(64) NOT NULL, - created_at TIMESTAMPTZ NOT NULL DEFAULT now(), - operations_summary JSONB NOT NULL DEFAULT '{}'::jsonb, - CONSTRAINT document_versions_unique_version UNIQUE (document_id, version_number) -); - -CREATE INDEX idx_document_versions_document ON document_versions(document_id); - -CREATE TABLE tags ( - id UUID PRIMARY KEY, - label VARCHAR(100) NOT NULL UNIQUE, - color VARCHAR(7), - created_at TIMESTAMPTZ NOT NULL DEFAULT now() -); - -CREATE TABLE document_tags ( - document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE, - tag_id UUID NOT NULL REFERENCES tags(id) ON DELETE CASCADE, - assigned_at TIMESTAMPTZ NOT NULL DEFAULT now(), - assigned_by UUID REFERENCES users(id), - PRIMARY KEY (document_id, tag_id) -); - -CREATE INDEX idx_document_tags_tag ON document_tags(tag_id); - -INSERT INTO users (id, username, password_hash, role) -VALUES ( - gen_random_uuid(), - 'admin', - '$argon2id$v=19$m=19456,t=2,p=1$UMkfsNut028fmZupy9JoQg$/YFvGQoEZ2hhMiDCyv68ZROF97GcwAxxRwRgwSbpX5U', - 'admin' -); diff --git a/backend/migrations/20240902000123_create_tenants/down.sql b/backend/migrations/20240902000123_create_tenants/down.sql deleted file mode 100644 index 68e11dc..0000000 --- a/backend/migrations/20240902000123_create_tenants/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS public.tenants; diff --git a/backend/migrations/20240902000123_create_tenants/up.sql b/backend/migrations/20240902000123_create_tenants/up.sql deleted file mode 100644 index d47fb29..0000000 --- a/backend/migrations/20240902000123_create_tenants/up.sql +++ /dev/null @@ -1,10 +0,0 @@ -CREATE TABLE public.tenants ( - tenant_id UUID PRIMARY KEY, - slug TEXT NOT NULL UNIQUE, - storage_root TEXT, - quickwit_index TEXT, - status TEXT NOT NULL DEFAULT 'active', - config JSONB NOT NULL DEFAULT '{}'::jsonb, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); diff --git a/backend/migrations/20240902003000_seed_default_tenant/down.sql b/backend/migrations/20240902003000_seed_default_tenant/down.sql deleted file mode 100644 index 8ba7b7d..0000000 --- a/backend/migrations/20240902003000_seed_default_tenant/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -DELETE FROM public.tenants -WHERE slug = 'admin'; diff --git a/backend/migrations/20240902003000_seed_default_tenant/up.sql b/backend/migrations/20240902003000_seed_default_tenant/up.sql deleted file mode 100644 index 438d250..0000000 --- a/backend/migrations/20240902003000_seed_default_tenant/up.sql +++ /dev/null @@ -1,10 +0,0 @@ -INSERT INTO public.tenants (tenant_id, slug, storage_root, quickwit_index, status, config) -VALUES ( - gen_random_uuid(), - 'admin', - NULL, - NULL, - 'active', - '{}'::jsonb -) -ON CONFLICT (slug) DO NOTHING; diff --git a/backend/migrations/20240902011000_create_user_memberships/down.sql b/backend/migrations/20240902011000_create_user_memberships/down.sql deleted file mode 100644 index a167636..0000000 --- a/backend/migrations/20240902011000_create_user_memberships/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS public.user_memberships; diff --git a/backend/migrations/20240902011000_create_user_memberships/up.sql b/backend/migrations/20240902011000_create_user_memberships/up.sql deleted file mode 100644 index 697a31d..0000000 --- a/backend/migrations/20240902011000_create_user_memberships/up.sql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE TABLE public.user_memberships ( - id UUID PRIMARY KEY, - user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, - tenant_id UUID NOT NULL REFERENCES public.tenants(tenant_id) ON DELETE CASCADE, - role TEXT NOT NULL, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - UNIQUE (user_id, tenant_id) -); - -CREATE INDEX user_memberships_tenant_id_idx ON public.user_memberships (tenant_id); -CREATE INDEX user_memberships_user_id_idx ON public.user_memberships (user_id); diff --git a/backend/migrations/20240902011500_seed_admin_membership/down.sql b/backend/migrations/20240902011500_seed_admin_membership/down.sql deleted file mode 100644 index e352c7f..0000000 --- a/backend/migrations/20240902011500_seed_admin_membership/down.sql +++ /dev/null @@ -1,7 +0,0 @@ -DELETE FROM public.user_memberships -WHERE user_id IN ( - SELECT id FROM public.users WHERE username = 'admin' -) - AND tenant_id IN ( - SELECT tenant_id FROM public.tenants WHERE slug = 'admin' -); diff --git a/backend/migrations/20240902011500_seed_admin_membership/up.sql b/backend/migrations/20240902011500_seed_admin_membership/up.sql deleted file mode 100644 index eb6de28..0000000 --- a/backend/migrations/20240902011500_seed_admin_membership/up.sql +++ /dev/null @@ -1,7 +0,0 @@ -INSERT INTO public.user_memberships (id, user_id, tenant_id, role) -SELECT gen_random_uuid(), u.id, t.tenant_id, 'admin' -FROM public.users AS u -JOIN public.tenants AS t ON t.slug = 'admin' -LEFT JOIN public.user_memberships AS um ON um.user_id = u.id AND um.tenant_id = t.tenant_id -WHERE u.username = 'admin' AND um.id IS NULL -ON CONFLICT (user_id, tenant_id) DO NOTHING; diff --git a/backend/migrations/20240902013000_drop_user_role/down.sql b/backend/migrations/20240902013000_drop_user_role/down.sql deleted file mode 100644 index 6d0888b..0000000 --- a/backend/migrations/20240902013000_drop_user_role/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE users - ADD COLUMN role VARCHAR(16) NOT NULL DEFAULT 'user'; diff --git a/backend/migrations/20240902013000_drop_user_role/up.sql b/backend/migrations/20240902013000_drop_user_role/up.sql deleted file mode 100644 index 455814f..0000000 --- a/backend/migrations/20240902013000_drop_user_role/up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE users - DROP COLUMN role; diff --git a/backend/migrations/20240902014000_add_tenant_id/down.sql b/backend/migrations/20240902014000_add_tenant_id/down.sql deleted file mode 100644 index d5de82d..0000000 --- a/backend/migrations/20240902014000_add_tenant_id/down.sql +++ /dev/null @@ -1,47 +0,0 @@ -DROP INDEX IF EXISTS jobs_tenant_id_idx; -ALTER TABLE jobs DROP CONSTRAINT IF EXISTS jobs_tenant_id_fkey; -ALTER TABLE jobs DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS refresh_tokens_tenant_id_idx; -ALTER TABLE refresh_tokens DROP CONSTRAINT IF EXISTS refresh_tokens_tenant_id_fkey; -ALTER TABLE refresh_tokens DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS users_tenant_id_idx; -ALTER TABLE users DROP CONSTRAINT IF EXISTS users_tenant_id_fkey; -ALTER TABLE users DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS folders_tenant_id_idx; -ALTER TABLE folders DROP CONSTRAINT IF EXISTS folders_tenant_id_fkey; -ALTER TABLE folders DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS tags_tenant_id_idx; -ALTER TABLE tags DROP CONSTRAINT IF EXISTS tags_tenant_id_fkey; -ALTER TABLE tags DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS correspondents_tenant_id_idx; -ALTER TABLE correspondents DROP CONSTRAINT IF EXISTS correspondents_tenant_id_fkey; -ALTER TABLE correspondents DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS document_correspondents_tenant_id_idx; -ALTER TABLE document_correspondents DROP CONSTRAINT IF EXISTS document_correspondents_tenant_id_fkey; -ALTER TABLE document_correspondents DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS document_tags_tenant_id_idx; -ALTER TABLE document_tags DROP CONSTRAINT IF EXISTS document_tags_tenant_id_fkey; -ALTER TABLE document_tags DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS document_asset_objects_tenant_id_idx; -ALTER TABLE document_asset_objects DROP CONSTRAINT IF EXISTS document_asset_objects_tenant_id_fkey; -ALTER TABLE document_asset_objects DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS document_assets_tenant_id_idx; -ALTER TABLE document_assets DROP CONSTRAINT IF EXISTS document_assets_tenant_id_fkey; -ALTER TABLE document_assets DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS document_versions_tenant_id_idx; -ALTER TABLE document_versions DROP CONSTRAINT IF EXISTS document_versions_tenant_id_fkey; -ALTER TABLE document_versions DROP COLUMN IF EXISTS tenant_id; - -DROP INDEX IF EXISTS documents_tenant_id_idx; -ALTER TABLE documents DROP CONSTRAINT IF EXISTS documents_tenant_id_fkey; -ALTER TABLE documents DROP COLUMN IF EXISTS tenant_id; diff --git a/backend/migrations/20240902014000_add_tenant_id/up.sql b/backend/migrations/20240902014000_add_tenant_id/up.sql deleted file mode 100644 index c757f2b..0000000 --- a/backend/migrations/20240902014000_add_tenant_id/up.sql +++ /dev/null @@ -1,120 +0,0 @@ --- Add tenant_id to documents -ALTER TABLE documents ADD COLUMN tenant_id UUID; -UPDATE documents -SET tenant_id = (SELECT tenant_id FROM public.tenants WHERE slug = 'admin'); -ALTER TABLE documents ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE documents - ADD CONSTRAINT documents_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX documents_tenant_id_idx ON documents (tenant_id); - --- Add tenant_id to document_versions -ALTER TABLE document_versions ADD COLUMN tenant_id UUID; -UPDATE document_versions AS dv -SET tenant_id = d.tenant_id -FROM documents AS d -WHERE dv.document_id = d.id; -ALTER TABLE document_versions ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE document_versions - ADD CONSTRAINT document_versions_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX document_versions_tenant_id_idx ON document_versions (tenant_id); - --- Add tenant_id to document_assets -ALTER TABLE document_assets ADD COLUMN tenant_id UUID; -UPDATE document_assets AS da -SET tenant_id = dv.tenant_id -FROM document_versions AS dv -WHERE da.document_version_id = dv.id; -ALTER TABLE document_assets ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE document_assets - ADD CONSTRAINT document_assets_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX document_assets_tenant_id_idx ON document_assets (tenant_id); - --- Add tenant_id to document_asset_objects -ALTER TABLE document_asset_objects ADD COLUMN tenant_id UUID; -UPDATE document_asset_objects AS dao -SET tenant_id = da.tenant_id -FROM document_assets AS da -WHERE dao.asset_id = da.id; -ALTER TABLE document_asset_objects ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE document_asset_objects - ADD CONSTRAINT document_asset_objects_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX document_asset_objects_tenant_id_idx ON document_asset_objects (tenant_id); - --- Add tenant_id to document_tags -ALTER TABLE document_tags ADD COLUMN tenant_id UUID; -UPDATE document_tags AS dt -SET tenant_id = d.tenant_id -FROM documents AS d -WHERE dt.document_id = d.id; -ALTER TABLE document_tags ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE document_tags - ADD CONSTRAINT document_tags_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX document_tags_tenant_id_idx ON document_tags (tenant_id); - --- Add tenant_id to document_correspondents -ALTER TABLE document_correspondents ADD COLUMN tenant_id UUID; -UPDATE document_correspondents AS dc -SET tenant_id = d.tenant_id -FROM documents AS d -WHERE dc.document_id = d.id; -ALTER TABLE document_correspondents ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE document_correspondents - ADD CONSTRAINT document_correspondents_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX document_correspondents_tenant_id_idx ON document_correspondents (tenant_id); - --- Add tenant_id to correspondents -ALTER TABLE correspondents ADD COLUMN tenant_id UUID; -UPDATE correspondents -SET tenant_id = (SELECT tenant_id FROM public.tenants WHERE slug = 'admin'); -ALTER TABLE correspondents ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE correspondents - ADD CONSTRAINT correspondents_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX correspondents_tenant_id_idx ON correspondents (tenant_id); - --- Add tenant_id to tags -ALTER TABLE tags ADD COLUMN tenant_id UUID; -UPDATE tags -SET tenant_id = (SELECT tenant_id FROM public.tenants WHERE slug = 'admin'); -ALTER TABLE tags ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE tags - ADD CONSTRAINT tags_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX tags_tenant_id_idx ON tags (tenant_id); - --- Add tenant_id to folders -ALTER TABLE folders ADD COLUMN tenant_id UUID; -UPDATE folders -SET tenant_id = (SELECT tenant_id FROM public.tenants WHERE slug = 'admin'); -ALTER TABLE folders ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE folders - ADD CONSTRAINT folders_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX folders_tenant_id_idx ON folders (tenant_id); - --- Add tenant_id to users -ALTER TABLE users ADD COLUMN tenant_id UUID; --- Add tenant_id to refresh_tokens -ALTER TABLE refresh_tokens ADD COLUMN tenant_id UUID; -UPDATE refresh_tokens AS rt -SET tenant_id = ( - SELECT um.tenant_id - FROM user_memberships AS um - WHERE um.user_id = rt.user_id - LIMIT 1 -); -ALTER TABLE refresh_tokens ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE refresh_tokens - ADD CONSTRAINT refresh_tokens_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX refresh_tokens_tenant_id_idx ON refresh_tokens (tenant_id); - --- Add tenant_id to jobs -ALTER TABLE jobs ADD COLUMN tenant_id UUID; -UPDATE jobs -SET tenant_id = ( - SELECT um.tenant_id - FROM user_memberships AS um - WHERE um.user_id = jobs.user_id - LIMIT 1 -); -ALTER TABLE jobs ALTER COLUMN tenant_id SET NOT NULL; -ALTER TABLE jobs - ADD CONSTRAINT jobs_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(tenant_id); -CREATE INDEX jobs_tenant_id_idx ON jobs (tenant_id); diff --git a/backend/migrations/20240902150000_rename_tenants_id/down.sql b/backend/migrations/20240902150000_rename_tenants_id/down.sql deleted file mode 100644 index db3cee5..0000000 --- a/backend/migrations/20240902150000_rename_tenants_id/down.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE public.tenants RENAME COLUMN id TO tenant_id; diff --git a/backend/migrations/20240902150000_rename_tenants_id/up.sql b/backend/migrations/20240902150000_rename_tenants_id/up.sql deleted file mode 100644 index af5daab..0000000 --- a/backend/migrations/20240902150000_rename_tenants_id/up.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE public.tenants RENAME COLUMN tenant_id TO id; diff --git a/backend/migrations/20240902160000_add_tenant_unique_constraints/down.sql b/backend/migrations/20240902160000_add_tenant_unique_constraints/down.sql deleted file mode 100644 index 040cb42..0000000 --- a/backend/migrations/20240902160000_add_tenant_unique_constraints/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -DROP INDEX IF EXISTS tenants_quickwit_index_unique; -DROP INDEX IF EXISTS tenants_storage_root_unique; diff --git a/backend/migrations/20240902160000_add_tenant_unique_constraints/up.sql b/backend/migrations/20240902160000_add_tenant_unique_constraints/up.sql deleted file mode 100644 index 665f35c..0000000 --- a/backend/migrations/20240902160000_add_tenant_unique_constraints/up.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE UNIQUE INDEX tenants_storage_root_unique - ON public.tenants (storage_root) - WHERE storage_root IS NOT NULL; - -CREATE UNIQUE INDEX tenants_quickwit_index_unique - ON public.tenants (quickwit_index) - WHERE quickwit_index IS NOT NULL; diff --git a/backend/migrations/20240902164000_drop_users_tenant_id/down.sql b/backend/migrations/20240902164000_drop_users_tenant_id/down.sql deleted file mode 100644 index 3662792..0000000 --- a/backend/migrations/20240902164000_drop_users_tenant_id/down.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE users ADD COLUMN tenant_id UUID; diff --git a/backend/migrations/20240902164000_drop_users_tenant_id/up.sql b/backend/migrations/20240902164000_drop_users_tenant_id/up.sql deleted file mode 100644 index b154b4f..0000000 --- a/backend/migrations/20240902164000_drop_users_tenant_id/up.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE users DROP CONSTRAINT IF EXISTS users_tenant_id_fkey; -DROP INDEX IF EXISTS users_tenant_id_idx; -ALTER TABLE users DROP COLUMN IF EXISTS tenant_id; diff --git a/backend/migrations/202502130001_create_jobs/down.sql b/backend/migrations/202502130001_create_jobs/down.sql deleted file mode 100644 index 5f795aa..0000000 --- a/backend/migrations/202502130001_create_jobs/down.sql +++ /dev/null @@ -1,5 +0,0 @@ -DROP TRIGGER IF EXISTS trg_jobs_updated_at ON jobs; -DROP FUNCTION IF EXISTS touch_jobs_updated_at; -DROP INDEX IF EXISTS idx_jobs_job_type; -DROP INDEX IF EXISTS idx_jobs_status_run_after; -DROP TABLE IF EXISTS jobs; diff --git a/backend/migrations/202502130001_create_jobs/up.sql b/backend/migrations/202502130001_create_jobs/up.sql deleted file mode 100644 index 4d7f4a1..0000000 --- a/backend/migrations/202502130001_create_jobs/up.sql +++ /dev/null @@ -1,28 +0,0 @@ -CREATE TABLE jobs ( - id UUID PRIMARY KEY, - job_type TEXT NOT NULL, - payload JSONB NOT NULL, - status TEXT NOT NULL DEFAULT 'queued', - attempts INTEGER NOT NULL DEFAULT 0, - run_after TIMESTAMPTZ NOT NULL DEFAULT now(), - last_error TEXT, - created_at TIMESTAMPTZ NOT NULL DEFAULT now(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), - CONSTRAINT jobs_status_check CHECK (status IN ('queued', 'processing', 'succeeded', 'failed')) -); - -CREATE INDEX idx_jobs_status_run_after ON jobs (status, run_after); -CREATE INDEX idx_jobs_job_type ON jobs (job_type); - -CREATE OR REPLACE FUNCTION touch_jobs_updated_at() -RETURNS TRIGGER AS $$ -BEGIN - NEW.updated_at = now(); - RETURN NEW; -END; -$$ LANGUAGE plpgsql; - -CREATE TRIGGER trg_jobs_updated_at -BEFORE UPDATE ON jobs -FOR EACH ROW -EXECUTE FUNCTION touch_jobs_updated_at(); diff --git a/backend/migrations/202502130002_create_document_assets/down.sql b/backend/migrations/202502130002_create_document_assets/down.sql deleted file mode 100644 index 9976f4c..0000000 --- a/backend/migrations/202502130002_create_document_assets/down.sql +++ /dev/null @@ -1,3 +0,0 @@ -DROP INDEX IF EXISTS idx_document_assets_type; -DROP INDEX IF EXISTS idx_document_assets_version; -DROP TABLE IF EXISTS document_assets; diff --git a/backend/migrations/202502130002_create_document_assets/up.sql b/backend/migrations/202502130002_create_document_assets/up.sql deleted file mode 100644 index d9a1ff1..0000000 --- a/backend/migrations/202502130002_create_document_assets/up.sql +++ /dev/null @@ -1,15 +0,0 @@ -CREATE TABLE document_assets ( - id UUID PRIMARY KEY, - document_version_id UUID NOT NULL REFERENCES document_versions(id) ON DELETE CASCADE, - asset_type TEXT NOT NULL, - s3_key TEXT NOT NULL, - mime_type TEXT NOT NULL, - width INTEGER, - height INTEGER, - metadata JSONB NOT NULL DEFAULT '{}'::jsonb, - created_at TIMESTAMPTZ NOT NULL DEFAULT now(), - CONSTRAINT document_assets_unique UNIQUE (document_version_id, asset_type) -); - -CREATE INDEX idx_document_assets_version ON document_assets(document_version_id); -CREATE INDEX idx_document_assets_type ON document_assets(asset_type); diff --git a/backend/migrations/202503040001_enforce_unique_folder_names/down.sql b/backend/migrations/202503040001_enforce_unique_folder_names/down.sql deleted file mode 100644 index 7484794..0000000 --- a/backend/migrations/202503040001_enforce_unique_folder_names/down.sql +++ /dev/null @@ -1,4 +0,0 @@ -DROP INDEX IF EXISTS folders_parent_name_unique_idx; - -ALTER TABLE folders - ADD CONSTRAINT folders_parent_name_unique UNIQUE (parent_id, name); diff --git a/backend/migrations/202503040001_enforce_unique_folder_names/up.sql b/backend/migrations/202503040001_enforce_unique_folder_names/up.sql deleted file mode 100644 index 2164fb8..0000000 --- a/backend/migrations/202503040001_enforce_unique_folder_names/up.sql +++ /dev/null @@ -1,5 +0,0 @@ -ALTER TABLE folders - DROP CONSTRAINT IF EXISTS folders_parent_name_unique; - -CREATE UNIQUE INDEX folders_parent_name_unique_idx - ON folders (COALESCE(parent_id, '00000000-0000-0000-0000-000000000000'::uuid), name); diff --git a/backend/migrations/202503090001_add_issued_at_to_documents/down.sql b/backend/migrations/202503090001_add_issued_at_to_documents/down.sql deleted file mode 100644 index b576330..0000000 --- a/backend/migrations/202503090001_add_issued_at_to_documents/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE documents - DROP COLUMN issued_at; diff --git a/backend/migrations/202503090001_add_issued_at_to_documents/up.sql b/backend/migrations/202503090001_add_issued_at_to_documents/up.sql deleted file mode 100644 index 544e5b1..0000000 --- a/backend/migrations/202503090001_add_issued_at_to_documents/up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE documents - ADD COLUMN issued_at TIMESTAMPTZ; diff --git a/backend/migrations/202503090002_add_name_to_documents/down.sql b/backend/migrations/202503090002_add_name_to_documents/down.sql deleted file mode 100644 index 430458f..0000000 --- a/backend/migrations/202503090002_add_name_to_documents/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE documents - DROP COLUMN name; diff --git a/backend/migrations/202503090002_add_name_to_documents/up.sql b/backend/migrations/202503090002_add_name_to_documents/up.sql deleted file mode 100644 index b2bda83..0000000 --- a/backend/migrations/202503090002_add_name_to_documents/up.sql +++ /dev/null @@ -1,11 +0,0 @@ -ALTER TABLE documents - ADD COLUMN name VARCHAR(255); - -UPDATE documents -SET name = CASE - WHEN filename ~ '\\.[^./]+$' THEN regexp_replace(filename, '\\.[^./]+$', '') - ELSE filename -END; - -ALTER TABLE documents - ALTER COLUMN name SET NOT NULL; diff --git a/backend/migrations/202503090003_rename_name_to_title/down.sql b/backend/migrations/202503090003_rename_name_to_title/down.sql deleted file mode 100644 index 1470159..0000000 --- a/backend/migrations/202503090003_rename_name_to_title/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE documents - RENAME COLUMN title TO name; diff --git a/backend/migrations/202503090003_rename_name_to_title/up.sql b/backend/migrations/202503090003_rename_name_to_title/up.sql deleted file mode 100644 index 60487bf..0000000 --- a/backend/migrations/202503090003_rename_name_to_title/up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE documents - RENAME COLUMN name TO title; diff --git a/backend/migrations/202503090004_create_refresh_tokens/down.sql b/backend/migrations/202503090004_create_refresh_tokens/down.sql deleted file mode 100644 index 7f0336a..0000000 --- a/backend/migrations/202503090004_create_refresh_tokens/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE refresh_tokens; diff --git a/backend/migrations/202503090004_create_refresh_tokens/up.sql b/backend/migrations/202503090004_create_refresh_tokens/up.sql deleted file mode 100644 index 0ad106d..0000000 --- a/backend/migrations/202503090004_create_refresh_tokens/up.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE TABLE refresh_tokens ( - id UUID PRIMARY KEY, - user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, - token_hash TEXT NOT NULL, - issued_at TIMESTAMPTZ NOT NULL, - expires_at TIMESTAMPTZ NOT NULL, - revoked_at TIMESTAMPTZ, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() -); - -CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens(user_id); -CREATE INDEX idx_refresh_tokens_token_hash ON refresh_tokens(token_hash); diff --git a/backend/migrations/202503120001_drop_asset_dimensions/down.sql b/backend/migrations/202503120001_drop_asset_dimensions/down.sql deleted file mode 100644 index a7be2e1..0000000 --- a/backend/migrations/202503120001_drop_asset_dimensions/down.sql +++ /dev/null @@ -1,13 +0,0 @@ --- Restore width/height columns and repopulate from metadata where available. - -ALTER TABLE document_assets - ADD COLUMN width INTEGER, - ADD COLUMN height INTEGER; - -UPDATE document_assets -SET width = (metadata->>'width')::INTEGER -WHERE metadata ? 'width'; - -UPDATE document_assets -SET height = (metadata->>'height')::INTEGER -WHERE metadata ? 'height'; diff --git a/backend/migrations/202503120001_drop_asset_dimensions/up.sql b/backend/migrations/202503120001_drop_asset_dimensions/up.sql deleted file mode 100644 index d8b05f9..0000000 --- a/backend/migrations/202503120001_drop_asset_dimensions/up.sql +++ /dev/null @@ -1,15 +0,0 @@ --- Backfill existing width/height values into metadata then drop the columns. - -UPDATE document_assets -SET metadata = metadata || jsonb_build_object('width', width) -WHERE width IS NOT NULL - AND NOT (metadata ? 'width'); - -UPDATE document_assets -SET metadata = metadata || jsonb_build_object('height', height) -WHERE height IS NOT NULL - AND NOT (metadata ? 'height'); - -ALTER TABLE document_assets - DROP COLUMN width, - DROP COLUMN height; diff --git a/backend/migrations/202503120003_use_version_uuid/down.sql b/backend/migrations/202503120003_use_version_uuid/down.sql deleted file mode 100644 index 25bffa4..0000000 --- a/backend/migrations/202503120003_use_version_uuid/down.sql +++ /dev/null @@ -1,17 +0,0 @@ -ALTER TABLE documents ADD COLUMN current_version INT4; - -UPDATE documents AS d -SET current_version = dv.version_number -FROM document_versions AS dv -WHERE dv.id = d.current_version_id; - -ALTER TABLE documents - ALTER COLUMN current_version SET NOT NULL; - -DROP INDEX IF EXISTS idx_documents_current_version_id; - -ALTER TABLE documents - DROP CONSTRAINT IF EXISTS documents_current_version_fk; - -ALTER TABLE documents - DROP COLUMN current_version_id; diff --git a/backend/migrations/202503120003_use_version_uuid/up.sql b/backend/migrations/202503120003_use_version_uuid/up.sql deleted file mode 100644 index 101ef2d..0000000 --- a/backend/migrations/202503120003_use_version_uuid/up.sql +++ /dev/null @@ -1,21 +0,0 @@ -ALTER TABLE documents ADD COLUMN current_version_id UUID; - -UPDATE documents AS d -SET current_version_id = dv.id -FROM document_versions AS dv -WHERE dv.document_id = d.id - AND dv.version_number = d.current_version; - -ALTER TABLE documents - ALTER COLUMN current_version_id SET NOT NULL; - -ALTER TABLE documents - ADD CONSTRAINT documents_current_version_fk - FOREIGN KEY (current_version_id) - REFERENCES document_versions(id) - DEFERRABLE INITIALLY DEFERRED; - -CREATE INDEX idx_documents_current_version_id - ON documents(current_version_id); - -ALTER TABLE documents DROP COLUMN current_version; diff --git a/backend/migrations/202503200001_add_correspondents/down.sql b/backend/migrations/202503200001_add_correspondents/down.sql deleted file mode 100644 index 1490292..0000000 --- a/backend/migrations/202503200001_add_correspondents/down.sql +++ /dev/null @@ -1,5 +0,0 @@ -DROP INDEX IF EXISTS idx_document_correspondents_role; -DROP INDEX IF EXISTS idx_document_correspondents_correspondent; -DROP INDEX IF EXISTS idx_document_correspondents_document; -DROP TABLE IF EXISTS document_correspondents; -DROP TABLE IF EXISTS correspondents; diff --git a/backend/migrations/202503200001_add_correspondents/up.sql b/backend/migrations/202503200001_add_correspondents/up.sql deleted file mode 100644 index 600680b..0000000 --- a/backend/migrations/202503200001_add_correspondents/up.sql +++ /dev/null @@ -1,27 +0,0 @@ -CREATE TABLE correspondents ( - id UUID PRIMARY KEY, - name VARCHAR(255) NOT NULL, - metadata JSONB NOT NULL DEFAULT '{}'::jsonb, - created_at TIMESTAMPTZ NOT NULL DEFAULT now(), - updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), - CONSTRAINT correspondents_name_unique UNIQUE (name) -); - -CREATE TABLE document_correspondents ( - document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE, - correspondent_id UUID NOT NULL REFERENCES correspondents(id) ON DELETE CASCADE, - role VARCHAR(32) NOT NULL, - assigned_at TIMESTAMPTZ NOT NULL DEFAULT now(), - assigned_by UUID REFERENCES users(id), - PRIMARY KEY (document_id, correspondent_id, role), - CONSTRAINT document_correspondents_role_check CHECK (role IN ('sender', 'receiver', 'other')) -); - -CREATE INDEX idx_document_correspondents_document - ON document_correspondents(document_id); - -CREATE INDEX idx_document_correspondents_correspondent - ON document_correspondents(correspondent_id); - -CREATE INDEX idx_document_correspondents_role - ON document_correspondents(role); diff --git a/backend/migrations/202503240001_index_documents_by_folder_title/down.sql b/backend/migrations/202503240001_index_documents_by_folder_title/down.sql deleted file mode 100644 index e0c12fe..0000000 --- a/backend/migrations/202503240001_index_documents_by_folder_title/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -DROP INDEX IF EXISTS idx_documents_folder_filename; -DROP INDEX IF EXISTS idx_documents_folder_title; diff --git a/backend/migrations/202503240001_index_documents_by_folder_title/up.sql b/backend/migrations/202503240001_index_documents_by_folder_title/up.sql deleted file mode 100644 index 116f09e..0000000 --- a/backend/migrations/202503240001_index_documents_by_folder_title/up.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE INDEX idx_documents_folder_title - ON documents ( - COALESCE(folder_id, '00000000-0000-0000-0000-000000000000'::uuid), - title - ) - WHERE deleted_at IS NULL; - -CREATE INDEX idx_documents_folder_filename - ON documents ( - COALESCE(folder_id, '00000000-0000-0000-0000-000000000000'::uuid), - filename - ) - WHERE deleted_at IS NULL; diff --git a/backend/migrations/202503240002_unique_document_names/down.sql b/backend/migrations/202503240002_unique_document_names/down.sql deleted file mode 100644 index 648a7ed..0000000 --- a/backend/migrations/202503240002_unique_document_names/down.sql +++ /dev/null @@ -1,16 +0,0 @@ -DROP INDEX IF EXISTS documents_unique_folder_filename; -DROP INDEX IF EXISTS idx_documents_folder_title; - -CREATE INDEX idx_documents_folder_title - ON documents ( - COALESCE(folder_id, '00000000-0000-0000-0000-000000000000'::uuid), - title - ) - WHERE deleted_at IS NULL; - -CREATE INDEX idx_documents_folder_filename - ON documents ( - COALESCE(folder_id, '00000000-0000-0000-0000-000000000000'::uuid), - filename - ) - WHERE deleted_at IS NULL; diff --git a/backend/migrations/202503240002_unique_document_names/up.sql b/backend/migrations/202503240002_unique_document_names/up.sql deleted file mode 100644 index a48b8b3..0000000 --- a/backend/migrations/202503240002_unique_document_names/up.sql +++ /dev/null @@ -1,18 +0,0 @@ -DROP INDEX IF EXISTS idx_documents_folder_title; -DROP INDEX IF EXISTS idx_documents_folder_filename; -DROP INDEX IF EXISTS documents_unique_folder_title; -DROP INDEX IF EXISTS documents_unique_folder_filename; - -CREATE INDEX idx_documents_folder_title - ON documents ( - COALESCE(folder_id, '00000000-0000-0000-0000-000000000000'::uuid), - title - ) - WHERE deleted_at IS NULL; - -CREATE UNIQUE INDEX documents_unique_folder_filename - ON documents ( - COALESCE(folder_id, '00000000-0000-0000-0000-000000000000'::uuid), - filename - ) - WHERE deleted_at IS NULL; diff --git a/backend/migrations/202503240003_add_metadata_to_document_versions/down.sql b/backend/migrations/202503240003_add_metadata_to_document_versions/down.sql deleted file mode 100644 index 1df5398..0000000 --- a/backend/migrations/202503240003_add_metadata_to_document_versions/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE document_versions - DROP COLUMN metadata; diff --git a/backend/migrations/202503240003_add_metadata_to_document_versions/up.sql b/backend/migrations/202503240003_add_metadata_to_document_versions/up.sql deleted file mode 100644 index 7b941e3..0000000 --- a/backend/migrations/202503240003_add_metadata_to_document_versions/up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE document_versions - ADD COLUMN metadata JSONB NOT NULL DEFAULT '{}'::jsonb; diff --git a/backend/migrations/202503240004_drop_folder_path_cache/down.sql b/backend/migrations/202503240004_drop_folder_path_cache/down.sql deleted file mode 100644 index 41af8f9..0000000 --- a/backend/migrations/202503240004_drop_folder_path_cache/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE folders - ADD COLUMN path_cache VARCHAR(1000); diff --git a/backend/migrations/202503240004_drop_folder_path_cache/up.sql b/backend/migrations/202503240004_drop_folder_path_cache/up.sql deleted file mode 100644 index fc3cfcf..0000000 --- a/backend/migrations/202503240004_drop_folder_path_cache/up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE folders - DROP COLUMN path_cache; diff --git a/backend/migrations/202503240005_create_document_asset_objects/down.sql b/backend/migrations/202503240005_create_document_asset_objects/down.sql deleted file mode 100644 index f4ce4ef..0000000 --- a/backend/migrations/202503240005_create_document_asset_objects/down.sql +++ /dev/null @@ -1,34 +0,0 @@ -ALTER TABLE document_assets - ADD COLUMN s3_key TEXT; - -UPDATE document_assets AS da -SET s3_key = dao.s3_key -FROM document_asset_objects AS dao -WHERE dao.asset_id = da.id - AND dao.ordinal = 1 - AND da.s3_key IS NULL; - -ALTER TABLE document_assets - ALTER COLUMN s3_key SET NOT NULL; - -UPDATE document_assets AS da -SET metadata = jsonb_set(da.metadata, '{width}', dao.metadata->'width', true) -FROM document_asset_objects AS dao -WHERE dao.asset_id = da.id - AND dao.ordinal = 1 - AND dao.metadata ? 'width'; - -UPDATE document_assets AS da -SET metadata = jsonb_set(da.metadata, '{height}', dao.metadata->'height', true) -FROM document_asset_objects AS dao -WHERE dao.asset_id = da.id - AND dao.ordinal = 1 - AND dao.metadata ? 'height'; - -DROP INDEX IF EXISTS idx_document_asset_objects_asset_ordinal; -DROP TABLE IF EXISTS document_asset_objects; - -ALTER TABLE document_assets - DROP CONSTRAINT IF EXISTS document_assets_cardinality_positive; -ALTER TABLE document_assets - DROP COLUMN IF EXISTS cardinality; diff --git a/backend/migrations/202503240005_create_document_asset_objects/up.sql b/backend/migrations/202503240005_create_document_asset_objects/up.sql deleted file mode 100644 index 46574e5..0000000 --- a/backend/migrations/202503240005_create_document_asset_objects/up.sql +++ /dev/null @@ -1,54 +0,0 @@ -ALTER TABLE document_assets - ADD COLUMN cardinality INTEGER, - ADD CONSTRAINT document_assets_cardinality_positive CHECK (cardinality IS NULL OR cardinality >= 1); - -CREATE TABLE document_asset_objects ( - id UUID PRIMARY KEY, - asset_id UUID NOT NULL REFERENCES document_assets(id) ON DELETE CASCADE, - ordinal INTEGER NOT NULL, - s3_key TEXT NOT NULL, - metadata JSONB NOT NULL DEFAULT '{}'::jsonb, - CONSTRAINT document_asset_objects_ordinal_positive CHECK (ordinal >= 1), - CONSTRAINT document_asset_objects_asset_ordinal_unique UNIQUE (asset_id, ordinal) -); - -CREATE INDEX idx_document_asset_objects_asset_ordinal - ON document_asset_objects (asset_id, ordinal); - -INSERT INTO document_asset_objects (id, asset_id, ordinal, s3_key, metadata) -SELECT - gen_random_uuid(), - id, - 1, - s3_key, - '{}'::jsonb -FROM document_assets; - -UPDATE document_asset_objects AS dao -SET metadata = jsonb_set(dao.metadata, '{width}', da.metadata->'width', true) -FROM document_assets AS da -WHERE dao.asset_id = da.id - AND dao.ordinal = 1 - AND da.metadata ? 'width'; - -UPDATE document_asset_objects AS dao -SET metadata = jsonb_set(dao.metadata, '{height}', da.metadata->'height', true) -FROM document_assets AS da -WHERE dao.asset_id = da.id - AND dao.ordinal = 1 - AND da.metadata ? 'height'; - -UPDATE document_assets -SET metadata = metadata - 'width' -WHERE metadata ? 'width'; - -UPDATE document_assets -SET metadata = metadata - 'height' -WHERE metadata ? 'height'; - -UPDATE document_assets -SET cardinality = 1 -WHERE cardinality IS NULL; - -ALTER TABLE document_assets - DROP COLUMN s3_key; diff --git a/backend/migrations/202503260001_initial_schema/down.sql b/backend/migrations/202503260001_initial_schema/down.sql new file mode 100644 index 0000000..acd7e40 --- /dev/null +++ b/backend/migrations/202503260001_initial_schema/down.sql @@ -0,0 +1,21 @@ +DROP TRIGGER IF EXISTS trg_jobs_updated_at ON jobs; +DROP FUNCTION IF EXISTS touch_jobs_updated_at(); + +ALTER TABLE documents DROP CONSTRAINT IF EXISTS documents_current_version_fk; + +DROP TABLE IF EXISTS document_asset_objects; +DROP TABLE IF EXISTS document_assets; +DROP TABLE IF EXISTS document_versions; +DROP TABLE IF EXISTS document_tags; +DROP TABLE IF EXISTS document_correspondents; +DROP TABLE IF EXISTS correspondents; +DROP TABLE IF EXISTS documents; +DROP TABLE IF EXISTS folders; +DROP TABLE IF EXISTS tags; +DROP TABLE IF EXISTS jobs; +DROP TABLE IF EXISTS refresh_tokens; +DROP TABLE IF EXISTS user_memberships; +DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS tenants; + +DROP EXTENSION IF EXISTS "pgcrypto"; diff --git a/backend/migrations/202503260001_initial_schema/up.sql b/backend/migrations/202503260001_initial_schema/up.sql new file mode 100644 index 0000000..bb328f3 --- /dev/null +++ b/backend/migrations/202503260001_initial_schema/up.sql @@ -0,0 +1,244 @@ +CREATE EXTENSION IF NOT EXISTS "pgcrypto"; + +CREATE TABLE tenants ( + id UUID PRIMARY KEY, + slug TEXT NOT NULL UNIQUE, + storage_root TEXT, + quickwit_index TEXT, + status TEXT NOT NULL DEFAULT 'active', + config JSONB NOT NULL DEFAULT '{}'::jsonb, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE UNIQUE INDEX tenants_storage_root_unique + ON tenants (storage_root) + WHERE storage_root IS NOT NULL; + +CREATE UNIQUE INDEX tenants_quickwit_index_unique + ON tenants (quickwit_index) + WHERE quickwit_index IS NOT NULL; + +CREATE TABLE users ( + id UUID PRIMARY KEY, + username VARCHAR(100) NOT NULL UNIQUE, + password_hash VARCHAR(255) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE TABLE user_memberships ( + id UUID PRIMARY KEY, + user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, + tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE, + role TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (user_id, tenant_id) +); + +CREATE INDEX user_memberships_tenant_id_idx ON user_memberships (tenant_id); +CREATE INDEX user_memberships_user_id_idx ON user_memberships (user_id); + +CREATE TABLE folders ( + id UUID PRIMARY KEY, + name VARCHAR(255) NOT NULL, + parent_id UUID REFERENCES folders(id) ON DELETE SET NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + tenant_id UUID NOT NULL REFERENCES tenants(id) +); + +CREATE INDEX idx_folders_parent ON folders(parent_id); +CREATE INDEX folders_tenant_id_idx ON folders(tenant_id); +CREATE UNIQUE INDEX folders_parent_name_unique_idx + ON folders (COALESCE(parent_id, '00000000-0000-0000-0000-000000000000'::uuid), name); + +CREATE TABLE documents ( + id UUID PRIMARY KEY, + filename VARCHAR(255) NOT NULL, + original_name VARCHAR(255) NOT NULL, + content_type VARCHAR(100), + folder_id UUID REFERENCES folders(id) ON DELETE SET NULL, + uploaded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + deleted_at TIMESTAMPTZ, + metadata JSONB NOT NULL DEFAULT '{}'::jsonb, + issued_at TIMESTAMPTZ, + title VARCHAR(255) NOT NULL, + current_version_id UUID NOT NULL, + tenant_id UUID NOT NULL REFERENCES tenants(id) +); + +CREATE INDEX idx_documents_folder ON documents (folder_id); +CREATE INDEX idx_documents_deleted_at ON documents (deleted_at); +CREATE INDEX documents_tenant_id_idx ON documents (tenant_id); +CREATE INDEX idx_documents_current_version_id ON documents (current_version_id); + +CREATE INDEX idx_documents_folder_title + ON documents ( + COALESCE(folder_id, '00000000-0000-0000-0000-000000000000'::uuid), + title + ) + WHERE deleted_at IS NULL; + +CREATE UNIQUE INDEX documents_unique_folder_filename + ON documents ( + COALESCE(folder_id, '00000000-0000-0000-0000-000000000000'::uuid), + filename + ) + WHERE deleted_at IS NULL; + +CREATE TABLE document_versions ( + id UUID PRIMARY KEY, + document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE, + version_number INT NOT NULL, + s3_key VARCHAR(500) NOT NULL, + size_bytes BIGINT NOT NULL, + checksum VARCHAR(64) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + operations_summary JSONB NOT NULL DEFAULT '{}'::jsonb, + metadata JSONB NOT NULL DEFAULT '{}'::jsonb, + tenant_id UUID NOT NULL REFERENCES tenants(id), + CONSTRAINT document_versions_unique_version UNIQUE (document_id, version_number) +); + +CREATE INDEX idx_document_versions_document ON document_versions (document_id); +CREATE INDEX document_versions_tenant_id_idx ON document_versions (tenant_id); + +ALTER TABLE documents + ADD CONSTRAINT documents_current_version_fk + FOREIGN KEY (current_version_id) + REFERENCES document_versions(id) + DEFERRABLE INITIALLY DEFERRED; + +CREATE TABLE tags ( + id UUID PRIMARY KEY, + label VARCHAR(100) NOT NULL UNIQUE, + color VARCHAR(7), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + tenant_id UUID NOT NULL REFERENCES tenants(id) +); + +CREATE INDEX tags_tenant_id_idx ON tags (tenant_id); + +CREATE TABLE document_tags ( + document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE, + tag_id UUID NOT NULL REFERENCES tags(id) ON DELETE CASCADE, + assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + assigned_by UUID REFERENCES users(id), + tenant_id UUID NOT NULL REFERENCES tenants(id), + PRIMARY KEY (document_id, tag_id) +); + +CREATE INDEX idx_document_tags_tag ON document_tags (tag_id); +CREATE INDEX document_tags_tenant_id_idx ON document_tags (tenant_id); + +CREATE TABLE correspondents ( + id UUID PRIMARY KEY, + name VARCHAR(255) NOT NULL, + metadata JSONB NOT NULL DEFAULT '{}'::jsonb, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + tenant_id UUID NOT NULL REFERENCES tenants(id), + CONSTRAINT correspondents_name_unique UNIQUE (name) +); + +CREATE INDEX correspondents_tenant_id_idx ON correspondents (tenant_id); + +CREATE TABLE document_correspondents ( + document_id UUID NOT NULL REFERENCES documents(id) ON DELETE CASCADE, + correspondent_id UUID NOT NULL REFERENCES correspondents(id) ON DELETE CASCADE, + role VARCHAR(32) NOT NULL, + assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + assigned_by UUID REFERENCES users(id), + tenant_id UUID NOT NULL REFERENCES tenants(id), + PRIMARY KEY (document_id, correspondent_id, role), + CONSTRAINT document_correspondents_role_check CHECK (role IN ('sender', 'receiver', 'other')) +); + +CREATE INDEX idx_document_correspondents_document ON document_correspondents (document_id); +CREATE INDEX idx_document_correspondents_correspondent ON document_correspondents (correspondent_id); +CREATE INDEX idx_document_correspondents_role ON document_correspondents (role); +CREATE INDEX document_correspondents_tenant_id_idx ON document_correspondents (tenant_id); + +CREATE TABLE document_assets ( + id UUID PRIMARY KEY, + document_version_id UUID NOT NULL REFERENCES document_versions(id) ON DELETE CASCADE, + asset_type TEXT NOT NULL, + mime_type TEXT NOT NULL, + metadata JSONB NOT NULL DEFAULT '{}'::jsonb, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + cardinality INTEGER, + tenant_id UUID NOT NULL REFERENCES tenants(id), + CONSTRAINT document_assets_unique UNIQUE (document_version_id, asset_type), + CONSTRAINT document_assets_cardinality_positive CHECK (cardinality IS NULL OR cardinality >= 1) +); + +CREATE INDEX idx_document_assets_version ON document_assets (document_version_id); +CREATE INDEX idx_document_assets_type ON document_assets (asset_type); +CREATE INDEX document_assets_tenant_id_idx ON document_assets (tenant_id); + +CREATE TABLE document_asset_objects ( + id UUID PRIMARY KEY, + asset_id UUID NOT NULL REFERENCES document_assets(id) ON DELETE CASCADE, + ordinal INTEGER NOT NULL, + s3_key TEXT NOT NULL, + metadata JSONB NOT NULL DEFAULT '{}'::jsonb, + tenant_id UUID NOT NULL REFERENCES tenants(id), + CONSTRAINT document_asset_objects_ordinal_positive CHECK (ordinal >= 1), + CONSTRAINT document_asset_objects_asset_ordinal_unique UNIQUE (asset_id, ordinal) +); + +CREATE INDEX idx_document_asset_objects_asset_ordinal + ON document_asset_objects (asset_id, ordinal); + +CREATE INDEX document_asset_objects_tenant_id_idx + ON document_asset_objects (tenant_id); + +CREATE TABLE jobs ( + id UUID PRIMARY KEY, + job_type TEXT NOT NULL, + payload JSONB NOT NULL, + status TEXT NOT NULL DEFAULT 'queued', + attempts INTEGER NOT NULL DEFAULT 0, + run_after TIMESTAMPTZ NOT NULL DEFAULT NOW(), + last_error TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + tenant_id UUID NOT NULL REFERENCES tenants(id), + CONSTRAINT jobs_status_check CHECK (status IN ('queued', 'processing', 'succeeded', 'failed')) +); + +CREATE INDEX idx_jobs_status_run_after ON jobs (status, run_after); +CREATE INDEX idx_jobs_job_type ON jobs (job_type); +CREATE INDEX jobs_tenant_id_idx ON jobs (tenant_id); + +CREATE OR REPLACE FUNCTION touch_jobs_updated_at() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER trg_jobs_updated_at +BEFORE UPDATE ON jobs +FOR EACH ROW +EXECUTE FUNCTION touch_jobs_updated_at(); + +CREATE TABLE refresh_tokens ( + id UUID PRIMARY KEY, + user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, + token_hash TEXT NOT NULL, + issued_at TIMESTAMPTZ NOT NULL, + expires_at TIMESTAMPTZ NOT NULL, + revoked_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + tenant_id UUID NOT NULL REFERENCES tenants(id) +); + +CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens (user_id); +CREATE INDEX idx_refresh_tokens_token_hash ON refresh_tokens (token_hash); +CREATE INDEX refresh_tokens_tenant_id_idx ON refresh_tokens (tenant_id); diff --git a/docker-compose.test.yml b/docker-compose.test.yml index ea2b6e1..d9cd0f4 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -10,19 +10,19 @@ services: tmpfs: - /var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U papercrate"] + test: ["CMD-SHELL", "pg_isready -U papercrate -d papercrate_test"] interval: 5s timeout: 5s retries: 5 - quickwit: + quickwit-test: image: quickwit/quickwit:0.8.2 command: ["run"] environment: QW_ENABLE_API_AUTH: "false" QW_DATA_DIR: /quickwit/data ports: - - "7280:7280" + - "7281:7280" volumes: - quickwit_test_data:/quickwit/data healthcheck: @@ -31,21 +31,40 @@ services: timeout: 5s retries: 5 - quickwit-create-index: - image: quickwit/quickwit:0.8.2 + admin-bootstrap: + build: + context: ./backend depends_on: - quickwit: + postgres-test: + condition: service_healthy + quickwit-test: condition: service_healthy - volumes: - - quickwit_test_data:/quickwit/data - - ./quickwit/documents-index.yaml:/tmp/documents-index.yaml:ro environment: - QW_DATA_DIR: /quickwit/data - QW_NODE_URI: http://quickwit:7280 - entrypoint: ["/bin/sh", "-c"] + DATABASE_URL: postgres://papercrate:papercrate_test@postgres-test:5432/papercrate_test + DATABASE_MAX_POOL_SIZE: 1 + S3_BUCKET: documents + JWT_SECRET: change-me-super-secret + QUICKWIT_ENDPOINT: http://quickwit-test:7280 + DEFAULT_TENANT_SLUG: admin + entrypoint: [] command: > - quickwit index list --node-uri http://quickwit:7280 2>/dev/null | grep -q '"documents"' \ - || quickwit index create --index-config /tmp/documents-index.yaml --node-uri http://quickwit:7280 + /bin/sh -c " + echo 'Running database migrations' && + diesel migration run && + echo 'Ensuring tenant admin exists' && + if papercrate-admin list-tenants | grep -q '^admin '; then + echo 'tenant admin already exists'; + else + papercrate-admin create-tenant admin; + fi && + echo 'Ensuring demo user credentials' && + (papercrate-admin create-user admin adminadmin || papercrate-admin set-password admin adminadmin) && + echo 'Ensuring demo membership' && + papercrate-admin add-user-to-tenant admin admin admin && + echo 'Ensuring Quickwit index for admin tenant' && + papercrate-admin quickwit-create-index admin + " + user: root restart: "no" volumes: diff --git a/docker-compose.yml b/docker-compose.yml index 9f23291..29bb5f8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -62,15 +62,44 @@ services: timeout: 5s retries: 5 - quickwit-create-index: - image: quickwit/quickwit:0.8.2 + admin-bootstrap: + build: + context: ./backend depends_on: + postgres: + condition: service_healthy quickwit: condition: service_healthy - volumes: - - quickwit_data:/quickwit/data - - ./quickwit/documents-index.yaml:/tmp/documents-index.yaml:ro - command: index create --endpoint=http://quickwit:7280 --index-config /tmp/documents-index.yaml + environment: + DATABASE_URL: postgres://papercrate:papercrate_dev@postgres:5432/papercrate + DATABASE_MAX_POOL_SIZE: 2 + AWS_ENDPOINT_URL: http://minio:9000 + AWS_ACCESS_KEY_ID: minioadmin + AWS_SECRET_ACCESS_KEY: minioadmin + AWS_REGION: us-east-1 + S3_BUCKET: documents + JWT_SECRET: change-me-super-secret + QUICKWIT_ENDPOINT: http://quickwit:7280 + DEFAULT_TENANT_SLUG: admin + entrypoint: [] + command: > + /bin/sh -c " + echo 'Running database migrations' && + diesel migration run && + echo 'Ensuring tenant admin exists' && + if papercrate-admin list-tenants | grep -q '^admin '; then + echo 'tenant admin already exists'; + else + papercrate-admin create-tenant admin; + fi && + echo 'Ensuring demo user credentials' && + (papercrate-admin create-user admin adminadmin || papercrate-admin set-password admin adminadmin) && + echo 'Ensuring demo membership' && + papercrate-admin add-user-to-tenant admin admin admin && + echo 'Ensuring Quickwit index for admin tenant' && + papercrate-admin quickwit-create-index admin + " + user: root restart: "no" volumes: