feat: 完成举报拉黑和审核处置闭环
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
CREATE TYPE "AccountRole" AS ENUM ('USER', 'ADMIN');
|
||||
ALTER TABLE "accounts" ADD COLUMN "role" "AccountRole" NOT NULL DEFAULT 'USER';
|
||||
ALTER TABLE "reports" ADD COLUMN "idempotency_key" VARCHAR(128) DEFAULT gen_random_uuid()::text;
|
||||
UPDATE "reports" SET "idempotency_key" = "id"::text WHERE "idempotency_key" IS NULL;
|
||||
ALTER TABLE "reports" ALTER COLUMN "idempotency_key" SET NOT NULL;
|
||||
CREATE UNIQUE INDEX "reports_reporter_id_idempotency_key_key" ON "reports"("reporter_id", "idempotency_key");
|
||||
ALTER TABLE "notifications" ADD COLUMN "dedupe_key" VARCHAR(255);
|
||||
UPDATE "notifications" SET "dedupe_key" = "id"::text WHERE "dedupe_key" IS NULL;
|
||||
ALTER TABLE "notifications" ALTER COLUMN "dedupe_key" SET NOT NULL;
|
||||
CREATE UNIQUE INDEX "notifications_account_id_dedupe_key_key" ON "notifications"("account_id", "dedupe_key");
|
||||
CREATE TABLE "push_preferences" (
|
||||
"account_id" UUID NOT NULL,
|
||||
"in_app_enabled" BOOLEAN NOT NULL DEFAULT true,
|
||||
"updated_at" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "push_preferences_pkey" PRIMARY KEY ("account_id"),
|
||||
CONSTRAINT "push_preferences_account_id_fkey" FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
@@ -13,6 +13,11 @@ enum AccountStatus {
|
||||
DELETED
|
||||
}
|
||||
|
||||
enum AccountRole {
|
||||
USER
|
||||
ADMIN
|
||||
}
|
||||
|
||||
enum AuthProvider {
|
||||
PHONE
|
||||
APPLE
|
||||
@@ -97,6 +102,7 @@ model Account {
|
||||
phoneCiphertext Bytes @map("phone_ciphertext")
|
||||
phoneHmac String @unique @map("phone_hmac") @db.VarChar(128)
|
||||
status AccountStatus @default(ACTIVE)
|
||||
role AccountRole @default(USER)
|
||||
tokenVersion Int @default(0) @map("token_version")
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
|
||||
@@ -119,6 +125,7 @@ model Account {
|
||||
auditLogs AuditLog[] @relation("AuditActor")
|
||||
dailyUsage DailyUsage[]
|
||||
pickRequests BottlePickRequest[]
|
||||
pushPreference PushPreference?
|
||||
|
||||
@@map("accounts")
|
||||
}
|
||||
@@ -368,6 +375,7 @@ model Report {
|
||||
/// Exactly one nullable target foreign key must be set; enforced in 0001_init SQL.
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
reporterId String @map("reporter_id") @db.Uuid
|
||||
idempotencyKey String @default(uuid()) @map("idempotency_key") @db.VarChar(128)
|
||||
reportedAccountId String? @map("reported_account_id") @db.Uuid
|
||||
bottleId String? @map("bottle_id") @db.Uuid
|
||||
conversationId String? @map("conversation_id") @db.Uuid
|
||||
@@ -388,6 +396,7 @@ model Report {
|
||||
|
||||
@@index([status, createdAt])
|
||||
@@index([reportedAccountId, createdAt])
|
||||
@@unique([reporterId, idempotencyKey])
|
||||
@@map("reports")
|
||||
}
|
||||
|
||||
@@ -439,6 +448,7 @@ model Sanction {
|
||||
model Notification {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
accountId String @map("account_id") @db.Uuid
|
||||
dedupeKey String @map("dedupe_key") @db.VarChar(255)
|
||||
type String @db.VarChar(100)
|
||||
payload Json
|
||||
status NotificationStatus @default(PENDING)
|
||||
@@ -449,9 +459,19 @@ model Notification {
|
||||
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([accountId, status, createdAt])
|
||||
@@unique([accountId, dedupeKey])
|
||||
@@map("notifications")
|
||||
}
|
||||
|
||||
model PushPreference {
|
||||
accountId String @id @map("account_id") @db.Uuid
|
||||
inAppEnabled Boolean @default(true) @map("in_app_enabled")
|
||||
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz(3)
|
||||
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("push_preferences")
|
||||
}
|
||||
|
||||
model OutboxEvent {
|
||||
/// Processing lease index outbox_events_processing_lease_idx is managed in 0007 SQL.
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
|
||||
+8
-1
@@ -23,10 +23,16 @@ async function seed(): Promise<void> {
|
||||
nickname: "星河",
|
||||
publicId: "00000000-0000-4000-8000-000000000002",
|
||||
},
|
||||
{
|
||||
key: "demo-admin",
|
||||
nickname: "管理员",
|
||||
publicId: "00000000-0000-4000-8000-000000000003",
|
||||
},
|
||||
].map(({ key, nickname, publicId }) =>
|
||||
prisma.account.upsert({
|
||||
where: { phoneHmac: id(`drift-bottle:${key}:phone-hmac`) },
|
||||
update: {
|
||||
role: key === "demo-admin" ? "ADMIN" : "USER",
|
||||
anonymousProfile: {
|
||||
upsert: {
|
||||
create: {
|
||||
@@ -44,6 +50,7 @@ async function seed(): Promise<void> {
|
||||
},
|
||||
},
|
||||
create: {
|
||||
role: key === "demo-admin" ? "ADMIN" : "USER",
|
||||
phoneCiphertext: Buffer.from(
|
||||
id(`drift-bottle:${key}:ciphertext`),
|
||||
"hex",
|
||||
@@ -78,7 +85,7 @@ async function seed(): Promise<void> {
|
||||
});
|
||||
|
||||
console.info(
|
||||
"Seed complete: 2 demo accounts, 2 anonymous profiles, 1 in-pool bottle.",
|
||||
"Seed complete: 3 demo accounts (including admin), 3 anonymous profiles, 1 in-pool bottle.",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user