Files
kita-planer/prisma/migrations/20261009010000_security_hardening/migration.sql
T

103 lines
8.3 KiB
PL/PgSQL

BEGIN;
-- AlterTable
ALTER TABLE "users" ADD COLUMN "disabledAt" TIMESTAMP(3),
ADD COLUMN "sessionVersion" INTEGER NOT NULL DEFAULT 0;
-- CreateTable
CREATE TABLE "rate_limit_buckets" (
"key" TEXT NOT NULL,
"count" INTEGER NOT NULL,
"resetAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "rate_limit_buckets_pkey" PRIMARY KEY ("key")
);
-- CreateTable
CREATE TABLE "pending_registrations" (
"email" TEXT NOT NULL,
"firstName" TEXT NOT NULL,
"lastName" TEXT NOT NULL,
"tokenHash" TEXT NOT NULL,
"expiresAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "pending_registrations_pkey" PRIMARY KEY ("email")
);
-- CreateIndex
CREATE INDEX "rate_limit_buckets_resetAt_idx" ON "rate_limit_buckets"("resetAt");
-- CreateIndex
CREATE UNIQUE INDEX "pending_registrations_tokenHash_key" ON "pending_registrations"("tokenHash");
-- CreateIndex
CREATE INDEX "pending_registrations_expiresAt_idx" ON "pending_registrations"("expiresAt");
-- CreateIndex
CREATE UNIQUE INDEX "families_id_kitaId_key" ON "families"("id", "kitaId");
-- CreateIndex
CREATE UNIQUE INDEX "users_id_kitaId_key" ON "users"("id", "kitaId");
-- CreateIndex
CREATE UNIQUE INDEX "children_id_kitaId_key" ON "children"("id", "kitaId");
-- CreateIndex
CREATE UNIQUE INDEX "educators_id_kitaId_key" ON "educators"("id", "kitaId");
-- CreateIndex
CREATE UNIQUE INDEX "parent_duties_id_kitaId_key" ON "parent_duties"("id", "kitaId");
-- CreateIndex
CREATE UNIQUE INDEX "duty_types_id_kitaId_key" ON "duty_types"("id", "kitaId");
-- CreateIndex
CREATE UNIQUE INDEX "termine_id_kitaId_key" ON "termine"("id", "kitaId");
-- CreateIndex
CREATE UNIQUE INDEX "notdienst_plans_id_kitaId_key" ON "notdienst_plans"("id", "kitaId");
-- CreateIndex
CREATE UNIQUE INDEX "notdienst_assignments_id_kitaId_key" ON "notdienst_assignments"("id", "kitaId");
-- Additional composite tenant foreign keys deliberately supplement the Prisma single-ID relations.
-- NO ACTION preserves their existing Cascade/SetNull behavior; validation rejects inconsistent legacy rows.
ALTER TABLE "users" ADD CONSTRAINT "users_familyId_tenant_fkey" FOREIGN KEY ("familyId", "kitaId") REFERENCES "families"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "children" ADD CONSTRAINT "children_familyId_tenant_fkey" FOREIGN KEY ("familyId", "kitaId") REFERENCES "families"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "parent_duty_assignments" ADD CONSTRAINT "parent_duty_assignments_dutyId_tenant_fkey" FOREIGN KEY ("dutyId", "kitaId") REFERENCES "parent_duties"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "parent_duty_assignments" ADD CONSTRAINT "parent_duty_assignments_userId_tenant_fkey" FOREIGN KEY ("userId", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "duty_assignments" ADD CONSTRAINT "duty_assignments_familyId_tenant_fkey" FOREIGN KEY ("familyId", "kitaId") REFERENCES "families"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "duty_assignments" ADD CONSTRAINT "duty_assignments_dutyTypeId_tenant_fkey" FOREIGN KEY ("dutyTypeId", "kitaId") REFERENCES "duty_types"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "absences" ADD CONSTRAINT "absences_childId_tenant_fkey" FOREIGN KEY ("childId", "kitaId") REFERENCES "children"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "announcements" ADD CONSTRAINT "announcements_authorId_tenant_fkey" FOREIGN KEY ("authorId", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "invitations" ADD CONSTRAINT "invitations_invitedById_tenant_fkey" FOREIGN KEY ("invitedById", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "termine" ADD CONSTRAINT "termine_createdById_tenant_fkey" FOREIGN KEY ("createdById", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "termine" ADD CONSTRAINT "termine_approvedById_tenant_fkey" FOREIGN KEY ("approvedById", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "event_participations" ADD CONSTRAINT "event_participations_eventId_tenant_fkey" FOREIGN KEY ("eventId", "kitaId") REFERENCES "termine"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "event_participations" ADD CONSTRAINT "event_participations_childId_tenant_fkey" FOREIGN KEY ("childId", "kitaId") REFERENCES "children"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "mitbringsel_items" ADD CONSTRAINT "mitbringsel_items_terminId_tenant_fkey" FOREIGN KEY ("terminId", "kitaId") REFERENCES "termine"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "mitbringsel_items" ADD CONSTRAINT "mitbringsel_items_userId_tenant_fkey" FOREIGN KEY ("userId", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_plans" ADD CONSTRAINT "notdienst_plans_createdById_tenant_fkey" FOREIGN KEY ("createdById", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_availabilities" ADD CONSTRAINT "notdienst_availabilities_childId_tenant_fkey" FOREIGN KEY ("childId", "kitaId") REFERENCES "children"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_availabilities" ADD CONSTRAINT "notdienst_availabilities_userId_tenant_fkey" FOREIGN KEY ("userId", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_assignments" ADD CONSTRAINT "notdienst_assignments_planId_tenant_fkey" FOREIGN KEY ("planId", "kitaId") REFERENCES "notdienst_plans"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_assignments" ADD CONSTRAINT "notdienst_assignments_childId_tenant_fkey" FOREIGN KEY ("childId", "kitaId") REFERENCES "children"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_swap_requests" ADD CONSTRAINT "notdienst_swap_requests_requesterUserId_tenant_fkey" FOREIGN KEY ("requesterUserId", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_swap_requests" ADD CONSTRAINT "notdienst_swap_requests_requesterFamilyId_tenant_fkey" FOREIGN KEY ("requesterFamilyId", "kitaId") REFERENCES "families"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_swap_requests" ADD CONSTRAINT "notdienst_swap_requests_targetAssignmentId_tenant_fkey" FOREIGN KEY ("targetAssignmentId", "kitaId") REFERENCES "notdienst_assignments"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_swap_requests" ADD CONSTRAINT "notdienst_swap_requests_offeredAssignmentId_tenant_fkey" FOREIGN KEY ("offeredAssignmentId", "kitaId") REFERENCES "notdienst_assignments"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_swap_requests" ADD CONSTRAINT "notdienst_swap_requests_respondedById_tenant_fkey" FOREIGN KEY ("respondedById", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_alerts" ADD CONSTRAINT "notdienst_alerts_assignmentId_tenant_fkey" FOREIGN KEY ("assignmentId", "kitaId") REFERENCES "notdienst_assignments"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_alerts" ADD CONSTRAINT "notdienst_alerts_parentUserId_tenant_fkey" FOREIGN KEY ("parentUserId", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_alerts" ADD CONSTRAINT "notdienst_alerts_triggeredById_tenant_fkey" FOREIGN KEY ("triggeredById", "kitaId") REFERENCES "users"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_alerts" ADD CONSTRAINT "notdienst_alerts_educatorId_tenant_fkey" FOREIGN KEY ("educatorId", "kitaId") REFERENCES "educators"("id", "kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
-- Existing founder registrations previously set this timestamp without verification.
UPDATE users SET "emailVerifiedAt" = NULL, "sessionVersion" = "sessionVersion" + 1
WHERE role = 'ADMIN' AND "kitaId" IS NULL;
-- Preserve existing administrative account locks separately from temporary brute-force lockouts.
UPDATE users SET "disabledAt" = NOW(), "sessionVersion" = "sessionVersion" + 1
WHERE "lockedUntil" >= TIMESTAMP '2099-01-01';
COMMIT;