auth.prisma 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. model User {
  2. id String @id @default(cuid())
  3. name String
  4. email String @unique
  5. emailVerified Boolean @default(false)
  6. /// The mobile a technician signs in with, and the number a workshop holds
  7. /// for whoever this is.
  8. ///
  9. /// Deliberately not unique. When a desk creates an account for a mechanic
  10. /// standing at the counter, a second workshop may create another for the
  11. /// same human, and neither should be able to block the other. Every lookup
  12. /// reaches it through a technician row and so is already scoped to one
  13. /// workshop; the number alone is never the question being asked.
  14. phone String?
  15. image String?
  16. isSuperAdmin Boolean @default(false)
  17. createdAt DateTime @default(now())
  18. updatedAt DateTime @updatedAt
  19. twoFactorEnabled Boolean @default(false)
  20. termsAcceptedAt DateTime?
  21. lastLogin DateTime?
  22. lastSeen DateTime?
  23. /// App version this user last saw/dismissed the update banner for.
  24. /// Null = never seeded (seeded silently on first load, no banner).
  25. lastSeenVersion String?
  26. /// Per-user dashboard grid layout (card positions/sizes/hidden set).
  27. /// Null = default layout. Shape validated in dashboardLayoutActions.
  28. dashboardLayout Json?
  29. sessions Session[]
  30. devices UserDevice[]
  31. accounts Account[]
  32. pushDevices PushDevice[]
  33. appSetupCodes TechnicianSetupCode[]
  34. vehicles Vehicle[]
  35. customers Customer[]
  36. settings AppSetting[]
  37. inventoryParts InventoryPart[]
  38. quotes Quote[]
  39. customFieldDefinitions CustomFieldDefinition[]
  40. twoFactor TwoFactor?
  41. passkeys Passkey[]
  42. organizationMembers OrganizationMember[]
  43. dashboardWidgets DashboardWidget[]
  44. auditLogs AuditLog[]
  45. technicians Technician[]
  46. stockMovements StockMovement[]
  47. tireWarehouses TireWarehouse[]
  48. tireSets TireSet[]
  49. tireSetAttachments TireSetAttachment[]
  50. tireMeasurements TireMeasurement[]
  51. tireMovements TireMovement[]
  52. tireTreatments TireTreatment[]
  53. importBatches ImportBatch[]
  54. @@map("users")
  55. }
  56. model Session {
  57. id String @id @default(cuid())
  58. expiresAt DateTime
  59. token String @unique
  60. createdAt DateTime @default(now())
  61. updatedAt DateTime @updatedAt
  62. ipAddress String?
  63. userAgent String?
  64. userId String
  65. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  66. @@index([userId])
  67. @@map("sessions")
  68. }
  69. model Account {
  70. id String @id @default(cuid())
  71. accountId String
  72. providerId String
  73. userId String
  74. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  75. accessToken String?
  76. refreshToken String?
  77. idToken String?
  78. accessTokenExpiresAt DateTime?
  79. refreshTokenExpiresAt DateTime?
  80. scope String?
  81. password String?
  82. createdAt DateTime @default(now())
  83. updatedAt DateTime @updatedAt
  84. @@index([userId])
  85. @@map("accounts")
  86. }
  87. model Verification {
  88. id String @id @default(cuid())
  89. identifier String @unique
  90. value String
  91. expiresAt DateTime
  92. createdAt DateTime? @default(now())
  93. updatedAt DateTime? @updatedAt
  94. @@map("verifications")
  95. }
  96. model TwoFactor {
  97. id String @id @default(cuid())
  98. secret String
  99. backupCodes String
  100. userId String @unique
  101. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  102. // better-auth's two-factor plugin writes these three since 1.6: a secret
  103. // stays unverified until the first code is entered, and repeated wrong
  104. // codes lock the method for a while. Rows from before default to verified,
  105. // because those people already proved their app worked.
  106. verified Boolean @default(true)
  107. failedVerificationCount Int @default(0)
  108. lockedUntil DateTime?
  109. @@map("two_factor")
  110. }
  111. model Passkey {
  112. id String @id @default(cuid())
  113. name String?
  114. publicKey String
  115. userId String
  116. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  117. credentialID String @unique
  118. counter Int
  119. deviceType String
  120. backedUp Boolean
  121. transports String?
  122. aaguid String?
  123. createdAt DateTime @default(now())
  124. @@index([userId])
  125. @@map("passkeys")
  126. }
  127. /// A browser or phone this person has signed in from before.
  128. ///
  129. /// Sessions come and go (sign-out, expiry, a password change that ends the
  130. /// others), so the session table cannot say whether a device is new; this can.
  131. /// A browser is known by a random id in a long-lived cookie, set the first
  132. /// time it signs in; a client without cookies, such as the technician app,
  133. /// is known by its user agent. The first device an account ever sees is
  134. /// recorded quietly; every later one earns a "new sign-in" mail.
  135. model UserDevice {
  136. id String @id @default(cuid())
  137. /// Cookie id, or a hash of the user agent when no cookie can be kept.
  138. deviceKey String
  139. userAgent String?
  140. lastIp String?
  141. firstSeenAt DateTime @default(now())
  142. lastSeenAt DateTime @default(now())
  143. userId String
  144. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  145. @@unique([userId, deviceKey])
  146. @@index([userId])
  147. @@map("user_devices")
  148. }