feat: groups

This commit is contained in:
Jason Rasmussen
2025-07-30 18:18:38 -04:00
parent 641a3baadd
commit 4a881022c3
76 changed files with 6515 additions and 124 deletions
+40
View File
@@ -165,6 +165,46 @@ export const album_user_delete_audit = registerFunction({
END`,
});
export const album_group_delete_audit = registerFunction({
name: 'album_group_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO "album_audit" ("albumId", "userId")
SELECT OLD."albumId", "group_user"."userId"
FROM OLD INNER JOIN "group_user" ON "group_user"."groupId" = OLD."groupId";
IF pg_trigger_depth() = 1 THEN
INSERT INTO album_group_audit ("albumId", "groupId")
SELECT "albumId", "groupId"
FROM OLD;
END IF;
RETURN NULL;
END`,
});
export const group_user_delete_audit = registerFunction({
name: 'group_user_delete_audit',
returnType: 'TRIGGER',
language: 'PLPGSQL',
body: `
BEGIN
INSERT INTO group_audit ("groupId", "userId")
SELECT "groupId", "userId"
FROM OLD;
IF pg_trigger_depth() = 1 THEN
INSERT INTO group_user_audit ("groupId", "userId")
SELECT "groupId", "userId"
FROM OLD;
END IF;
RETURN NULL;
END`,
});
export const memory_delete_audit = registerFunction({
name: 'memory_delete_audit',
returnType: 'TRIGGER',
+22 -3
View File
@@ -22,6 +22,8 @@ import { ActivityTable } from 'src/schema/tables/activity.table';
import { AlbumAssetAuditTable } from 'src/schema/tables/album-asset-audit.table';
import { AlbumAssetTable } from 'src/schema/tables/album-asset.table';
import { AlbumAuditTable } from 'src/schema/tables/album-audit.table';
import { AlbumGroupAuditTable } from 'src/schema/tables/album-group-audit.table';
import { AlbumGroupTable } from 'src/schema/tables/album-group.table';
import { AlbumUserAuditTable } from 'src/schema/tables/album-user-audit.table';
import { AlbumUserTable } from 'src/schema/tables/album-user.table';
import { AlbumTable } from 'src/schema/tables/album.table';
@@ -36,6 +38,10 @@ import { AssetTable } from 'src/schema/tables/asset.table';
import { AuditTable } from 'src/schema/tables/audit.table';
import { FaceSearchTable } from 'src/schema/tables/face-search.table';
import { GeodataPlacesTable } from 'src/schema/tables/geodata-places.table';
import { GroupAuditTable } from 'src/schema/tables/group-audit.table';
import { GroupUserAuditTable } from 'src/schema/tables/group-user-audit.table';
import { GroupUserTable } from 'src/schema/tables/group-user.table';
import { GroupTable } from 'src/schema/tables/group.table';
import { LibraryTable } from 'src/schema/tables/library.table';
import { MemoryAssetAuditTable } from 'src/schema/tables/memory-asset-audit.table';
import { MemoryAssetTable } from 'src/schema/tables/memory-asset.table';
@@ -71,12 +77,14 @@ import { Database, Extensions, Generated, Int8 } from 'src/sql-tools';
export class ImmichDatabase {
tables = [
ActivityTable,
AlbumAssetTable,
AlbumAssetAuditTable,
AlbumAuditTable,
AlbumTable,
AlbumGroupTable,
AlbumGroupAuditTable,
AlbumUserAuditTable,
AlbumUserTable,
AlbumTable,
AlbumAssetTable,
AlbumAssetAuditTable,
ApiKeyTable,
AssetAuditTable,
AssetFaceTable,
@@ -88,6 +96,10 @@ export class ImmichDatabase {
AssetExifTable,
FaceSearchTable,
GeodataPlacesTable,
GroupTable,
GroupAuditTable,
GroupUserTable,
GroupUserAuditTable,
LibraryTable,
MemoryTable,
MemoryAuditTable,
@@ -154,6 +166,8 @@ export interface DB {
album_audit: AlbumAuditTable;
album_asset: AlbumAssetTable;
album_asset_audit: AlbumAssetAuditTable;
album_group: AlbumGroupTable;
album_group_audit: AlbumGroupAuditTable;
album_user: AlbumUserTable;
album_user_audit: AlbumUserAuditTable;
@@ -173,6 +187,11 @@ export interface DB {
geodata_places: GeodataPlacesTable;
group: GroupTable;
group_audit: GroupAuditTable;
group_user: GroupUserTable;
group_user_audit: GroupUserAuditTable;
library: LibraryTable;
memory: MemoryTable;
@@ -0,0 +1,118 @@
import { Kysely, sql } from 'kysely';
export async function up(db: Kysely<any>): Promise<void> {
await sql`CREATE OR REPLACE FUNCTION group_delete_audit()
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS $$
BEGIN
INSERT INTO group_audit ("groupId")
SELECT "id"
FROM OLD;
RETURN NULL;
END
$$;`.execute(db);
await sql`CREATE OR REPLACE FUNCTION group_user_delete_audit()
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS $$
BEGIN
INSERT INTO group_audit ("groupId", "userId")
SELECT "groupId", "userId"
FROM OLD;
IF pg_trigger_depth() = 1 THEN
INSERT INTO group_user_audit ("groupId", "userId")
SELECT "groupId", "userId"
FROM OLD;
END IF;
RETURN NULL;
END
$$;`.execute(db);
await sql`CREATE TABLE "group_audit" (
"id" uuid NOT NULL DEFAULT immich_uuid_v7(),
"groupId" uuid NOT NULL,
"deletedAt" timestamp with time zone NOT NULL DEFAULT clock_timestamp(),
CONSTRAINT "group_audit_pkey" PRIMARY KEY ("id")
);`.execute(db);
await sql`CREATE INDEX "group_audit_deletedAt_idx" ON "group_audit" ("deletedAt");`.execute(db);
await sql`CREATE TABLE "group_user_audit" (
"id" uuid NOT NULL DEFAULT immich_uuid_v7(),
"groupId" uuid NOT NULL,
"userId" uuid NOT NULL,
"deletedAt" timestamp with time zone NOT NULL DEFAULT clock_timestamp(),
CONSTRAINT "group_user_audit_pkey" PRIMARY KEY ("id")
);`.execute(db);
await sql`CREATE INDEX "group_user_audit_groupId_idx" ON "group_user_audit" ("groupId");`.execute(db);
await sql`CREATE INDEX "group_user_audit_userId_idx" ON "group_user_audit" ("userId");`.execute(db);
await sql`CREATE INDEX "group_user_audit_deletedAt_idx" ON "group_user_audit" ("deletedAt");`.execute(db);
await sql`CREATE TABLE "group_user" (
"groupId" uuid NOT NULL,
"userId" uuid NOT NULL,
"createId" uuid NOT NULL DEFAULT immich_uuid_v7(),
"createdAt" timestamp with time zone NOT NULL DEFAULT now(),
"updateId" uuid NOT NULL DEFAULT immich_uuid_v7(),
"updatedAt" timestamp with time zone NOT NULL DEFAULT now(),
CONSTRAINT "group_user_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "album" ("id") ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT "group_user_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT "group_user_pkey" PRIMARY KEY ("groupId", "userId")
);`.execute(db);
await sql`CREATE INDEX "group_user_groupId_idx" ON "group_user" ("groupId");`.execute(db);
await sql`CREATE INDEX "group_user_userId_idx" ON "group_user" ("userId");`.execute(db);
await sql`CREATE INDEX "group_user_createId_idx" ON "group_user" ("createId");`.execute(db);
await sql`CREATE INDEX "group_user_updateId_idx" ON "group_user" ("updateId");`.execute(db);
await sql`CREATE OR REPLACE TRIGGER "group_user_delete_audit"
AFTER DELETE ON "group_user"
REFERENCING OLD TABLE AS "old"
FOR EACH STATEMENT
WHEN (pg_trigger_depth() <= 1)
EXECUTE FUNCTION group_user_delete_audit();`.execute(db);
await sql`CREATE OR REPLACE TRIGGER "group_user_updatedAt"
BEFORE UPDATE ON "group_user"
FOR EACH ROW
EXECUTE FUNCTION updated_at();`.execute(db);
await sql`CREATE TABLE "group" (
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
"name" character varying NOT NULL,
"description" character varying,
"createdAt" timestamp with time zone NOT NULL DEFAULT now(),
"updatedAt" timestamp with time zone NOT NULL DEFAULT now(),
"updateId" uuid NOT NULL DEFAULT immich_uuid_v7(),
CONSTRAINT "group_name_uq" UNIQUE ("name"),
CONSTRAINT "group_pkey" PRIMARY KEY ("id")
);`.execute(db);
await sql`CREATE INDEX "group_updatedAt_id_idx" ON "group" ("updatedAt", "id");`.execute(db);
await sql`CREATE INDEX "group_updateId_idx" ON "group" ("updateId");`.execute(db);
await sql`CREATE OR REPLACE TRIGGER "group_delete_audit"
AFTER DELETE ON "group"
REFERENCING OLD TABLE AS "old"
FOR EACH STATEMENT
WHEN (pg_trigger_depth() = 0)
EXECUTE FUNCTION group_delete_audit();`.execute(db);
await sql`CREATE OR REPLACE TRIGGER "group_updatedAt"
BEFORE UPDATE ON "group"
FOR EACH ROW
EXECUTE FUNCTION updated_at();`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('function_group_delete_audit', '{"type":"function","name":"group_delete_audit","sql":"CREATE OR REPLACE FUNCTION group_delete_audit()\\n RETURNS TRIGGER\\n LANGUAGE PLPGSQL\\n AS $$\\n BEGIN\\n INSERT INTO group_audit (\\"groupId\\")\\n SELECT \\"id\\"\\n FROM OLD;\\n RETURN NULL;\\n END\\n $$;"}'::jsonb);`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('function_group_user_delete_audit', '{"type":"function","name":"group_user_delete_audit","sql":"CREATE OR REPLACE FUNCTION group_user_delete_audit()\\n RETURNS TRIGGER\\n LANGUAGE PLPGSQL\\n AS $$\\n BEGIN\\n INSERT INTO group_audit (\\"groupId\\", \\"userId\\")\\n SELECT \\"groupId\\", \\"userId\\"\\n FROM OLD;\\n\\n IF pg_trigger_depth() = 1 THEN\\n INSERT INTO group_user_audit (\\"groupId\\", \\"userId\\")\\n SELECT \\"groupId\\", \\"userId\\"\\n FROM OLD;\\n END IF;\\n\\n RETURN NULL;\\n END\\n $$;"}'::jsonb);`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('trigger_group_user_delete_audit', '{"type":"trigger","name":"group_user_delete_audit","sql":"CREATE OR REPLACE TRIGGER \\"group_user_delete_audit\\"\\n AFTER DELETE ON \\"group_user\\"\\n REFERENCING OLD TABLE AS \\"old\\"\\n FOR EACH STATEMENT\\n WHEN (pg_trigger_depth() <= 1)\\n EXECUTE FUNCTION group_user_delete_audit();"}'::jsonb);`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('trigger_group_user_updatedAt', '{"type":"trigger","name":"group_user_updatedAt","sql":"CREATE OR REPLACE TRIGGER \\"group_user_updatedAt\\"\\n BEFORE UPDATE ON \\"group_user\\"\\n FOR EACH ROW\\n EXECUTE FUNCTION updated_at();"}'::jsonb);`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('trigger_group_delete_audit', '{"type":"trigger","name":"group_delete_audit","sql":"CREATE OR REPLACE TRIGGER \\"group_delete_audit\\"\\n AFTER DELETE ON \\"group\\"\\n REFERENCING OLD TABLE AS \\"old\\"\\n FOR EACH STATEMENT\\n WHEN (pg_trigger_depth() = 0)\\n EXECUTE FUNCTION group_delete_audit();"}'::jsonb);`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('trigger_group_updatedAt', '{"type":"trigger","name":"group_updatedAt","sql":"CREATE OR REPLACE TRIGGER \\"group_updatedAt\\"\\n BEFORE UPDATE ON \\"group\\"\\n FOR EACH ROW\\n EXECUTE FUNCTION updated_at();"}'::jsonb);`.execute(db);
}
export async function down(db: Kysely<any>): Promise<void> {
await sql`DROP TABLE "group_audit";`.execute(db);
await sql`DROP TABLE "group_user_audit";`.execute(db);
await sql`DROP TABLE "group_user";`.execute(db);
await sql`DROP TABLE "group";`.execute(db);
await sql`DROP FUNCTION group_delete_audit;`.execute(db);
await sql`DROP FUNCTION group_user_delete_audit;`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'function_group_delete_audit';`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'function_group_user_delete_audit';`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'trigger_group_user_delete_audit';`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'trigger_group_user_updatedAt';`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'trigger_group_delete_audit';`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'trigger_group_updatedAt';`.execute(db);
}
@@ -0,0 +1,11 @@
import { Kysely, sql } from 'kysely';
export async function up(db: Kysely<any>): Promise<void> {
await sql`ALTER TABLE "group_user" DROP CONSTRAINT "group_user_groupId_fkey";`.execute(db);
await sql`ALTER TABLE "group_user" ADD CONSTRAINT "group_user_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "group" ("id") ON UPDATE CASCADE ON DELETE CASCADE;`.execute(db);
}
export async function down(db: Kysely<any>): Promise<void> {
await sql`ALTER TABLE "group_user" DROP CONSTRAINT "group_user_groupId_fkey";`.execute(db);
await sql`ALTER TABLE "group_user" ADD CONSTRAINT "group_user_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "album" ("id") ON UPDATE CASCADE ON DELETE CASCADE;`.execute(db);
}
@@ -0,0 +1,33 @@
import { Kysely, sql } from 'kysely';
export async function up(db: Kysely<any>): Promise<void> {
await sql`DROP TRIGGER "group_delete_audit" ON "group";`.execute(db);
await sql`ALTER TABLE "group_audit" ADD "userId" uuid NOT NULL;`.execute(db);
await sql`DROP FUNCTION group_delete_audit;`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'function_group_delete_audit';`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'trigger_group_delete_audit';`.execute(db);
}
export async function down(db: Kysely<any>): Promise<void> {
await sql`CREATE OR REPLACE FUNCTION public.group_delete_audit()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO group_audit ("groupId")
SELECT "id"
FROM OLD;
RETURN NULL;
END
$function$
`.execute(db);
await sql`CREATE OR REPLACE TRIGGER "group_delete_audit"
AFTER DELETE ON "group"
REFERENCING OLD TABLE AS "old"
FOR EACH STATEMENT
WHEN ((pg_trigger_depth() = 0))
EXECUTE FUNCTION group_delete_audit();`.execute(db);
await sql`ALTER TABLE "group_audit" DROP COLUMN "userId";`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('function_group_delete_audit', '{"sql":"CREATE OR REPLACE FUNCTION group_delete_audit()\\n RETURNS TRIGGER\\n LANGUAGE PLPGSQL\\n AS $$\\n BEGIN\\n INSERT INTO group_audit (\\"groupId\\")\\n SELECT \\"id\\"\\n FROM OLD;\\n RETURN NULL;\\n END\\n $$;","name":"group_delete_audit","type":"function"}'::jsonb);`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('trigger_group_delete_audit', '{"sql":"CREATE OR REPLACE TRIGGER \\"group_delete_audit\\"\\n AFTER DELETE ON \\"group\\"\\n REFERENCING OLD TABLE AS \\"old\\"\\n FOR EACH STATEMENT\\n WHEN (pg_trigger_depth() = 0)\\n EXECUTE FUNCTION group_delete_audit();","name":"group_delete_audit","type":"trigger"}'::jsonb);`.execute(db);
}
@@ -0,0 +1,70 @@
import { Kysely, sql } from 'kysely';
export async function up(db: Kysely<any>): Promise<void> {
await sql`CREATE OR REPLACE FUNCTION album_group_delete_audit()
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS $$
BEGIN
INSERT INTO "album_audit" ("albumId", "userId")
SELECT OLD."albumId", "group_user"."userId"
FROM OLD INNER JOIN "group_user" ON "group_user"."groupId" = OLD."groupId";
IF pg_trigger_depth() = 1 THEN
INSERT INTO album_group_audit ("albumId", "groupId")
SELECT "albumId", "groupId"
FROM OLD;
END IF;
RETURN NULL;
END
$$;`.execute(db);
await sql`CREATE TABLE "album_group_audit" (
"id" uuid NOT NULL DEFAULT immich_uuid_v7(),
"albumId" uuid NOT NULL,
"groupId" uuid NOT NULL,
"deletedAt" timestamp with time zone NOT NULL DEFAULT clock_timestamp(),
CONSTRAINT "album_group_audit_pkey" PRIMARY KEY ("id")
);`.execute(db);
await sql`CREATE INDEX "album_group_audit_albumId_idx" ON "album_group_audit" ("albumId");`.execute(db);
await sql`CREATE INDEX "album_group_audit_groupId_idx" ON "album_group_audit" ("groupId");`.execute(db);
await sql`CREATE INDEX "album_group_audit_deletedAt_idx" ON "album_group_audit" ("deletedAt");`.execute(db);
await sql`CREATE TABLE "album_group" (
"albumId" uuid NOT NULL,
"groupId" uuid NOT NULL,
"role" character varying NOT NULL DEFAULT 'editor',
"createId" uuid NOT NULL DEFAULT immich_uuid_v7(),
"createdAt" timestamp with time zone NOT NULL DEFAULT now(),
"updateId" uuid NOT NULL DEFAULT immich_uuid_v7(),
"updatedAt" timestamp with time zone NOT NULL DEFAULT now(),
CONSTRAINT "album_group_albumId_fkey" FOREIGN KEY ("albumId") REFERENCES "album" ("id") ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT "album_group_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "group" ("id") ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT "album_group_pkey" PRIMARY KEY ("albumId", "groupId")
);`.execute(db);
await sql`CREATE INDEX "album_group_albumId_idx" ON "album_group" ("albumId");`.execute(db);
await sql`CREATE INDEX "album_group_groupId_idx" ON "album_group" ("groupId");`.execute(db);
await sql`CREATE INDEX "album_group_createId_idx" ON "album_group" ("createId");`.execute(db);
await sql`CREATE INDEX "album_group_updateId_idx" ON "album_group" ("updateId");`.execute(db);
await sql`CREATE OR REPLACE TRIGGER "album_group_delete_audit"
AFTER DELETE ON "album_group"
REFERENCING OLD TABLE AS "old"
FOR EACH STATEMENT
WHEN (pg_trigger_depth() <= 1)
EXECUTE FUNCTION album_group_delete_audit();`.execute(db);
await sql`CREATE OR REPLACE TRIGGER "album_group_updatedAt"
BEFORE UPDATE ON "album_group"
FOR EACH ROW
EXECUTE FUNCTION updated_at();`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('function_album_group_delete_audit', '{"type":"function","name":"album_group_delete_audit","sql":"CREATE OR REPLACE FUNCTION album_group_delete_audit()\\n RETURNS TRIGGER\\n LANGUAGE PLPGSQL\\n AS $$\\n BEGIN\\n INSERT INTO \\"album_audit\\" (\\"albumId\\", \\"userId\\")\\n SELECT OLD.\\"albumId\\", \\"group_user\\".\\"userId\\"\\n FROM OLD INNER JOIN \\"group_user\\" ON \\"group_user\\".\\"groupId\\" = OLD.\\"groupId\\";\\n\\n IF pg_trigger_depth() = 1 THEN\\n INSERT INTO album_group_audit (\\"albumId\\", \\"groupId\\")\\n SELECT \\"albumId\\", \\"groupId\\"\\n FROM OLD;\\n END IF;\\n\\n RETURN NULL;\\n END\\n $$;"}'::jsonb);`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('trigger_album_group_delete_audit', '{"type":"trigger","name":"album_group_delete_audit","sql":"CREATE OR REPLACE TRIGGER \\"album_group_delete_audit\\"\\n AFTER DELETE ON \\"album_group\\"\\n REFERENCING OLD TABLE AS \\"old\\"\\n FOR EACH STATEMENT\\n WHEN (pg_trigger_depth() <= 1)\\n EXECUTE FUNCTION album_group_delete_audit();"}'::jsonb);`.execute(db);
await sql`INSERT INTO "migration_overrides" ("name", "value") VALUES ('trigger_album_group_updatedAt', '{"type":"trigger","name":"album_group_updatedAt","sql":"CREATE OR REPLACE TRIGGER \\"album_group_updatedAt\\"\\n BEFORE UPDATE ON \\"album_group\\"\\n FOR EACH ROW\\n EXECUTE FUNCTION updated_at();"}'::jsonb);`.execute(db);
}
export async function down(db: Kysely<any>): Promise<void> {
await sql`DROP TABLE "album_group_audit";`.execute(db);
await sql`DROP TABLE "album_group";`.execute(db);
await sql`DROP FUNCTION album_group_delete_audit;`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'function_album_group_delete_audit';`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'trigger_album_group_delete_audit';`.execute(db);
await sql`DELETE FROM "migration_overrides" WHERE "name" = 'trigger_album_group_updatedAt';`.execute(db);
}
@@ -0,0 +1,17 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('album_group_audit')
export class AlbumGroupAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid', index: true })
albumId!: string;
@Column({ type: 'uuid', index: true })
groupId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}
@@ -0,0 +1,56 @@
import { CreateIdColumn, UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { AlbumUserRole } from 'src/enum';
import { album_group_delete_audit } from 'src/schema/functions';
import { AlbumTable } from 'src/schema/tables/album.table';
import { GroupTable } from 'src/schema/tables/group.table';
import {
AfterDeleteTrigger,
Column,
CreateDateColumn,
ForeignKeyColumn,
Generated,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@Table({ name: 'album_group' })
@UpdatedAtTrigger('album_group_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: album_group_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() <= 1',
})
export class AlbumGroupTable {
@ForeignKeyColumn(() => AlbumTable, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
nullable: false,
primary: true,
})
albumId!: string;
@ForeignKeyColumn(() => GroupTable, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
nullable: false,
primary: true,
})
groupId!: string;
@Column({ type: 'character varying', default: AlbumUserRole.Editor })
role!: Generated<AlbumUserRole>;
@CreateIdColumn({ index: true })
createId!: Generated<string>;
@CreateDateColumn()
createdAt!: Generated<Timestamp>;
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
@UpdateDateColumn()
updatedAt!: Generated<Timestamp>;
}
@@ -0,0 +1,17 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('group_audit')
export class GroupAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid' })
groupId!: string;
@Column({ type: 'uuid' })
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}
@@ -0,0 +1,17 @@
import { PrimaryGeneratedUuidV7Column } from 'src/decorators';
import { Column, CreateDateColumn, Generated, Table, Timestamp } from 'src/sql-tools';
@Table('group_user_audit')
export class GroupUserAuditTable {
@PrimaryGeneratedUuidV7Column()
id!: Generated<string>;
@Column({ type: 'uuid', index: true })
groupId!: string;
@Column({ type: 'uuid', index: true })
userId!: string;
@CreateDateColumn({ default: () => 'clock_timestamp()', index: true })
deletedAt!: Generated<Timestamp>;
}
@@ -0,0 +1,51 @@
import { CreateIdColumn, UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { group_user_delete_audit } from 'src/schema/functions';
import { GroupTable } from 'src/schema/tables/group.table';
import { UserTable } from 'src/schema/tables/user.table';
import {
AfterDeleteTrigger,
CreateDateColumn,
ForeignKeyColumn,
Generated,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@Table({ name: 'group_user' })
@UpdatedAtTrigger('group_user_updatedAt')
@AfterDeleteTrigger({
scope: 'statement',
function: group_user_delete_audit,
referencingOldTableAs: 'old',
when: 'pg_trigger_depth() <= 1',
})
export class GroupUserTable {
@ForeignKeyColumn(() => GroupTable, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
nullable: false,
primary: true,
})
groupId!: string;
@ForeignKeyColumn(() => UserTable, {
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
nullable: false,
primary: true,
})
userId!: string;
@CreateIdColumn({ index: true })
createId!: Generated<string>;
@CreateDateColumn()
createdAt!: Generated<Timestamp>;
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
@UpdateDateColumn()
updatedAt!: Generated<Timestamp>;
}
+34
View File
@@ -0,0 +1,34 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import {
Column,
CreateDateColumn,
Generated,
Index,
PrimaryGeneratedColumn,
Table,
Timestamp,
UpdateDateColumn,
} from 'src/sql-tools';
@Table('group')
@UpdatedAtTrigger('group_updatedAt')
@Index({ columns: ['updatedAt', 'id'] })
export class GroupTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;
@Column({ unique: true })
name!: string;
@Column({ nullable: true })
description!: string | null;
@CreateDateColumn()
createdAt!: Generated<Timestamp>;
@UpdateDateColumn()
updatedAt!: Generated<Timestamp>;
@UpdateIdColumn({ index: true })
updateId!: Generated<string>;
}