57 lines
2.1 KiB
Markdown
57 lines
2.1 KiB
Markdown
# Database Migration Strategy: Mandatory Organizer Ownership Invariant
|
|
|
|
This document details the database schema migration strategy for enforcing mandatory, non-null `organizerId` on the `Giveaway` table in production.
|
|
|
|
---
|
|
|
|
## 1. Context & Invariant
|
|
|
|
In Randomayzer, every giveaway is owned by an authenticated Organizer (represented by the `User` model via VK ID OAuth 2.1).
|
|
To prevent broken access control and ambiguous authorization states:
|
|
- `Giveaway.organizerId` is strictly `NOT NULL`.
|
|
- Foreign key relation is defined with `onDelete: Restrict`, strictly preventing the deletion of an organizer account while owned giveaways exist.
|
|
|
|
---
|
|
|
|
## 2. Prisma Schema Definition
|
|
|
|
```prisma
|
|
model User {
|
|
id String @id @default(cuid())
|
|
vkUserId String @unique
|
|
giveaways Giveaway[]
|
|
...
|
|
}
|
|
|
|
model Giveaway {
|
|
id String @id @default(cuid())
|
|
organizerId String
|
|
organizer User @relation(fields: [organizerId], references: [id], onDelete: Restrict)
|
|
...
|
|
@@index([organizerId])
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Migration Plan for Existing Records
|
|
|
|
### A. Development & Staging Environments
|
|
Existing anonymous test records created prior to Phase 2.2 can be purged:
|
|
```sql
|
|
DELETE FROM "ParticipantSnapshot" WHERE "giveawayId" IN (SELECT "id" FROM "Giveaway" WHERE "organizerId" IS NULL);
|
|
DELETE FROM "Participant" WHERE "giveawayId" IN (SELECT "id" FROM "Giveaway" WHERE "organizerId" IS NULL);
|
|
DELETE FROM "Giveaway" WHERE "organizerId" IS NULL;
|
|
```
|
|
|
|
### B. Production Migration Protocol
|
|
1. **Never assign legacy records to arbitrary users**: If unassigned giveaways exist in a production database, do not automatically bind them to random organizers.
|
|
2. **Quarantine or Admin Assignment**: Migrate legacy orphan giveaways to a designated system quarantine table or assign to an explicitly verified administrative organizer.
|
|
3. **Execute SQL Migration**:
|
|
```sql
|
|
-- Step 1: Verify 0 null records remain
|
|
SELECT COUNT(*) FROM "Giveaway" WHERE "organizerId" IS NULL;
|
|
|
|
-- Step 2: Enforce NOT NULL and Restrict constraint
|
|
ALTER TABLE "Giveaway" ALTER COLUMN "organizerId" SET NOT NULL;
|
|
```
|