dorfteich/apps/api/prisma/migrations/20260708082627_attachments/migration.sql
Claude Sonnet 5 0fae699018
All checks were successful
CD / Build and push images (push) Successful in 2m2s
CI / Lint, typecheck, test (push) Successful in 1m43s
CI / Auth e2e pack (push) Successful in 1m48s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 8s
CD / Smoke tests against Test (push) Successful in 1m10s
CD / Promote to Int (push) Successful in 10s
Add file storage service and image upload API (#27)
Implements the FileStorage abstraction (uploads/<pondId>/<fileId> on the
mounted volume), the attachments model, and POST /ponds/:id/files, GET
/media/:fileId, DELETE /files/:id. Uploads are validated by sniffing
magic bytes rather than trusting the client's Content-Type/filename
(catches a renamed .html-as-.png), checked against the max_file_bytes
and storage_bytes quotas, and served with nosniff + immutable caching.

Closes #27
2026-07-08 10:35:03 +02:00

31 lines
1.1 KiB
SQL

-- CreateTable
CREATE TABLE "attachments" (
"id" TEXT NOT NULL,
"pond_id" TEXT NOT NULL,
"page_id" TEXT,
"file_name" TEXT NOT NULL,
"mime_type" TEXT NOT NULL,
"size_bytes" INTEGER NOT NULL,
"storage_path" TEXT NOT NULL,
"uploaded_by" TEXT NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" TIMESTAMP(3),
CONSTRAINT "attachments_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "attachments_pond_id_idx" ON "attachments"("pond_id");
-- CreateIndex
CREATE INDEX "attachments_page_id_idx" ON "attachments"("page_id");
-- AddForeignKey
ALTER TABLE "attachments" ADD CONSTRAINT "attachments_pond_id_fkey" FOREIGN KEY ("pond_id") REFERENCES "ponds"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "attachments" ADD CONSTRAINT "attachments_page_id_fkey" FOREIGN KEY ("page_id") REFERENCES "pages"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "attachments" ADD CONSTRAINT "attachments_uploaded_by_fkey" FOREIGN KEY ("uploaded_by") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;