diff --git a/libs/supabase/package-lock.json b/libs/supabase/package-lock.json new file mode 100644 index 0000000..f498fb1 --- /dev/null +++ b/libs/supabase/package-lock.json @@ -0,0 +1,20 @@ +{ + "name": "@learning-app/supabase", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@learning-app/supabase", + "version": "0.0.1", + "dependencies": { + "tslib": "^2.3.0" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + } + } +} diff --git a/libs/supabase/prisma/migrations/20240327063011_createdby_updatedby_in_mcq_question/migration.sql b/libs/supabase/prisma/migrations/20240327063011_createdby_updatedby_in_mcq_question/migration.sql new file mode 100644 index 0000000..3192924 --- /dev/null +++ b/libs/supabase/prisma/migrations/20240327063011_createdby_updatedby_in_mcq_question/migration.sql @@ -0,0 +1,9 @@ +-- AlterTable +ALTER TABLE "McqQuestion" ADD COLUMN "createdById" UUID, +ADD COLUMN "updatedById" UUID; + +-- AddForeignKey +ALTER TABLE "McqQuestion" ADD CONSTRAINT "McqQuestion_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "Profile"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "McqQuestion" ADD CONSTRAINT "McqQuestion_updatedById_fkey" FOREIGN KEY ("updatedById") REFERENCES "Profile"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/libs/supabase/prisma/models.ts b/libs/supabase/prisma/models.ts new file mode 100644 index 0000000..892e0f3 --- /dev/null +++ b/libs/supabase/prisma/models.ts @@ -0,0 +1 @@ +export const allModels = ['Subject', 'Topic', 'McqQuestion'] \ No newline at end of file diff --git a/libs/supabase/prisma/schema.prisma b/libs/supabase/prisma/schema.prisma index 5a2ded0..7213f56 100644 --- a/libs/supabase/prisma/schema.prisma +++ b/libs/supabase/prisma/schema.prisma @@ -41,6 +41,9 @@ model Profile { createdTopics Topic[] @relation("TopicCreatedBy") updatedTopics Topic[] @relation("TopicUpdatedBy") + + createdMcqs McqQuestion[] @relation("McqCreatedBy") + updatedMcqs McqQuestion[] @relation("McqUpdatedBy") } model Course { @@ -115,13 +118,17 @@ model McqQuestion { explanation String topic Topic @relation(fields: [topicId], references: [id]) topicId String @db.Uuid + createdBy Profile? @relation("McqCreatedBy", fields: [createdById], references: [id], onDelete: Restrict) + createdById String? @db.Uuid + updatedBy Profile? @relation("McqUpdatedBy", fields: [updatedById], references: [id], onDelete: Restrict) + updatedById String? @db.Uuid } model ContactUs { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - type String? - name String? - email String? - mobile String? - message String? + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + type String? + name String? + email String? + mobile String? + message String? } diff --git a/libs/supabase/prisma/seed.ts b/libs/supabase/prisma/seed.ts index 16b1248..179aae2 100644 --- a/libs/supabase/prisma/seed.ts +++ b/libs/supabase/prisma/seed.ts @@ -2,12 +2,18 @@ import { PrismaClient } from '@prisma/client'; import { create_profile_on_signup } from './seeds/create_profile_on_signup'; import { create_check_mobile_exists } from './seeds/check_mobile_exists'; import { seedRLSPolicies } from './seeds/rls_policies'; +import { create_createdBy } from './seeds/create_createdBy_trigger'; +import { create_updatedBy } from './seeds/create_updatedBy_trigger'; +import { create_updatedAt } from './seeds/create_updatedAt_trigger'; const prisma = new PrismaClient(); async function main() { await create_profile_on_signup(prisma); await create_check_mobile_exists(prisma); + await create_createdBy(prisma); + await create_updatedAt(prisma); + await create_updatedBy(prisma); await seedRLSPolicies(prisma); } diff --git a/libs/supabase/prisma/seeds/create_createdBy_trigger.ts b/libs/supabase/prisma/seeds/create_createdBy_trigger.ts new file mode 100644 index 0000000..f494aae --- /dev/null +++ b/libs/supabase/prisma/seeds/create_createdBy_trigger.ts @@ -0,0 +1,37 @@ +import { PrismaClient } from '@prisma/client'; +import { allModels } from '../models'; + +async function makeFunction(prisma) { + await prisma.$executeRaw` + CREATE OR REPLACE FUNCTION public.update_createdBy() + RETURNS trigger AS $$ + BEGIN + NEW."createdById" := auth.uid(); + RETURN NEW; + END; + $$ + LANGUAGE plpgsql + SECURITY definer SET search_path = public; + `; +} + +async function makeTrigger(prisma: PrismaClient, tableName: string) { + await prisma.$executeRawUnsafe(` + CREATE OR REPLACE TRIGGER update_createdBy_trigger + BEFORE INSERT ON public."${tableName}" + FOR EACH ROW + EXECUTE PROCEDURE public.update_createdBy(); + `); +} + +export async function create_createdBy(prisma: PrismaClient) { + await makeFunction(prisma); + await makeCreatedByTriggers(prisma) +} + + +async function makeCreatedByTriggers(prisma: PrismaClient) { + for (const entity of allModels) { + await makeTrigger(prisma, entity); + } +} \ No newline at end of file diff --git a/libs/supabase/prisma/seeds/create_updatedAt_trigger.ts b/libs/supabase/prisma/seeds/create_updatedAt_trigger.ts new file mode 100644 index 0000000..d923484 --- /dev/null +++ b/libs/supabase/prisma/seeds/create_updatedAt_trigger.ts @@ -0,0 +1,29 @@ +import { PrismaClient } from '@prisma/client'; +import { allModels } from '../models'; + +async function makeFunction(prisma) { + await prisma.$executeRaw` + CREATE EXTENSION IF NOT EXISTS moddatetime SCHEMA public; + `; +} + +async function makeTrigger(prisma: PrismaClient, tableName: string) { + await prisma.$executeRawUnsafe(` + CREATE OR REPLACE TRIGGER update_updatedAt_trigger + BEFORE UPDATE ON public."${tableName}" + FOR EACH ROW + EXECUTE PROCEDURE moddatetime("updatedAt"); + `); +} + +export async function create_updatedAt(prisma: PrismaClient) { + await makeFunction(prisma); + await makeUpdatedAtTriggers(prisma) +} + + +async function makeUpdatedAtTriggers(prisma: PrismaClient) { + for (const entity of allModels) { + await makeTrigger(prisma, entity); + } +} \ No newline at end of file diff --git a/libs/supabase/prisma/seeds/create_updatedBy_trigger.ts b/libs/supabase/prisma/seeds/create_updatedBy_trigger.ts new file mode 100644 index 0000000..169c8c7 --- /dev/null +++ b/libs/supabase/prisma/seeds/create_updatedBy_trigger.ts @@ -0,0 +1,37 @@ +import { PrismaClient } from '@prisma/client'; +import { allModels } from '../models'; + +async function makeFunction(prisma) { + await prisma.$executeRaw` + CREATE OR REPLACE FUNCTION public.update_updated_by() + RETURNS trigger AS $$ + BEGIN + NEW."updatedById" := auth.uid(); + RETURN NEW; + END; + $$ + LANGUAGE plpgsql + SECURITY definer SET search_path = public; + `; +} + +async function makeTrigger(prisma: PrismaClient, tableName: string) { + await prisma.$executeRawUnsafe(` + CREATE OR REPLACE TRIGGER update_updatedBy_trigger + BEFORE UPDATE OR INSERT ON public."${tableName}" + FOR EACH ROW + EXECUTE PROCEDURE public.update_updated_by(); + `); +} + +export async function create_updatedBy(prisma: PrismaClient) { + await makeFunction(prisma); + await makeUpdatedByTriggers(prisma) +} + + +async function makeUpdatedByTriggers(prisma: PrismaClient) { + for (const entity of allModels) { + await makeTrigger(prisma, entity); + } +} \ No newline at end of file