Skip to content
File

Blob: src/worker/db/schema/auth.ts

typescript391 lines
1import { relations, sql } from "drizzle-orm";
2import { sqliteTable, text, integer, index, uniqueIndex } from "drizzle-orm/sqlite-core";
3 
4export const users = sqliteTable("users", {
5 id: text("id").primaryKey(),
6 name: text("name").notNull(),
7 email: text("email").notNull().unique(),
8 emailVerified: integer("email_verified", { mode: "boolean" }).default(false).notNull(),
9 image: text("image"),
10 createdAt: integer("created_at", { mode: "timestamp_ms" })
11 .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
12 .notNull(),
13 updatedAt: integer("updated_at", { mode: "timestamp_ms" })
14 .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
15 .$onUpdate(() => /* @__PURE__ */ new Date())
16 .notNull(),
17 role: text("role"),
18 banned: integer("banned", { mode: "boolean" }).default(false),
19 banReason: text("ban_reason"),
20 banExpires: integer("ban_expires", { mode: "timestamp_ms" }),
21 preferredUsername: text("preferred_username"),
22});
23 
24export const sessions = sqliteTable(
25 "sessions",
26 {
27 id: text("id").primaryKey(),
28 expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
29 token: text("token").notNull().unique(),
30 createdAt: integer("created_at", { mode: "timestamp_ms" })
31 .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
32 .notNull(),
33 updatedAt: integer("updated_at", { mode: "timestamp_ms" })
34 .$onUpdate(() => /* @__PURE__ */ new Date())
35 .notNull(),
36 ipAddress: text("ip_address"),
37 userAgent: text("user_agent"),
38 userId: text("user_id")
39 .notNull()
40 .references(() => users.id, { onDelete: "cascade" }),
41 impersonatedBy: text("impersonated_by"),
42 },
43 (table) => [index("sessions_userId_idx").on(table.userId)],
44);
45 
46export const accounts = sqliteTable(
47 "accounts",
48 {
49 id: text("id").primaryKey(),
50 accountId: text("account_id").notNull(),
51 providerId: text("provider_id").notNull(),
52 userId: text("user_id")
53 .notNull()
54 .references(() => users.id, { onDelete: "cascade" }),
55 accessToken: text("access_token"),
56 refreshToken: text("refresh_token"),
57 idToken: text("id_token"),
58 accessTokenExpiresAt: integer("access_token_expires_at", {
59 mode: "timestamp_ms",
60 }),
61 refreshTokenExpiresAt: integer("refresh_token_expires_at", {
62 mode: "timestamp_ms",
63 }),
64 scope: text("scope"),
65 password: text("password"),
66 createdAt: integer("created_at", { mode: "timestamp_ms" })
67 .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
68 .notNull(),
69 updatedAt: integer("updated_at", { mode: "timestamp_ms" })
70 .$onUpdate(() => /* @__PURE__ */ new Date())
71 .notNull(),
72 },
73 (table) => [index("accounts_userId_idx").on(table.userId)],
74);
75 
76export const verifications = sqliteTable(
77 "verifications",
78 {
79 id: text("id").primaryKey(),
80 identifier: text("identifier").notNull(),
81 value: text("value").notNull(),
82 expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
83 createdAt: integer("created_at", { mode: "timestamp_ms" })
84 .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
85 .notNull(),
86 updatedAt: integer("updated_at", { mode: "timestamp_ms" })
87 .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
88 .$onUpdate(() => /* @__PURE__ */ new Date())
89 .notNull(),
90 },
91 (table) => [index("verifications_identifier_idx").on(table.identifier)],
92);
93 
94export const jwkss = sqliteTable("jwkss", {
95 id: text("id").primaryKey(),
96 publicKey: text("public_key").notNull(),
97 privateKey: text("private_key").notNull(),
98 createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
99 expiresAt: integer("expires_at", { mode: "timestamp_ms" }),
100 alg: text("alg"),
101 crv: text("crv"),
102});
103 
104export const oauthClients = sqliteTable(
105 "oauth_clients",
106 {
107 id: text("id").primaryKey(),
108 clientId: text("client_id").notNull().unique(),
109 clientSecret: text("client_secret"),
110 clientDiscoveryId: text("client_discovery_id"),
111 disabled: integer("disabled", { mode: "boolean" }).default(false),
112 skipConsent: integer("skip_consent", { mode: "boolean" }),
113 enableEndSession: integer("enable_end_session", { mode: "boolean" }),
114 subjectType: text("subject_type"),
115 scopes: text("scopes", { mode: "json" }),
116 clientCredentialsScopes: text("client_credentials_scopes", {
117 mode: "json",
118 }).default([]),
119 userId: text("user_id").references(() => users.id, { onDelete: "cascade" }),
120 createdAt: integer("created_at", { mode: "timestamp_ms" }),
121 updatedAt: integer("updated_at", { mode: "timestamp_ms" }),
122 name: text("name"),
123 uri: text("uri"),
124 icon: text("icon"),
125 contacts: text("contacts", { mode: "json" }),
126 tos: text("tos"),
127 policy: text("policy"),
128 softwareId: text("software_id"),
129 softwareVersion: text("software_version"),
130 softwareStatement: text("software_statement"),
131 redirectUris: text("redirect_uris", { mode: "json" }).notNull(),
132 postLogoutRedirectUris: text("post_logout_redirect_uris", { mode: "json" }),
133 backchannelLogoutUri: text("backchannel_logout_uri"),
134 backchannelLogoutSessionRequired: integer("backchannel_logout_session_required", { mode: "boolean" }),
135 tokenEndpointAuthMethod: text("token_endpoint_auth_method"),
136 applicationType: text("application_type"),
137 jwks: text("jwks"),
138 jwksUri: text("jwks_uri"),
139 grantTypes: text("grant_types", { mode: "json" }),
140 responseTypes: text("response_types", { mode: "json" }),
141 requirePKCE: integer("require_pkce", { mode: "boolean" }),
142 dpopBoundAccessTokens: integer("dpop_bound_access_tokens", {
143 mode: "boolean",
144 }).default(false),
145 referenceId: text("reference_id"),
146 metadata: text("metadata", { mode: "json" }),
147 },
148 (table) => [index("oauthClients_userId_idx").on(table.userId)],
149);
150 
151export const oauthResources = sqliteTable("oauth_resources", {
152 id: text("id").primaryKey(),
153 identifier: text("identifier").notNull().unique(),
154 name: text("name").notNull(),
155 accessTokenTtl: integer("access_token_ttl"),
156 refreshTokenTtl: integer("refresh_token_ttl"),
157 signingAlgorithm: text("signing_algorithm"),
158 signingKeyId: text("signing_key_id"),
159 allowedScopes: text("allowed_scopes", { mode: "json" }),
160 customClaims: text("custom_claims", { mode: "json" }),
161 dpopBoundAccessTokensRequired: integer("dpop_bound_access_tokens_required", {
162 mode: "boolean",
163 }).default(false),
164 disabled: integer("disabled", { mode: "boolean" }).default(false),
165 createdAt: integer("created_at", { mode: "timestamp_ms" }),
166 updatedAt: integer("updated_at", { mode: "timestamp_ms" }),
167 policyVersion: integer("policy_version").default(1),
168 metadata: text("metadata", { mode: "json" }),
169});
170 
171export const oauthClientResources = sqliteTable(
172 "oauth_client_resources",
173 {
174 id: text("id").primaryKey(),
175 clientId: text("client_id")
176 .notNull()
177 .references(() => oauthClients.clientId, { onDelete: "cascade" }),
178 resourceId: text("resource_id")
179 .notNull()
180 .references(() => oauthResources.identifier, { onDelete: "cascade" }),
181 metadata: text("metadata", { mode: "json" }),
182 createdAt: integer("created_at", { mode: "timestamp_ms" }),
183 },
184 (table) => [
185 uniqueIndex("oauthClientResources_clientId_resourceId_uidx").on(table.clientId, table.resourceId),
186 index("oauthClientResources_clientId_idx").on(table.clientId),
187 index("oauthClientResources_resourceId_idx").on(table.resourceId),
188 ],
189);
190 
191export const oauthRefreshTokens = sqliteTable(
192 "oauth_refresh_tokens",
193 {
194 id: text("id").primaryKey(),
195 token: text("token").notNull().unique(),
196 clientId: text("client_id")
197 .notNull()
198 .references(() => oauthClients.clientId, { onDelete: "cascade" }),
199 sessionId: text("session_id").references(() => sessions.id, {
200 onDelete: "set null",
201 }),
202 userId: text("user_id")
203 .notNull()
204 .references(() => users.id, { onDelete: "cascade" }),
205 referenceId: text("reference_id"),
206 authorizationCodeId: text("authorization_code_id"),
207 resources: text("resources", { mode: "json" }),
208 requestedUserInfoClaims: text("requested_user_info_claims", {
209 mode: "json",
210 }),
211 expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
212 createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
213 revoked: integer("revoked", { mode: "timestamp_ms" }),
214 rotatedAt: integer("rotated_at", { mode: "timestamp_ms" }),
215 rotationReplayResponse: text("rotation_replay_response"),
216 rotationReplayExpiresAt: integer("rotation_replay_expires_at", {
217 mode: "timestamp_ms",
218 }),
219 authTime: integer("auth_time", { mode: "timestamp_ms" }),
220 confirmation: text("confirmation", { mode: "json" }),
221 scopes: text("scopes", { mode: "json" }).notNull(),
222 },
223 (table) => [
224 index("oauthRefreshTokens_clientId_idx").on(table.clientId),
225 index("oauthRefreshTokens_sessionId_idx").on(table.sessionId),
226 index("oauthRefreshTokens_userId_idx").on(table.userId),
227 index("oauthRefreshTokens_authorizationCodeId_idx").on(table.authorizationCodeId),
228 ],
229);
230 
231export const oauthAccessTokens = sqliteTable(
232 "oauth_access_tokens",
233 {
234 id: text("id").primaryKey(),
235 token: text("token").notNull().unique(),
236 clientId: text("client_id")
237 .notNull()
238 .references(() => oauthClients.clientId, { onDelete: "cascade" }),
239 sessionId: text("session_id").references(() => sessions.id, {
240 onDelete: "set null",
241 }),
242 userId: text("user_id").references(() => users.id, { onDelete: "cascade" }),
243 referenceId: text("reference_id"),
244 authorizationCodeId: text("authorization_code_id"),
245 resources: text("resources", { mode: "json" }),
246 requestedUserInfoClaims: text("requested_user_info_claims", {
247 mode: "json",
248 }),
249 refreshId: text("refresh_id").references(() => oauthRefreshTokens.id, {
250 onDelete: "cascade",
251 }),
252 expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
253 createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
254 revoked: integer("revoked", { mode: "timestamp_ms" }),
255 confirmation: text("confirmation", { mode: "json" }),
256 scopes: text("scopes", { mode: "json" }).notNull(),
257 },
258 (table) => [
259 index("oauthAccessTokens_clientId_idx").on(table.clientId),
260 index("oauthAccessTokens_sessionId_idx").on(table.sessionId),
261 index("oauthAccessTokens_userId_idx").on(table.userId),
262 index("oauthAccessTokens_authorizationCodeId_idx").on(table.authorizationCodeId),
263 index("oauthAccessTokens_refreshId_idx").on(table.refreshId),
264 ],
265);
266 
267export const oauthConsents = sqliteTable(
268 "oauth_consents",
269 {
270 id: text("id").primaryKey(),
271 clientId: text("client_id")
272 .notNull()
273 .references(() => oauthClients.clientId, { onDelete: "cascade" }),
274 userId: text("user_id").references(() => users.id, { onDelete: "cascade" }),
275 referenceId: text("reference_id"),
276 resources: text("resources", { mode: "json" }),
277 requestedUserInfoClaims: text("requested_user_info_claims", {
278 mode: "json",
279 }),
280 scopes: text("scopes", { mode: "json" }).notNull(),
281 createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
282 updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
283 },
284 (table) => [
285 index("oauthConsents_clientId_idx").on(table.clientId),
286 index("oauthConsents_userId_idx").on(table.userId),
287 ],
288);
289 
290export const oauthClientAssertions = sqliteTable("oauth_client_assertions", {
291 id: text("id").primaryKey(),
292 expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
293});
294 
295export const usersRelations = relations(users, ({ many }) => ({
296 sessions: many(sessions),
297 accounts: many(accounts),
298 oauthClients: many(oauthClients),
299 oauthRefreshTokens: many(oauthRefreshTokens),
300 oauthAccessTokens: many(oauthAccessTokens),
301 oauthConsents: many(oauthConsents),
302}));
303 
304export const sessionsRelations = relations(sessions, ({ one, many }) => ({
305 user: one(users, {
306 fields: [sessions.userId],
307 references: [users.id],
308 }),
309 oauthRefreshTokens: many(oauthRefreshTokens),
310 oauthAccessTokens: many(oauthAccessTokens),
311}));
312 
313export const accountsRelations = relations(accounts, ({ one }) => ({
314 user: one(users, {
315 fields: [accounts.userId],
316 references: [users.id],
317 }),
318}));
319 
320export const oauthClientsRelations = relations(oauthClients, ({ one, many }) => ({
321 user: one(users, {
322 fields: [oauthClients.userId],
323 references: [users.id],
324 }),
325 oauthClientResources: many(oauthClientResources),
326 oauthRefreshTokens: many(oauthRefreshTokens),
327 oauthAccessTokens: many(oauthAccessTokens),
328 oauthConsents: many(oauthConsents),
329}));
330 
331export const oauthResourcesRelations = relations(oauthResources, ({ many }) => ({
332 oauthClientResources: many(oauthClientResources),
333}));
334 
335export const oauthClientResourcesRelations = relations(oauthClientResources, ({ one }) => ({
336 oauthClient: one(oauthClients, {
337 fields: [oauthClientResources.clientId],
338 references: [oauthClients.clientId],
339 }),
340 oauthResource: one(oauthResources, {
341 fields: [oauthClientResources.resourceId],
342 references: [oauthResources.identifier],
343 }),
344}));
345 
346export const oauthRefreshTokensRelations = relations(oauthRefreshTokens, ({ one, many }) => ({
347 oauthClient: one(oauthClients, {
348 fields: [oauthRefreshTokens.clientId],
349 references: [oauthClients.clientId],
350 }),
351 session: one(sessions, {
352 fields: [oauthRefreshTokens.sessionId],
353 references: [sessions.id],
354 }),
355 user: one(users, {
356 fields: [oauthRefreshTokens.userId],
357 references: [users.id],
358 }),
359 oauthAccessTokens: many(oauthAccessTokens),
360}));
361 
362export const oauthAccessTokensRelations = relations(oauthAccessTokens, ({ one }) => ({
363 oauthClient: one(oauthClients, {
364 fields: [oauthAccessTokens.clientId],
365 references: [oauthClients.clientId],
366 }),
367 session: one(sessions, {
368 fields: [oauthAccessTokens.sessionId],
369 references: [sessions.id],
370 }),
371 user: one(users, {
372 fields: [oauthAccessTokens.userId],
373 references: [users.id],
374 }),
375 oauthRefreshToken: one(oauthRefreshTokens, {
376 fields: [oauthAccessTokens.refreshId],
377 references: [oauthRefreshTokens.id],
378 }),
379}));
380 
381export const oauthConsentsRelations = relations(oauthConsents, ({ one }) => ({
382 oauthClient: one(oauthClients, {
383 fields: [oauthConsents.clientId],
384 references: [oauthClients.clientId],
385 }),
386 user: one(users, {
387 fields: [oauthConsents.userId],
388 references: [users.id],
389 }),
390}));