feat: secure KYC storage, Google OAuth, terms gating

This commit is contained in:
arifal
2026-04-28 23:10:21 +07:00
parent 58da4608ac
commit 05d0929f7a
41 changed files with 3087 additions and 262 deletions
+32 -7
View File
@@ -11,7 +11,8 @@ model User {
id String @id @default(cuid())
name String
email String @unique
password String
/// Hash bcrypt. Null untuk user yang sign-in via OAuth (mis. Google).
password String?
image String?
/// Apakah user telah menyetujui Syarat & Ketentuan dan Kebijakan Privasi
acceptedTermsAndPrivacy Boolean @default(false)
@@ -20,6 +21,7 @@ model User {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
accounts Account[]
trips Trip[]
participations TripParticipant[]
tripReviews TripReview[]
@@ -28,6 +30,27 @@ model User {
reviewedVerifications OrganizerVerification[] @relation("OrganizerVerificationReviewer")
}
/// Tabel link akun OAuth pihak ketiga (Google, dst). Diisi oleh PrismaAdapter NextAuth.
/// Session tidak pakai DB — kita pakai JWT, jadi Session/VerificationToken tidak perlu.
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String?
access_token String?
expires_at Int?
token_type String?
scope String?
id_token String?
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model OrganizerVerification {
id String @id @default(cuid())
userId String @unique
@@ -35,15 +58,17 @@ model OrganizerVerification {
/// Nama lengkap sesuai KTP
fullName String
/// Nomor Induk Kependudukan (PII — perlakukan sensitif)
nik String @unique
/// NIK terenkripsi (AES-256-GCM, base64). Plaintext tidak disimpan.
nikEncrypted String
/// HMAC-SHA256(NIK + pepper) untuk uniqueness lookup tanpa membuka plaintext.
nikHash String @unique
birthDate DateTime
address String
/// URL foto KTP (untuk MVP pakai hosting; pindah ke storage privat untuk produksi)
ktpImageUrl String
/// URL selfie memegang KTP
selfieUrl String
/// Storage key foto KTP (mis. `ktp/<id>.jpg`). File disimpan terenkripsi di luar /public.
ktpImageKey String
/// Storage key selfie memegang KTP.
selfieKey String
bankName String
bankAccountNumber String