fix architecture and write new tests
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
-- Company API keys are stored hash-only. Raw keys are shown once at creation.
|
||||
CREATE TABLE IF NOT EXISTS "company_api_keys" (
|
||||
"id" TEXT PRIMARY KEY,
|
||||
"companyId" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"prefix" TEXT NOT NULL UNIQUE,
|
||||
"keyHash" TEXT NOT NULL,
|
||||
"lastUsedAt" TIMESTAMP(3),
|
||||
"revokedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "company_api_keys_companyId_fkey"
|
||||
FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "company_api_keys_companyId_idx" ON "company_api_keys"("companyId");
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
CREATE TABLE IF NOT EXISTS "reservation_public_access" (
|
||||
"id" TEXT PRIMARY KEY,
|
||||
"reservationId" TEXT NOT NULL,
|
||||
"tokenHash" TEXT NOT NULL UNIQUE,
|
||||
"expiresAt" TIMESTAMP(3) NOT NULL,
|
||||
"usedAt" TIMESTAMP(3),
|
||||
"revokedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT "reservation_public_access_reservationId_fkey"
|
||||
FOREIGN KEY ("reservationId") REFERENCES "reservations"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "reservation_public_access_reservationId_idx" ON "reservation_public_access"("reservationId");
|
||||
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE IF NOT EXISTS "webhook_events" (
|
||||
"id" TEXT NOT NULL,
|
||||
"provider" TEXT NOT NULL,
|
||||
"providerEventId" TEXT NOT NULL,
|
||||
"eventType" TEXT NOT NULL,
|
||||
"status" TEXT NOT NULL,
|
||||
"payloadHash" TEXT NOT NULL,
|
||||
"errorMessage" TEXT,
|
||||
"receivedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"processedAt" TIMESTAMP(3),
|
||||
CONSTRAINT "webhook_events_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "webhook_events_provider_providerEventId_key"
|
||||
ON "webhook_events"("provider", "providerEventId");
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "webhook_events_provider_status_idx"
|
||||
ON "webhook_events"("provider", "status");
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
-- Remove legacy plaintext company API key storage.
|
||||
-- Company integrations must use company_api_keys, which stores only key hashes and prefixes.
|
||||
DROP INDEX IF EXISTS "companies_apiKey_key";
|
||||
ALTER TABLE "companies" DROP COLUMN IF EXISTS "apiKey";
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "admin_recovery_codes" (
|
||||
"id" TEXT NOT NULL,
|
||||
"adminUserId" TEXT NOT NULL,
|
||||
"codeHash" TEXT NOT NULL,
|
||||
"usedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "admin_recovery_codes_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "admin_recovery_codes_adminUserId_usedAt_idx" ON "admin_recovery_codes"("adminUserId", "usedAt");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "admin_recovery_codes" ADD CONSTRAINT "admin_recovery_codes_adminUserId_fkey" FOREIGN KEY ("adminUserId") REFERENCES "admin_users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -502,7 +502,6 @@ model Company {
|
||||
address Json?
|
||||
status CompanyStatus @default(PENDING)
|
||||
subscriptionPaymentRef String?
|
||||
apiKey String @unique @default(cuid())
|
||||
|
||||
subscription Subscription?
|
||||
billingAccounts BillingAccount[]
|
||||
@@ -522,6 +521,7 @@ model Company {
|
||||
notifications Notification[] @relation("CompanyNotifications")
|
||||
complaints Complaint[]
|
||||
companyMenuItems CompanyMenuItem[]
|
||||
apiKeys CompanyApiKey[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -530,6 +530,21 @@ model Company {
|
||||
@@map("companies")
|
||||
}
|
||||
|
||||
model CompanyApiKey {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
prefix String @unique
|
||||
keyHash String
|
||||
lastUsedAt DateTime?
|
||||
revokedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([companyId])
|
||||
@@map("company_api_keys")
|
||||
}
|
||||
|
||||
model Subscription {
|
||||
id String @id @default(cuid())
|
||||
companyId String @unique
|
||||
@@ -1301,6 +1316,7 @@ model Reservation {
|
||||
photos ReservationPhoto[]
|
||||
review Review?
|
||||
complaints Complaint[]
|
||||
publicAccess ReservationPublicAccess[]
|
||||
damageChargeAmount Int?
|
||||
damageChargeNote String?
|
||||
extras Json?
|
||||
@@ -1315,6 +1331,37 @@ model Reservation {
|
||||
@@map("reservations")
|
||||
}
|
||||
|
||||
model ReservationPublicAccess {
|
||||
id String @id @default(cuid())
|
||||
reservationId String
|
||||
reservation Reservation @relation(fields: [reservationId], references: [id], onDelete: Cascade)
|
||||
tokenHash String @unique
|
||||
expiresAt DateTime
|
||||
usedAt DateTime?
|
||||
revokedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([reservationId])
|
||||
@@map("reservation_public_access")
|
||||
}
|
||||
|
||||
|
||||
model WebhookEvent {
|
||||
id String @id @default(cuid())
|
||||
provider String
|
||||
providerEventId String
|
||||
eventType String
|
||||
status String
|
||||
payloadHash String
|
||||
errorMessage String?
|
||||
receivedAt DateTime @default(now())
|
||||
processedAt DateTime?
|
||||
|
||||
@@unique([provider, providerEventId])
|
||||
@@index([provider, status])
|
||||
@@map("webhook_events")
|
||||
}
|
||||
|
||||
model RentalPayment {
|
||||
id String @id @default(cuid())
|
||||
companyId String
|
||||
@@ -1746,8 +1793,9 @@ model AdminUser {
|
||||
passwordResetToken String? @unique
|
||||
passwordResetExpiresAt DateTime?
|
||||
|
||||
auditLogs AuditLog[]
|
||||
permissions AdminPermission[]
|
||||
auditLogs AuditLog[]
|
||||
permissions AdminPermission[]
|
||||
recoveryCodes AdminRecoveryCode[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -1766,6 +1814,19 @@ model AdminPermission {
|
||||
@@map("admin_permissions")
|
||||
}
|
||||
|
||||
|
||||
model AdminRecoveryCode {
|
||||
id String @id @default(cuid())
|
||||
adminUserId String
|
||||
adminUser AdminUser @relation(fields: [adminUserId], references: [id], onDelete: Cascade)
|
||||
codeHash String
|
||||
usedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([adminUserId, usedAt])
|
||||
@@map("admin_recovery_codes")
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id String @id @default(cuid())
|
||||
adminUserId String
|
||||
|
||||
Reference in New Issue
Block a user