Files
sp/apps/web/prisma/sase/schema.prisma
Semih eee3675589 feat(sase): Public API anahtar yönetimi — /projects/sase/api-keys
Sase.tr'nin yeni Public API'sinin (Faz 1+2) anahtar yaşam döngüsü artık
panelden yönetiliyor:
- Liste: katman-1 RO DB (apikeys modeli pinlendi, key hash kolonu bilinçli
  dışarıda) + bugünkü decode-kota kullanımı spoke /usage ucundan (Redis)
- Üretim: tip seçimi (live/test/widget-pk), domain kilidi, günlük decode
  limiti, geçerlilik, istek/dk — düz metin anahtar tek seferlik modal
- Düzenleme: limit/domains/rate/expiry PATCH; kapat/aç
- apikeys tablosu prod'da yokken sayfa kırılmaz (promote-öncesi uyarı)
- admin-sdk sase: 6 yeni endpoint (auto-audit)

Spoke karşılığı: sase.tr feature/api-key-admin (dev)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 06:26:43 +03:00

196 lines
7.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Partial view of Sase.tr public schema.
// Owned by the spoke; panel reads with super_panel_reader (SELECT only).
// Add models here only as panel features need them — keep the surface narrow.
generator client {
provider = "prisma-client-js"
output = "../../node_modules/.prisma/client-sase"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL_SASE_RO")
}
model User {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
email String @unique @db.VarChar(255)
emailVerified Boolean @default(false) @map("email_verified")
role String @default("user") @db.VarChar(20)
status String @default("active") @db.VarChar(20)
statusReason String? @map("status_reason")
statusChangedAt DateTime? @map("status_changed_at") @db.Timestamptz(6)
statusChangedBy String? @map("status_changed_by") @db.Uuid
image String?
referralCode String? @map("referral_code") @db.VarChar(20)
referredBy String? @map("referred_by") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6)
subscriptions UserSubscription[]
payments Payment[]
brands UserBrand[]
queryLogs QueryLog[]
apiKeys ApiKey[]
@@map("users")
}
// Public API anahtarları (better-auth apiKey plugin'i yönetir).
// `key` hash kolonu bilinçli olarak pinlenmedi — panel yüzeyine asla çıkmaz.
model ApiKey {
id String @id
name String?
start String?
prefix String?
userId String @map("user_id") @db.Uuid
enabled Boolean @default(true)
rateLimitEnabled Boolean @default(true) @map("rate_limit_enabled")
rateLimitTimeWindow Int? @map("rate_limit_time_window")
rateLimitMax Int? @map("rate_limit_max")
requestCount Int @default(0) @map("request_count")
lastRequest DateTime? @map("last_request") @db.Timestamptz(6)
expiresAt DateTime? @map("expires_at") @db.Timestamptz(6)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6)
metadata String?
user User @relation(fields: [userId], references: [id])
@@index([userId])
@@map("apikeys")
}
model Plan {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(100)
brandCount Int @map("brand_count")
priceMonthly Int @map("price_monthly")
priceYearly Int @map("price_yearly")
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6)
subscriptions UserSubscription[]
@@map("plans")
}
model UserSubscription {
id String @id @default(uuid()) @db.Uuid
userId String @map("user_id") @db.Uuid
planId String @map("plan_id") @db.Uuid
status String @default("pending") @db.VarChar(20)
billingPeriod String @default("monthly") @map("billing_period") @db.VarChar(10)
startDate DateTime? @map("start_date") @db.Timestamptz(6)
endDate DateTime? @map("end_date") @db.Timestamptz(6)
cancelledAt DateTime? @map("cancelled_at") @db.Timestamptz(6)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6)
user User @relation(fields: [userId], references: [id])
plan Plan @relation(fields: [planId], references: [id])
brands UserBrand[]
payments Payment[]
@@index([status])
@@index([userId])
@@map("user_subscriptions")
}
model Brand {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(100)
slug String @unique @db.VarChar(100)
logoUrl String? @map("logo_url")
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6)
users UserBrand[]
@@map("brands")
}
model UserBrand {
id String @id @default(uuid()) @db.Uuid
userId String @map("user_id") @db.Uuid
subscriptionId String @map("subscription_id") @db.Uuid
brandId String @map("brand_id") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
user User @relation(fields: [userId], references: [id])
subscription UserSubscription @relation(fields: [subscriptionId], references: [id])
brand Brand @relation(fields: [brandId], references: [id])
@@unique([userId, subscriptionId, brandId])
@@index([userId])
@@map("user_brands")
}
model BankAccount {
id String @id @default(uuid()) @db.Uuid
bankName String @map("bank_name") @db.VarChar(100)
accountHolder String @map("account_holder") @db.VarChar(200)
iban String @db.VarChar(34)
kolayAdres String? @map("kolay_adres") @db.VarChar(100)
kolayAdresType String? @map("kolay_adres_type") @db.VarChar(20)
qrImageUrl String? @map("qr_image_url")
descriptionTemplate String @default("SASE-{{paymentId}}") @map("description_template") @db.VarChar(200)
isActive Boolean @default(false) @map("is_active")
displayOrder Int @default(0) @map("display_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6)
payments Payment[]
@@map("bank_accounts")
}
model Payment {
id String @id @default(uuid()) @db.Uuid
userId String @map("user_id") @db.Uuid
subscriptionId String @map("subscription_id") @db.Uuid
amount Int
currency String @default("TRY") @db.VarChar(3)
method String @db.VarChar(20)
status String @default("pending") @db.VarChar(20)
iyzicoPaymentId String? @map("iyzico_payment_id")
stripeSessionId String? @map("stripe_session_id")
stripePaymentIntentId String? @map("stripe_payment_intent_id")
bankAccountId String? @map("bank_account_id") @db.Uuid
eftReceiptUrl String? @map("eft_receipt_url")
adminNote String? @map("admin_note")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz(6)
user User @relation(fields: [userId], references: [id])
subscription UserSubscription @relation(fields: [subscriptionId], references: [id])
bankAccount BankAccount? @relation(fields: [bankAccountId], references: [id])
@@index([userId])
@@index([status])
@@index([stripeSessionId])
@@map("payments")
}
model QueryLog {
id String @id @default(uuid()) @db.Uuid
userId String @map("user_id") @db.Uuid
vin String @db.VarChar(17)
brandId String? @map("brand_id") @db.Uuid
source String? @db.VarChar(20)
success Boolean @default(true)
errorMessage String? @map("error_message")
responseTimeMs Int? @map("response_time_ms")
timings Json?
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
user User @relation(fields: [userId], references: [id])
@@index([userId, createdAt])
@@index([vin])
@@map("query_logs")
}