@factiii/auth 0.5.2 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -42,8 +42,10 @@ __export(index_exports, {
42
42
  createAuthRouter: () => createAuthRouter,
43
43
  createAuthToken: () => createAuthToken,
44
44
  createConsoleEmailAdapter: () => createConsoleEmailAdapter,
45
+ createDrizzleAdapter: () => createDrizzleAdapter,
45
46
  createNoopEmailAdapter: () => createNoopEmailAdapter,
46
47
  createOAuthVerifier: () => createOAuthVerifier,
48
+ createPrismaAdapter: () => createPrismaAdapter,
47
49
  decodeToken: () => decodeToken,
48
50
  defaultAuthConfig: () => defaultAuthConfig,
49
51
  defaultCookieSettings: () => defaultCookieSettings,
@@ -78,6 +80,260 @@ module.exports = __toCommonJS(index_exports);
78
80
  // src/middleware/authGuard.ts
79
81
  var import_server = require("@trpc/server");
80
82
 
83
+ // src/adapters/prismaAdapter.ts
84
+ function createPrismaAdapter(prisma) {
85
+ return {
86
+ user: {
87
+ async findByEmailInsensitive(email) {
88
+ return prisma.user.findFirst({
89
+ where: { email: { equals: email, mode: "insensitive" } }
90
+ });
91
+ },
92
+ async findByUsernameInsensitive(username) {
93
+ return prisma.user.findFirst({
94
+ where: { username: { equals: username, mode: "insensitive" } }
95
+ });
96
+ },
97
+ async findByEmailOrUsernameInsensitive(identifier) {
98
+ return prisma.user.findFirst({
99
+ where: {
100
+ OR: [
101
+ { email: { equals: identifier, mode: "insensitive" } },
102
+ { username: { equals: identifier, mode: "insensitive" } }
103
+ ]
104
+ }
105
+ });
106
+ },
107
+ async findByEmailOrOAuthId(email, oauthId) {
108
+ return prisma.user.findFirst({
109
+ where: {
110
+ OR: [
111
+ { email: { equals: email, mode: "insensitive" } },
112
+ { oauthId: { equals: oauthId } }
113
+ ]
114
+ }
115
+ });
116
+ },
117
+ async findById(id) {
118
+ return prisma.user.findUnique({ where: { id } });
119
+ },
120
+ async findActiveById(id) {
121
+ return prisma.user.findUnique({
122
+ where: { id, status: "ACTIVE" }
123
+ });
124
+ },
125
+ async create(data) {
126
+ return prisma.user.create({ data });
127
+ },
128
+ async update(id, data) {
129
+ return prisma.user.update({ where: { id }, data });
130
+ }
131
+ },
132
+ session: {
133
+ async findById(id) {
134
+ const session = await prisma.session.findUnique({
135
+ where: { id },
136
+ select: {
137
+ id: true,
138
+ userId: true,
139
+ socketId: true,
140
+ twoFaSecret: true,
141
+ browserName: true,
142
+ issuedAt: true,
143
+ lastUsed: true,
144
+ revokedAt: true,
145
+ deviceId: true,
146
+ user: { select: { status: true, verifiedHumanAt: true } }
147
+ }
148
+ });
149
+ return session;
150
+ },
151
+ async create(data) {
152
+ return prisma.session.create({ data });
153
+ },
154
+ async update(id, data) {
155
+ return prisma.session.update({ where: { id }, data });
156
+ },
157
+ async updateLastUsed(id) {
158
+ const session = await prisma.session.update({
159
+ where: { id },
160
+ data: { lastUsed: /* @__PURE__ */ new Date() },
161
+ select: {
162
+ id: true,
163
+ userId: true,
164
+ socketId: true,
165
+ twoFaSecret: true,
166
+ browserName: true,
167
+ issuedAt: true,
168
+ lastUsed: true,
169
+ revokedAt: true,
170
+ deviceId: true,
171
+ user: { select: { verifiedHumanAt: true } }
172
+ }
173
+ });
174
+ return session;
175
+ },
176
+ async revoke(id) {
177
+ await prisma.session.update({
178
+ where: { id },
179
+ data: { revokedAt: /* @__PURE__ */ new Date() }
180
+ });
181
+ },
182
+ async findActiveByUserId(userId, excludeSessionId) {
183
+ return prisma.session.findMany({
184
+ where: {
185
+ userId,
186
+ revokedAt: null,
187
+ ...excludeSessionId ? { NOT: { id: excludeSessionId } } : {}
188
+ },
189
+ select: { id: true, socketId: true, userId: true }
190
+ });
191
+ },
192
+ async revokeAllByUserId(userId, excludeSessionId) {
193
+ await prisma.session.updateMany({
194
+ where: {
195
+ userId,
196
+ revokedAt: null,
197
+ ...excludeSessionId ? { NOT: { id: excludeSessionId } } : {}
198
+ },
199
+ data: { revokedAt: /* @__PURE__ */ new Date() }
200
+ });
201
+ },
202
+ async findTwoFaSecretsByUserId(userId) {
203
+ return prisma.session.findMany({
204
+ where: { userId, twoFaSecret: { not: null } },
205
+ select: { twoFaSecret: true }
206
+ });
207
+ },
208
+ async clearTwoFaSecrets(userId, excludeSessionId) {
209
+ await prisma.session.updateMany({
210
+ where: {
211
+ userId,
212
+ ...excludeSessionId ? { NOT: { id: excludeSessionId } } : {}
213
+ },
214
+ data: { twoFaSecret: null }
215
+ });
216
+ },
217
+ async findByIdWithDevice(id, userId) {
218
+ const session = await prisma.session.findUnique({
219
+ where: { id, userId },
220
+ select: {
221
+ twoFaSecret: true,
222
+ deviceId: true,
223
+ device: { select: { pushToken: true } }
224
+ }
225
+ });
226
+ return session;
227
+ },
228
+ async revokeByDevicePushToken(userId, pushToken, excludeSessionId) {
229
+ await prisma.session.updateMany({
230
+ where: {
231
+ userId,
232
+ id: { not: excludeSessionId },
233
+ revokedAt: null,
234
+ device: { pushToken }
235
+ },
236
+ data: { revokedAt: /* @__PURE__ */ new Date() }
237
+ });
238
+ },
239
+ async clearDeviceId(userId, deviceId) {
240
+ await prisma.session.updateMany({
241
+ where: { userId, deviceId },
242
+ data: { deviceId: null }
243
+ });
244
+ }
245
+ },
246
+ otp: {
247
+ async findValidByUserAndCode(userId, code) {
248
+ return prisma.oTP.findFirst({
249
+ where: { userId, code, expiresAt: { gte: /* @__PURE__ */ new Date() } }
250
+ });
251
+ },
252
+ async create(data) {
253
+ return prisma.oTP.create({ data });
254
+ },
255
+ async delete(id) {
256
+ await prisma.oTP.delete({ where: { id } });
257
+ }
258
+ },
259
+ passwordReset: {
260
+ async findById(id) {
261
+ return prisma.passwordReset.findUnique({
262
+ where: { id },
263
+ select: { id: true, createdAt: true, userId: true }
264
+ });
265
+ },
266
+ async create(userId) {
267
+ return prisma.passwordReset.create({
268
+ data: { userId }
269
+ });
270
+ },
271
+ async delete(id) {
272
+ await prisma.passwordReset.delete({ where: { id } });
273
+ },
274
+ async deleteAllByUserId(userId) {
275
+ await prisma.passwordReset.deleteMany({ where: { userId } });
276
+ }
277
+ },
278
+ device: {
279
+ async findByTokenSessionAndUser(pushToken, sessionId, userId) {
280
+ return prisma.device.findFirst({
281
+ where: {
282
+ pushToken,
283
+ sessions: { some: { id: sessionId } },
284
+ users: { some: { id: userId } }
285
+ },
286
+ select: { id: true }
287
+ });
288
+ },
289
+ async upsertByPushToken(pushToken, sessionId, userId) {
290
+ await prisma.device.upsert({
291
+ where: { pushToken },
292
+ create: {
293
+ pushToken,
294
+ sessions: { connect: { id: sessionId } },
295
+ users: { connect: { id: userId } }
296
+ },
297
+ update: {
298
+ sessions: { connect: { id: sessionId } },
299
+ users: { connect: { id: userId } }
300
+ }
301
+ });
302
+ },
303
+ async findByUserAndToken(userId, pushToken) {
304
+ return prisma.device.findFirst({
305
+ where: { users: { some: { id: userId } }, pushToken },
306
+ select: { id: true }
307
+ });
308
+ },
309
+ async disconnectUser(deviceId, userId) {
310
+ await prisma.device.update({
311
+ where: { id: deviceId },
312
+ data: { users: { disconnect: { id: userId } } }
313
+ });
314
+ },
315
+ async hasRemainingUsers(deviceId) {
316
+ const result = await prisma.device.findUnique({
317
+ where: { id: deviceId },
318
+ select: { users: { select: { id: true }, take: 1 } }
319
+ });
320
+ return (result?.users.length ?? 0) > 0;
321
+ },
322
+ async delete(id) {
323
+ await prisma.device.delete({ where: { id } });
324
+ }
325
+ },
326
+ admin: {
327
+ async findByUserId(userId) {
328
+ return prisma.admin.findFirst({
329
+ where: { userId },
330
+ select: { ip: true }
331
+ });
332
+ }
333
+ }
334
+ };
335
+ }
336
+
81
337
  // src/adapters/email.ts
82
338
  function createNoopEmailAdapter() {
83
339
  return {
@@ -131,6 +387,291 @@ function createConsoleEmailAdapter() {
131
387
  };
132
388
  }
133
389
 
390
+ // src/adapters/drizzleAdapter.ts
391
+ function createDrizzleAdapter(db, tables) {
392
+ const {
393
+ eq,
394
+ and,
395
+ or,
396
+ isNull,
397
+ isNotNull,
398
+ gte,
399
+ ne,
400
+ sql
401
+ } = require("drizzle-orm");
402
+ const { users, sessions, otps, passwordResets, devices, admins } = tables;
403
+ return {
404
+ user: {
405
+ async findByEmailInsensitive(email) {
406
+ const rows = await db.select().from(users).where(sql`lower(${users.email}) = lower(${email})`).limit(1);
407
+ return rows[0] ?? null;
408
+ },
409
+ async findByUsernameInsensitive(username) {
410
+ const rows = await db.select().from(users).where(sql`lower(${users.username}) = lower(${username})`).limit(1);
411
+ return rows[0] ?? null;
412
+ },
413
+ async findByEmailOrUsernameInsensitive(identifier) {
414
+ const rows = await db.select().from(users).where(
415
+ or(
416
+ sql`lower(${users.email}) = lower(${identifier})`,
417
+ sql`lower(${users.username}) = lower(${identifier})`
418
+ )
419
+ ).limit(1);
420
+ return rows[0] ?? null;
421
+ },
422
+ async findByEmailOrOAuthId(email, oauthId) {
423
+ const rows = await db.select().from(users).where(
424
+ or(
425
+ sql`lower(${users.email}) = lower(${email})`,
426
+ eq(users.oauthId, oauthId)
427
+ )
428
+ ).limit(1);
429
+ return rows[0] ?? null;
430
+ },
431
+ async findById(id) {
432
+ const rows = await db.select().from(users).where(eq(users.id, id)).limit(1);
433
+ return rows[0] ?? null;
434
+ },
435
+ async findActiveById(id) {
436
+ const rows = await db.select().from(users).where(and(eq(users.id, id), eq(users.status, "ACTIVE"))).limit(1);
437
+ return rows[0] ?? null;
438
+ },
439
+ async create(data) {
440
+ const rows = await db.insert(users).values(data).returning();
441
+ return rows[0];
442
+ },
443
+ async update(id, data) {
444
+ const rows = await db.update(users).set(data).where(eq(users.id, id)).returning();
445
+ return rows[0];
446
+ }
447
+ },
448
+ session: {
449
+ async findById(id) {
450
+ const rows = await db.select({
451
+ id: sessions.id,
452
+ userId: sessions.userId,
453
+ socketId: sessions.socketId,
454
+ twoFaSecret: sessions.twoFaSecret,
455
+ browserName: sessions.browserName,
456
+ issuedAt: sessions.issuedAt,
457
+ lastUsed: sessions.lastUsed,
458
+ revokedAt: sessions.revokedAt,
459
+ deviceId: sessions.deviceId,
460
+ user: {
461
+ status: users.status,
462
+ verifiedHumanAt: users.verifiedHumanAt
463
+ }
464
+ }).from(sessions).innerJoin(users, eq(sessions.userId, users.id)).where(eq(sessions.id, id)).limit(1);
465
+ return rows[0] ?? null;
466
+ },
467
+ async create(data) {
468
+ const rows = await db.insert(sessions).values(data).returning();
469
+ return rows[0];
470
+ },
471
+ async update(id, data) {
472
+ const rows = await db.update(sessions).set(data).where(eq(sessions.id, id)).returning();
473
+ return rows[0];
474
+ },
475
+ async updateLastUsed(id) {
476
+ await db.update(sessions).set({ lastUsed: /* @__PURE__ */ new Date() }).where(eq(sessions.id, id));
477
+ const rows = await db.select({
478
+ id: sessions.id,
479
+ userId: sessions.userId,
480
+ socketId: sessions.socketId,
481
+ twoFaSecret: sessions.twoFaSecret,
482
+ browserName: sessions.browserName,
483
+ issuedAt: sessions.issuedAt,
484
+ lastUsed: sessions.lastUsed,
485
+ revokedAt: sessions.revokedAt,
486
+ deviceId: sessions.deviceId,
487
+ user: {
488
+ verifiedHumanAt: users.verifiedHumanAt
489
+ }
490
+ }).from(sessions).innerJoin(users, eq(sessions.userId, users.id)).where(eq(sessions.id, id)).limit(1);
491
+ return rows[0];
492
+ },
493
+ async revoke(id) {
494
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(eq(sessions.id, id));
495
+ },
496
+ async findActiveByUserId(userId, excludeSessionId) {
497
+ const conditions = [eq(sessions.userId, userId), isNull(sessions.revokedAt)];
498
+ if (excludeSessionId !== void 0) {
499
+ conditions.push(ne(sessions.id, excludeSessionId));
500
+ }
501
+ return db.select({
502
+ id: sessions.id,
503
+ socketId: sessions.socketId,
504
+ userId: sessions.userId
505
+ }).from(sessions).where(and(...conditions));
506
+ },
507
+ async revokeAllByUserId(userId, excludeSessionId) {
508
+ const conditions = [eq(sessions.userId, userId), isNull(sessions.revokedAt)];
509
+ if (excludeSessionId !== void 0) {
510
+ conditions.push(ne(sessions.id, excludeSessionId));
511
+ }
512
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(and(...conditions));
513
+ },
514
+ async findTwoFaSecretsByUserId(userId) {
515
+ return db.select({ twoFaSecret: sessions.twoFaSecret }).from(sessions).where(and(eq(sessions.userId, userId), isNotNull(sessions.twoFaSecret)));
516
+ },
517
+ async clearTwoFaSecrets(userId, excludeSessionId) {
518
+ const conditions = [eq(sessions.userId, userId)];
519
+ if (excludeSessionId !== void 0) {
520
+ conditions.push(ne(sessions.id, excludeSessionId));
521
+ }
522
+ await db.update(sessions).set({ twoFaSecret: null }).where(and(...conditions));
523
+ },
524
+ async findByIdWithDevice(id, userId) {
525
+ const rows = await db.select({
526
+ twoFaSecret: sessions.twoFaSecret,
527
+ deviceId: sessions.deviceId,
528
+ device: {
529
+ pushToken: devices.pushToken
530
+ }
531
+ }).from(sessions).leftJoin(devices, eq(sessions.deviceId, devices.id)).where(and(eq(sessions.id, id), eq(sessions.userId, userId))).limit(1);
532
+ if (!rows[0]) return null;
533
+ const row = rows[0];
534
+ return {
535
+ twoFaSecret: row.twoFaSecret,
536
+ deviceId: row.deviceId,
537
+ device: row.device?.pushToken ? { pushToken: row.device.pushToken } : null
538
+ };
539
+ },
540
+ async revokeByDevicePushToken(userId, pushToken, excludeSessionId) {
541
+ const deviceRows = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
542
+ if (!deviceRows[0]) return;
543
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(
544
+ and(
545
+ eq(sessions.userId, userId),
546
+ ne(sessions.id, excludeSessionId),
547
+ isNull(sessions.revokedAt),
548
+ eq(sessions.deviceId, deviceRows[0].id)
549
+ )
550
+ );
551
+ },
552
+ async clearDeviceId(userId, deviceId) {
553
+ await db.update(sessions).set({ deviceId: null }).where(and(eq(sessions.userId, userId), eq(sessions.deviceId, deviceId)));
554
+ }
555
+ },
556
+ otp: {
557
+ async findValidByUserAndCode(userId, code) {
558
+ const rows = await db.select().from(otps).where(
559
+ and(eq(otps.userId, userId), eq(otps.code, code), gte(otps.expiresAt, /* @__PURE__ */ new Date()))
560
+ ).limit(1);
561
+ return rows[0] ?? null;
562
+ },
563
+ async create(data) {
564
+ const rows = await db.insert(otps).values(data).returning();
565
+ return rows[0];
566
+ },
567
+ async delete(id) {
568
+ await db.delete(otps).where(eq(otps.id, id));
569
+ }
570
+ },
571
+ passwordReset: {
572
+ async findById(id) {
573
+ const rows = await db.select({
574
+ id: passwordResets.id,
575
+ createdAt: passwordResets.createdAt,
576
+ userId: passwordResets.userId
577
+ }).from(passwordResets).where(eq(passwordResets.id, id)).limit(1);
578
+ return rows[0] ?? null;
579
+ },
580
+ async create(userId) {
581
+ const rows = await db.insert(passwordResets).values({ userId }).returning();
582
+ return rows[0];
583
+ },
584
+ async delete(id) {
585
+ await db.delete(passwordResets).where(eq(passwordResets.id, id));
586
+ },
587
+ async deleteAllByUserId(userId) {
588
+ await db.delete(passwordResets).where(eq(passwordResets.userId, userId));
589
+ }
590
+ },
591
+ device: {
592
+ async findByTokenSessionAndUser(pushToken, sessionId, userId) {
593
+ const rows = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
594
+ if (!rows[0]) return null;
595
+ if (tables.devicesToSessions && tables.devicesToUsers) {
596
+ const sessionLink = await db.select().from(tables.devicesToSessions).where(
597
+ and(
598
+ eq(tables.devicesToSessions.deviceId, rows[0].id),
599
+ eq(tables.devicesToSessions.sessionId, sessionId)
600
+ )
601
+ ).limit(1);
602
+ const userLink = await db.select().from(tables.devicesToUsers).where(
603
+ and(
604
+ eq(tables.devicesToUsers.deviceId, rows[0].id),
605
+ eq(tables.devicesToUsers.userId, userId)
606
+ )
607
+ ).limit(1);
608
+ if (!sessionLink[0] || !userLink[0]) return null;
609
+ }
610
+ return { id: rows[0].id };
611
+ },
612
+ async upsertByPushToken(pushToken, sessionId, userId) {
613
+ const existing = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
614
+ let deviceId;
615
+ if (existing[0]) {
616
+ deviceId = existing[0].id;
617
+ } else {
618
+ const rows = await db.insert(devices).values({ pushToken }).returning({ id: devices.id });
619
+ deviceId = rows[0].id;
620
+ }
621
+ if (tables.devicesToSessions) {
622
+ await db.insert(tables.devicesToSessions).values({ deviceId, sessionId }).onConflictDoNothing();
623
+ }
624
+ if (tables.devicesToUsers) {
625
+ await db.insert(tables.devicesToUsers).values({ deviceId, userId }).onConflictDoNothing();
626
+ }
627
+ await db.update(sessions).set({ deviceId }).where(eq(sessions.id, sessionId));
628
+ },
629
+ async findByUserAndToken(userId, pushToken) {
630
+ if (tables.devicesToUsers) {
631
+ const rows2 = await db.select({ id: devices.id }).from(devices).innerJoin(
632
+ tables.devicesToUsers,
633
+ eq(devices.id, tables.devicesToUsers.deviceId)
634
+ ).where(
635
+ and(
636
+ eq(devices.pushToken, pushToken),
637
+ eq(tables.devicesToUsers.userId, userId)
638
+ )
639
+ ).limit(1);
640
+ return rows2[0] ? { id: rows2[0].id } : null;
641
+ }
642
+ const rows = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
643
+ return rows[0] ? { id: rows[0].id } : null;
644
+ },
645
+ async disconnectUser(deviceId, userId) {
646
+ if (tables.devicesToUsers) {
647
+ await db.delete(tables.devicesToUsers).where(
648
+ and(
649
+ eq(tables.devicesToUsers.deviceId, deviceId),
650
+ eq(tables.devicesToUsers.userId, userId)
651
+ )
652
+ );
653
+ }
654
+ },
655
+ async hasRemainingUsers(deviceId) {
656
+ if (tables.devicesToUsers) {
657
+ const rows = await db.select({ userId: tables.devicesToUsers.userId }).from(tables.devicesToUsers).where(eq(tables.devicesToUsers.deviceId, deviceId)).limit(1);
658
+ return rows.length > 0;
659
+ }
660
+ return false;
661
+ },
662
+ async delete(id) {
663
+ await db.delete(devices).where(eq(devices.id, id));
664
+ }
665
+ },
666
+ admin: {
667
+ async findByUserId(userId) {
668
+ const rows = await db.select({ ip: admins.ip }).from(admins).where(eq(admins.userId, userId)).limit(1);
669
+ return rows[0] ?? null;
670
+ }
671
+ }
672
+ };
673
+ }
674
+
134
675
  // src/utilities/config.ts
135
676
  var defaultTokenSettings = {
136
677
  jwtExpiry: 30 * 24 * 60 * 60,
@@ -161,9 +702,16 @@ var defaultFeatures = {
161
702
  otpLogin: true
162
703
  };
163
704
  function createAuthConfig(config) {
705
+ if (!config.database && !config.prisma) {
706
+ throw new Error(
707
+ "@factiii/auth: Provide either a `database` adapter or a `prisma` client in config."
708
+ );
709
+ }
710
+ const database = config.database ?? createPrismaAdapter(config.prisma);
164
711
  const emailService = config.emailService ?? createNoopEmailAdapter();
165
712
  return {
166
713
  ...config,
714
+ database,
167
715
  features: { ...defaultFeatures, ...config.features },
168
716
  tokenSettings: { ...defaultTokenSettings, ...config.tokenSettings },
169
717
  cookieSettings: { ...defaultCookieSettings, ...config.cookieSettings },
@@ -281,6 +829,7 @@ function isTokenInvalidError(error) {
281
829
  function createAuthGuard(config, t) {
282
830
  const storageKeys = config.storageKeys ?? defaultStorageKeys;
283
831
  const cookieSettings = { ...defaultCookieSettings, ...config.cookieSettings };
832
+ const database = config.database ?? createPrismaAdapter(config.prisma);
284
833
  const revokeSession = async (ctx, sessionId, description, errorStack, path) => {
285
834
  clearAuthCookie(ctx.res, cookieSettings, storageKeys);
286
835
  if (config.hooks?.logError) {
@@ -317,15 +866,9 @@ ${errorStack}` : null,
317
866
  }
318
867
  if (sessionId) {
319
868
  try {
320
- await config.prisma.session.update({
321
- where: { id: sessionId },
322
- data: { revokedAt: /* @__PURE__ */ new Date() }
323
- });
869
+ await database.session.revoke(sessionId);
324
870
  if (config.hooks?.onSessionRevoked) {
325
- const session = await config.prisma.session.findUnique({
326
- where: { id: sessionId },
327
- select: { id: true, userId: true, socketId: true }
328
- });
871
+ const session = await database.session.findById(sessionId);
329
872
  if (session) {
330
873
  await config.hooks.onSessionRevoked(session.userId, session.socketId, description);
331
874
  }
@@ -350,23 +893,7 @@ ${errorStack}` : null,
350
893
  secret: config.secrets.jwt,
351
894
  ignoreExpiration: meta?.ignoreExpiration ?? false
352
895
  });
353
- const session = await config.prisma.session.findUnique({
354
- where: {
355
- id: decodedToken.id
356
- },
357
- select: {
358
- userId: true,
359
- user: {
360
- select: {
361
- status: true,
362
- verifiedHumanAt: true
363
- }
364
- },
365
- revokedAt: true,
366
- socketId: true,
367
- id: true
368
- }
369
- });
896
+ const session = await database.session.findById(decodedToken.id);
370
897
  if (!session) {
371
898
  await revokeSession(
372
899
  ctx,
@@ -420,10 +947,7 @@ ${errorStack}` : null,
420
947
  });
421
948
  }
422
949
  if (meta?.adminRequired) {
423
- const admin = await config.prisma.admin.findFirst({
424
- where: { userId: session.userId },
425
- select: { ip: true }
426
- });
950
+ const admin = await database.admin.findByUserId(session.userId);
427
951
  if (!admin || admin.ip !== ctx.ip) {
428
952
  await revokeSession(
429
953
  ctx,
@@ -756,19 +1280,14 @@ var BaseProcedureFactory = class {
756
1280
  if (this.config.hooks?.beforeRegister) {
757
1281
  await this.config.hooks.beforeRegister(typedInput);
758
1282
  }
759
- const usernameCheck = await this.config.prisma.user.findFirst({
760
- where: { username: { equals: username, mode: "insensitive" } }
761
- });
1283
+ const usernameCheck = await this.config.database.user.findByUsernameInsensitive(username);
762
1284
  if (usernameCheck) {
763
1285
  throw new import_server2.TRPCError({
764
1286
  code: "CONFLICT",
765
1287
  message: "An account already exists with that username."
766
1288
  });
767
1289
  }
768
- const emailCheck = await this.config.prisma.user.findFirst({
769
- where: { email: { equals: email, mode: "insensitive" } },
770
- select: { id: true }
771
- });
1290
+ const emailCheck = await this.config.database.user.findByEmailInsensitive(email);
772
1291
  if (emailCheck) {
773
1292
  throw new import_server2.TRPCError({
774
1293
  code: "CONFLICT",
@@ -776,30 +1295,25 @@ var BaseProcedureFactory = class {
776
1295
  });
777
1296
  }
778
1297
  const hashedPassword = await hashPassword(password);
779
- const user = await this.config.prisma.user.create({
780
- data: {
781
- username,
782
- email,
783
- password: hashedPassword,
784
- status: "ACTIVE",
785
- tag: this.config.features.biometric ? "BOT" : "HUMAN",
786
- twoFaEnabled: false,
787
- emailVerificationStatus: "UNVERIFIED",
788
- verifiedHumanAt: null
789
- }
1298
+ const user = await this.config.database.user.create({
1299
+ username,
1300
+ email,
1301
+ password: hashedPassword,
1302
+ status: "ACTIVE",
1303
+ tag: this.config.features.biometric ? "BOT" : "HUMAN",
1304
+ twoFaEnabled: false,
1305
+ emailVerificationStatus: "UNVERIFIED",
1306
+ verifiedHumanAt: null
790
1307
  });
791
1308
  if (this.config.hooks?.onUserCreated) {
792
1309
  await this.config.hooks.onUserCreated(user.id, typedInput);
793
1310
  }
794
1311
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
795
- const session = await this.config.prisma.session.create({
796
- data: {
797
- userId: user.id,
798
- browserName: detectBrowser(userAgent),
799
- socketId: null,
800
- ...extraSessionData
801
- },
802
- select: { id: true, userId: true }
1312
+ const session = await this.config.database.session.create({
1313
+ userId: user.id,
1314
+ browserName: detectBrowser(userAgent),
1315
+ socketId: null,
1316
+ ...extraSessionData
803
1317
  });
804
1318
  if (this.config.hooks?.onSessionCreated) {
805
1319
  await this.config.hooks.onSessionCreated(session.id, typedInput);
@@ -837,24 +1351,7 @@ var BaseProcedureFactory = class {
837
1351
  if (this.config.hooks?.beforeLogin) {
838
1352
  await this.config.hooks.beforeLogin(typedInput);
839
1353
  }
840
- const user = await this.config.prisma.user.findFirst({
841
- where: {
842
- OR: [
843
- { email: { equals: username, mode: "insensitive" } },
844
- { username: { equals: username, mode: "insensitive" } }
845
- ]
846
- },
847
- select: {
848
- id: true,
849
- status: true,
850
- password: true,
851
- twoFaEnabled: true,
852
- email: true,
853
- username: true,
854
- oauthProvider: true,
855
- verifiedHumanAt: true
856
- }
857
- });
1354
+ const user = await this.config.database.user.findByEmailOrUsernameInsensitive(username);
858
1355
  if (!user) {
859
1356
  throw new import_server2.TRPCError({
860
1357
  code: "FORBIDDEN",
@@ -890,14 +1387,12 @@ var BaseProcedureFactory = class {
890
1387
  if (!code) {
891
1388
  return {
892
1389
  success: false,
893
- requires2FA: true
1390
+ requires2FA: true,
1391
+ userId: user.id
894
1392
  };
895
1393
  }
896
1394
  let validCode = false;
897
- const secrets = await this.config.prisma.session.findMany({
898
- where: { userId: user.id, twoFaSecret: { not: null } },
899
- select: { twoFaSecret: true }
900
- });
1395
+ const secrets = await this.config.database.session.findTwoFaSecretsByUserId(user.id);
901
1396
  for (const s of secrets) {
902
1397
  if (s.twoFaSecret && await verifyTotp(code, cleanBase32String(s.twoFaSecret))) {
903
1398
  validCode = true;
@@ -905,14 +1400,13 @@ var BaseProcedureFactory = class {
905
1400
  }
906
1401
  }
907
1402
  if (!validCode) {
908
- const checkOTP = await this.config.prisma.oTP.findFirst({
909
- where: { userId: user.id, code: Number(code), expiresAt: { gte: /* @__PURE__ */ new Date() } }
910
- });
1403
+ const checkOTP = await this.config.database.otp.findValidByUserAndCode(
1404
+ user.id,
1405
+ Number(code)
1406
+ );
911
1407
  if (checkOTP) {
912
1408
  validCode = true;
913
- await this.config.prisma.oTP.delete({
914
- where: { id: checkOTP.id }
915
- });
1409
+ await this.config.database.otp.delete(checkOTP.id);
916
1410
  }
917
1411
  }
918
1412
  if (!validCode) {
@@ -923,24 +1417,11 @@ var BaseProcedureFactory = class {
923
1417
  }
924
1418
  }
925
1419
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
926
- const session = await this.config.prisma.session.create({
927
- data: {
928
- userId: user.id,
929
- browserName: detectBrowser(userAgent),
930
- socketId: null,
931
- ...extraSessionData
932
- },
933
- select: {
934
- id: true,
935
- userId: true,
936
- socketId: true,
937
- browserName: true,
938
- issuedAt: true,
939
- lastUsed: true,
940
- revokedAt: true,
941
- deviceId: true,
942
- twoFaSecret: true
943
- }
1420
+ const session = await this.config.database.session.create({
1421
+ userId: user.id,
1422
+ browserName: detectBrowser(userAgent),
1423
+ socketId: null,
1424
+ ...extraSessionData
944
1425
  });
945
1426
  if (this.config.hooks?.onUserLogin) {
946
1427
  await this.config.hooks.onUserLogin(user.id, session.id);
@@ -971,15 +1452,9 @@ var BaseProcedureFactory = class {
971
1452
  return this.authProcedure.meta({ ignoreExpiration: true }).mutation(async ({ ctx }) => {
972
1453
  const { userId, sessionId } = ctx;
973
1454
  if (sessionId) {
974
- await this.config.prisma.session.update({
975
- where: { id: sessionId },
976
- data: { revokedAt: /* @__PURE__ */ new Date() }
977
- });
1455
+ await this.config.database.session.revoke(sessionId);
978
1456
  if (userId) {
979
- await this.config.prisma.user.update({
980
- where: { id: userId },
981
- data: { isActive: false }
982
- });
1457
+ await this.config.database.user.update(userId, { isActive: false });
983
1458
  }
984
1459
  if (this.config.hooks?.afterLogout) {
985
1460
  await this.config.hooks.afterLogout(userId, sessionId, ctx.socketId);
@@ -991,15 +1466,7 @@ var BaseProcedureFactory = class {
991
1466
  }
992
1467
  refresh() {
993
1468
  return this.authProcedure.query(async ({ ctx }) => {
994
- const session = await this.config.prisma.session.update({
995
- where: { id: ctx.sessionId },
996
- data: { lastUsed: /* @__PURE__ */ new Date() },
997
- select: {
998
- id: true,
999
- userId: true,
1000
- user: { select: { verifiedHumanAt: true } }
1001
- }
1002
- });
1469
+ const session = await this.config.database.session.updateLastUsed(ctx.sessionId);
1003
1470
  if (this.config.hooks?.onRefresh) {
1004
1471
  this.config.hooks.onRefresh(session.userId).catch(() => {
1005
1472
  });
@@ -1024,22 +1491,14 @@ var BaseProcedureFactory = class {
1024
1491
  return this.authProcedure.input(endAllSessionsSchema).mutation(async ({ ctx, input }) => {
1025
1492
  const { skipCurrentSession } = input;
1026
1493
  const { userId, sessionId } = ctx;
1027
- const sessionsToRevoke = await this.config.prisma.session.findMany({
1028
- where: {
1029
- userId,
1030
- revokedAt: null,
1031
- ...skipCurrentSession ? { NOT: { id: sessionId } } : {}
1032
- },
1033
- select: { socketId: true, id: true, userId: true }
1034
- });
1035
- await this.config.prisma.session.updateMany({
1036
- where: {
1037
- userId,
1038
- revokedAt: null,
1039
- ...skipCurrentSession ? { NOT: { id: sessionId } } : {}
1040
- },
1041
- data: { revokedAt: /* @__PURE__ */ new Date() }
1042
- });
1494
+ const sessionsToRevoke = await this.config.database.session.findActiveByUserId(
1495
+ userId,
1496
+ skipCurrentSession ? sessionId : void 0
1497
+ );
1498
+ await this.config.database.session.revokeAllByUserId(
1499
+ userId,
1500
+ skipCurrentSession ? sessionId : void 0
1501
+ );
1043
1502
  for (const session of sessionsToRevoke) {
1044
1503
  if (this.config.hooks?.onSessionRevoked) {
1045
1504
  await this.config.hooks.onSessionRevoked(
@@ -1050,10 +1509,7 @@ var BaseProcedureFactory = class {
1050
1509
  }
1051
1510
  }
1052
1511
  if (!skipCurrentSession) {
1053
- await this.config.prisma.user.update({
1054
- where: { id: userId },
1055
- data: { isActive: false }
1056
- });
1512
+ await this.config.database.user.update(userId, { isActive: false });
1057
1513
  }
1058
1514
  return { success: true, revokedCount: sessionsToRevoke.length };
1059
1515
  });
@@ -1068,10 +1524,7 @@ var BaseProcedureFactory = class {
1068
1524
  message: "New password cannot be the same as current password"
1069
1525
  });
1070
1526
  }
1071
- const user = await this.config.prisma.user.findUnique({
1072
- where: { id: userId },
1073
- select: { password: true }
1074
- });
1527
+ const user = await this.config.database.user.findById(userId);
1075
1528
  if (!user) {
1076
1529
  throw new import_server2.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1077
1530
  }
@@ -1089,14 +1542,8 @@ var BaseProcedureFactory = class {
1089
1542
  });
1090
1543
  }
1091
1544
  const hashedPassword = await hashPassword(newPassword);
1092
- await this.config.prisma.user.update({
1093
- where: { id: userId },
1094
- data: { password: hashedPassword }
1095
- });
1096
- await this.config.prisma.session.updateMany({
1097
- where: { userId, revokedAt: null, NOT: { id: sessionId } },
1098
- data: { revokedAt: /* @__PURE__ */ new Date() }
1099
- });
1545
+ await this.config.database.user.update(userId, { password: hashedPassword });
1546
+ await this.config.database.session.revokeAllByUserId(userId, sessionId);
1100
1547
  if (this.config.hooks?.onPasswordChanged) {
1101
1548
  await this.config.hooks.onPasswordChanged(userId);
1102
1549
  }
@@ -1109,11 +1556,8 @@ var BaseProcedureFactory = class {
1109
1556
  sendPasswordResetEmail() {
1110
1557
  return this.procedure.input(requestPasswordResetSchema).mutation(async ({ input }) => {
1111
1558
  const { email } = input;
1112
- const user = await this.config.prisma.user.findFirst({
1113
- where: { email: { equals: email, mode: "insensitive" }, status: "ACTIVE" },
1114
- select: { id: true, password: true, email: true }
1115
- });
1116
- if (!user) {
1559
+ const user = await this.config.database.user.findByEmailInsensitive(email);
1560
+ if (!user || user.status !== "ACTIVE") {
1117
1561
  return { message: "If an account exists with that email, a reset link has been sent." };
1118
1562
  }
1119
1563
  if (!user.password) {
@@ -1122,10 +1566,8 @@ var BaseProcedureFactory = class {
1122
1566
  message: "This account uses social login. Please use that method."
1123
1567
  });
1124
1568
  }
1125
- await this.config.prisma.passwordReset.deleteMany({ where: { userId: user.id } });
1126
- const passwordReset = await this.config.prisma.passwordReset.create({
1127
- data: { userId: user.id }
1128
- });
1569
+ await this.config.database.passwordReset.deleteAllByUserId(user.id);
1570
+ const passwordReset = await this.config.database.passwordReset.create(user.id);
1129
1571
  if (this.config.emailService) {
1130
1572
  await this.config.emailService.sendPasswordResetEmail(user.email, String(passwordReset.id));
1131
1573
  }
@@ -1135,15 +1577,12 @@ var BaseProcedureFactory = class {
1135
1577
  checkPasswordReset() {
1136
1578
  return this.procedure.input(checkPasswordResetSchema).query(async ({ input }) => {
1137
1579
  const { token } = input;
1138
- const passwordReset = await this.config.prisma.passwordReset.findUnique({
1139
- where: { id: token },
1140
- select: { id: true, createdAt: true, userId: true }
1141
- });
1580
+ const passwordReset = await this.config.database.passwordReset.findById(token);
1142
1581
  if (!passwordReset) {
1143
1582
  throw new import_server2.TRPCError({ code: "NOT_FOUND", message: "Invalid reset token." });
1144
1583
  }
1145
1584
  if (passwordReset.createdAt.getTime() + this.config.tokenSettings.passwordResetExpiryMs < Date.now()) {
1146
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1585
+ await this.config.database.passwordReset.delete(token);
1147
1586
  throw new import_server2.TRPCError({ code: "FORBIDDEN", message: "Reset token expired." });
1148
1587
  }
1149
1588
  return { valid: true };
@@ -1152,31 +1591,23 @@ var BaseProcedureFactory = class {
1152
1591
  resetPassword() {
1153
1592
  return this.procedure.input(resetPasswordSchema).mutation(async ({ input }) => {
1154
1593
  const { token, password } = input;
1155
- const passwordReset = await this.config.prisma.passwordReset.findFirst({
1156
- where: { id: token },
1157
- select: { id: true, createdAt: true, userId: true }
1158
- });
1594
+ const passwordReset = await this.config.database.passwordReset.findById(token);
1159
1595
  if (!passwordReset) {
1160
1596
  throw new import_server2.TRPCError({ code: "NOT_FOUND", message: "Invalid reset token." });
1161
1597
  }
1162
1598
  if (passwordReset.createdAt.getTime() + this.config.tokenSettings.passwordResetExpiryMs < Date.now()) {
1163
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1599
+ await this.config.database.passwordReset.delete(token);
1164
1600
  throw new import_server2.TRPCError({ code: "FORBIDDEN", message: "Reset token expired." });
1165
1601
  }
1166
1602
  const hashedPassword = await hashPassword(password);
1167
- await this.config.prisma.user.update({
1168
- where: { id: passwordReset.userId },
1169
- data: { password: hashedPassword }
1170
- });
1171
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1172
- const sessionsToRevoke = await this.config.prisma.session.findMany({
1173
- where: { userId: passwordReset.userId, revokedAt: null },
1174
- select: { id: true, socketId: true, userId: true }
1175
- });
1176
- await this.config.prisma.session.updateMany({
1177
- where: { userId: passwordReset.userId, revokedAt: null },
1178
- data: { revokedAt: /* @__PURE__ */ new Date() }
1603
+ await this.config.database.user.update(passwordReset.userId, {
1604
+ password: hashedPassword
1179
1605
  });
1606
+ await this.config.database.passwordReset.delete(token);
1607
+ const sessionsToRevoke = await this.config.database.session.findActiveByUserId(
1608
+ passwordReset.userId
1609
+ );
1610
+ await this.config.database.session.revokeAllByUserId(passwordReset.userId);
1180
1611
  for (const session of sessionsToRevoke) {
1181
1612
  if (this.config.hooks?.onSessionRevoked) {
1182
1613
  await this.config.hooks.onSessionRevoked(
@@ -1213,9 +1644,9 @@ var BiometricProcedureFactory = class {
1213
1644
  return this.authProcedure.input(biometricVerifySchema).mutation(async ({ ctx }) => {
1214
1645
  this.checkConfig();
1215
1646
  const { userId } = ctx;
1216
- await this.config.prisma.user.update({
1217
- where: { id: userId },
1218
- data: { verifiedHumanAt: /* @__PURE__ */ new Date(), tag: "HUMAN" }
1647
+ await this.config.database.user.update(userId, {
1648
+ verifiedHumanAt: /* @__PURE__ */ new Date(),
1649
+ tag: "HUMAN"
1219
1650
  });
1220
1651
  if (this.config.hooks?.onBiometricVerified) {
1221
1652
  await this.config.hooks.onBiometricVerified(userId);
@@ -1227,10 +1658,7 @@ var BiometricProcedureFactory = class {
1227
1658
  return this.authProcedure.query(async ({ ctx }) => {
1228
1659
  this.checkConfig();
1229
1660
  const { userId } = ctx;
1230
- const user = await this.config.prisma.user.findUnique({
1231
- where: { id: userId },
1232
- select: { verifiedHumanAt: true }
1233
- });
1661
+ const user = await this.config.database.user.findById(userId);
1234
1662
  if (!user) {
1235
1663
  throw new import_server3.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1236
1664
  }
@@ -1277,10 +1705,7 @@ var EmailVerificationProcedureFactory = class {
1277
1705
  return this.authProcedure.mutation(async ({ ctx }) => {
1278
1706
  this.checkConfig();
1279
1707
  const { userId } = ctx;
1280
- const user = await this.config.prisma.user.findUnique({
1281
- where: { id: userId, status: "ACTIVE" },
1282
- select: { id: true, email: true, emailVerificationStatus: true }
1283
- });
1708
+ const user = await this.config.database.user.findActiveById(userId);
1284
1709
  if (!user) {
1285
1710
  throw new import_server4.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1286
1711
  }
@@ -1288,9 +1713,9 @@ var EmailVerificationProcedureFactory = class {
1288
1713
  return { message: "Email is already verified", emailSent: false };
1289
1714
  }
1290
1715
  const otp = (0, import_node_crypto.randomUUID)();
1291
- await this.config.prisma.user.update({
1292
- where: { id: userId },
1293
- data: { emailVerificationStatus: "PENDING", otpForEmailVerification: otp }
1716
+ await this.config.database.user.update(userId, {
1717
+ emailVerificationStatus: "PENDING",
1718
+ otpForEmailVerification: otp
1294
1719
  });
1295
1720
  if (this.config.emailService) {
1296
1721
  try {
@@ -1308,10 +1733,7 @@ var EmailVerificationProcedureFactory = class {
1308
1733
  this.checkConfig();
1309
1734
  const { userId } = ctx;
1310
1735
  const { code } = input;
1311
- const user = await this.config.prisma.user.findUnique({
1312
- where: { id: userId, status: "ACTIVE" },
1313
- select: { id: true, emailVerificationStatus: true, otpForEmailVerification: true }
1314
- });
1736
+ const user = await this.config.database.user.findActiveById(userId);
1315
1737
  if (!user) {
1316
1738
  throw new import_server4.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1317
1739
  }
@@ -1321,9 +1743,9 @@ var EmailVerificationProcedureFactory = class {
1321
1743
  if (code !== user.otpForEmailVerification) {
1322
1744
  throw new import_server4.TRPCError({ code: "BAD_REQUEST", message: "Invalid verification code" });
1323
1745
  }
1324
- await this.config.prisma.user.update({
1325
- where: { id: userId },
1326
- data: { emailVerificationStatus: "VERIFIED", otpForEmailVerification: null }
1746
+ await this.config.database.user.update(userId, {
1747
+ emailVerificationStatus: "VERIFIED",
1748
+ otpForEmailVerification: null
1327
1749
  });
1328
1750
  if (this.config.hooks?.onEmailVerified) {
1329
1751
  await this.config.hooks.onEmailVerified(userId);
@@ -1335,10 +1757,7 @@ var EmailVerificationProcedureFactory = class {
1335
1757
  return this.authProcedure.query(async ({ ctx }) => {
1336
1758
  this.checkConfig();
1337
1759
  const { userId } = ctx;
1338
- const user = await this.config.prisma.user.findUnique({
1339
- where: { id: userId },
1340
- select: { emailVerificationStatus: true, email: true }
1341
- });
1760
+ const user = await this.config.database.user.findById(userId);
1342
1761
  if (!user) {
1343
1762
  throw new import_server4.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1344
1763
  }
@@ -1392,23 +1811,7 @@ var OAuthLoginProcedureFactory = class {
1392
1811
  message: "Email not provided by OAuth provider"
1393
1812
  });
1394
1813
  }
1395
- let user = await this.config.prisma.user.findFirst({
1396
- where: {
1397
- OR: [{ email: { equals: email, mode: "insensitive" } }, { oauthId: { equals: oauthId } }]
1398
- },
1399
- select: {
1400
- id: true,
1401
- status: true,
1402
- email: true,
1403
- username: true,
1404
- password: true,
1405
- oauthProvider: true,
1406
- oauthId: true,
1407
- twoFaEnabled: true,
1408
- verifiedHumanAt: true,
1409
- emailVerificationStatus: true
1410
- }
1411
- });
1814
+ let user = await this.config.database.user.findByEmailOrOAuthId(email, oauthId);
1412
1815
  if (user?.oauthProvider && user.oauthProvider !== provider) {
1413
1816
  throw new import_server5.TRPCError({
1414
1817
  code: "BAD_REQUEST",
@@ -1423,19 +1826,17 @@ var OAuthLoginProcedureFactory = class {
1423
1826
  }
1424
1827
  if (!user) {
1425
1828
  const generateUsername = this.config.generateUsername ?? (() => `user_${Date.now()}`);
1426
- user = await this.config.prisma.user.create({
1427
- data: {
1428
- username: generateUsername(),
1429
- email,
1430
- password: null,
1431
- emailVerificationStatus: "VERIFIED",
1432
- oauthProvider: provider,
1433
- oauthId,
1434
- status: "ACTIVE",
1435
- tag: this.config.features.biometric ? "BOT" : "HUMAN",
1436
- twoFaEnabled: false,
1437
- verifiedHumanAt: null
1438
- }
1829
+ user = await this.config.database.user.create({
1830
+ username: generateUsername(),
1831
+ email,
1832
+ password: null,
1833
+ emailVerificationStatus: "VERIFIED",
1834
+ oauthProvider: provider,
1835
+ oauthId,
1836
+ status: "ACTIVE",
1837
+ tag: this.config.features.biometric ? "BOT" : "HUMAN",
1838
+ twoFaEnabled: false,
1839
+ verifiedHumanAt: null
1439
1840
  });
1440
1841
  if (this.config.hooks?.onUserCreated) {
1441
1842
  await this.config.hooks.onUserCreated(user.id, typedInput);
@@ -1451,24 +1852,11 @@ var OAuthLoginProcedureFactory = class {
1451
1852
  throw new import_server5.TRPCError({ code: "FORBIDDEN", message: "Your account has been banned." });
1452
1853
  }
1453
1854
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
1454
- const session = await this.config.prisma.session.create({
1455
- data: {
1456
- userId: user.id,
1457
- browserName: detectBrowser(userAgent),
1458
- socketId: null,
1459
- ...extraSessionData
1460
- },
1461
- select: {
1462
- id: true,
1463
- userId: true,
1464
- socketId: true,
1465
- browserName: true,
1466
- issuedAt: true,
1467
- lastUsed: true,
1468
- revokedAt: true,
1469
- deviceId: true,
1470
- twoFaSecret: true
1471
- }
1855
+ const session = await this.config.database.session.create({
1856
+ userId: user.id,
1857
+ browserName: detectBrowser(userAgent),
1858
+ socketId: null,
1859
+ ...extraSessionData
1472
1860
  });
1473
1861
  if (this.config.hooks?.onUserLogin) {
1474
1862
  await this.config.hooks.onUserLogin(user.id, session.id);
@@ -1525,10 +1913,7 @@ var TwoFaProcedureFactory = class {
1525
1913
  return this.authProcedure.mutation(async ({ ctx }) => {
1526
1914
  this.checkConfig();
1527
1915
  const { userId, sessionId } = ctx;
1528
- const user = await this.config.prisma.user.findFirst({
1529
- where: { id: userId },
1530
- select: { twoFaEnabled: true, oauthProvider: true, password: true }
1531
- });
1916
+ const user = await this.config.database.user.findById(userId);
1532
1917
  if (!user) {
1533
1918
  throw new import_server6.TRPCError({ code: "NOT_FOUND", message: "User not found." });
1534
1919
  }
@@ -1542,10 +1927,7 @@ var TwoFaProcedureFactory = class {
1542
1927
  throw new import_server6.TRPCError({ code: "BAD_REQUEST", message: "2FA already enabled." });
1543
1928
  }
1544
1929
  if (this.config.features.twoFaRequiresDevice !== false) {
1545
- const checkSession = await this.config.prisma.session.findFirst({
1546
- where: { userId, id: sessionId },
1547
- select: { deviceId: true }
1548
- });
1930
+ const checkSession = await this.config.database.session.findById(sessionId);
1549
1931
  if (!checkSession?.deviceId) {
1550
1932
  throw new import_server6.TRPCError({
1551
1933
  code: "BAD_REQUEST",
@@ -1553,23 +1935,11 @@ var TwoFaProcedureFactory = class {
1553
1935
  });
1554
1936
  }
1555
1937
  }
1556
- await this.config.prisma.session.updateMany({
1557
- where: { userId, revokedAt: null, NOT: { id: sessionId } },
1558
- data: { revokedAt: /* @__PURE__ */ new Date() }
1559
- });
1560
- await this.config.prisma.session.updateMany({
1561
- where: { userId, NOT: { id: sessionId } },
1562
- data: { twoFaSecret: null }
1563
- });
1938
+ await this.config.database.session.revokeAllByUserId(userId, sessionId);
1939
+ await this.config.database.session.clearTwoFaSecrets(userId, sessionId);
1564
1940
  const secret = generateTotpSecret();
1565
- await this.config.prisma.user.update({
1566
- where: { id: userId },
1567
- data: { twoFaEnabled: true }
1568
- });
1569
- await this.config.prisma.session.update({
1570
- where: { id: sessionId },
1571
- data: { twoFaSecret: secret }
1572
- });
1941
+ await this.config.database.user.update(userId, { twoFaEnabled: true });
1942
+ await this.config.database.session.update(sessionId, { twoFaSecret: secret });
1573
1943
  if (this.config.hooks?.onTwoFaStatusChanged) {
1574
1944
  await this.config.hooks.onTwoFaStatusChanged(userId, true);
1575
1945
  }
@@ -1581,10 +1951,7 @@ var TwoFaProcedureFactory = class {
1581
1951
  this.checkConfig();
1582
1952
  const { userId, sessionId } = ctx;
1583
1953
  const { password } = input;
1584
- const user = await this.config.prisma.user.findFirst({
1585
- where: { id: userId },
1586
- select: { password: true, status: true, oauthProvider: true }
1587
- });
1954
+ const user = await this.config.database.user.findById(userId);
1588
1955
  if (!user) {
1589
1956
  throw new import_server6.TRPCError({ code: "NOT_FOUND", message: "User not found." });
1590
1957
  }
@@ -1607,14 +1974,8 @@ var TwoFaProcedureFactory = class {
1607
1974
  if (!isMatch) {
1608
1975
  throw new import_server6.TRPCError({ code: "FORBIDDEN", message: "Incorrect password." });
1609
1976
  }
1610
- await this.config.prisma.user.update({
1611
- where: { id: userId },
1612
- data: { twoFaEnabled: false }
1613
- });
1614
- await this.config.prisma.session.update({
1615
- where: { id: sessionId },
1616
- data: { twoFaSecret: null }
1617
- });
1977
+ await this.config.database.user.update(userId, { twoFaEnabled: false });
1978
+ await this.config.database.session.update(sessionId, { twoFaSecret: null });
1618
1979
  if (this.config.hooks?.onTwoFaStatusChanged) {
1619
1980
  await this.config.hooks.onTwoFaStatusChanged(userId, false);
1620
1981
  }
@@ -1626,10 +1987,7 @@ var TwoFaProcedureFactory = class {
1626
1987
  this.checkConfig();
1627
1988
  const { userId, sessionId } = ctx;
1628
1989
  const { pushCode } = input;
1629
- const user = await this.config.prisma.user.findFirst({
1630
- where: { id: userId },
1631
- select: { twoFaEnabled: true, oauthProvider: true }
1632
- });
1990
+ const user = await this.config.database.user.findById(userId);
1633
1991
  if (user?.oauthProvider) {
1634
1992
  throw new import_server6.TRPCError({
1635
1993
  code: "FORBIDDEN",
@@ -1639,10 +1997,7 @@ var TwoFaProcedureFactory = class {
1639
1997
  if (!user?.twoFaEnabled) {
1640
1998
  throw new import_server6.TRPCError({ code: "BAD_REQUEST", message: "2FA not enabled." });
1641
1999
  }
1642
- const session = await this.config.prisma.session.findUnique({
1643
- where: { id: sessionId, userId },
1644
- select: { twoFaSecret: true, device: { select: { pushToken: true } } }
1645
- });
2000
+ const session = await this.config.database.session.findByIdWithDevice(sessionId, userId);
1646
2001
  if (!session?.device) {
1647
2002
  throw new import_server6.TRPCError({ code: "BAD_REQUEST", message: "Invalid request" });
1648
2003
  }
@@ -1654,10 +2009,7 @@ var TwoFaProcedureFactory = class {
1654
2009
  return { secret: session.twoFaSecret };
1655
2010
  }
1656
2011
  const secret = generateTotpSecret();
1657
- await this.config.prisma.session.update({
1658
- where: { id: sessionId },
1659
- data: { twoFaSecret: secret }
1660
- });
2012
+ await this.config.database.session.update(sessionId, { twoFaSecret: secret });
1661
2013
  return { secret };
1662
2014
  });
1663
2015
  }
@@ -1665,11 +2017,8 @@ var TwoFaProcedureFactory = class {
1665
2017
  return this.procedure.input(twoFaResetSchema).mutation(async ({ input }) => {
1666
2018
  this.checkConfig();
1667
2019
  const { username, password } = input;
1668
- const user = await this.config.prisma.user.findFirst({
1669
- where: { username: { equals: username, mode: "insensitive" }, twoFaEnabled: true },
1670
- select: { id: true, password: true, email: true }
1671
- });
1672
- if (!user) {
2020
+ const user = await this.config.database.user.findByUsernameInsensitive(username);
2021
+ if (!user || !user.twoFaEnabled) {
1673
2022
  throw new import_server6.TRPCError({ code: "UNAUTHORIZED", message: "Invalid credentials." });
1674
2023
  }
1675
2024
  if (!user.password) {
@@ -1684,9 +2033,7 @@ var TwoFaProcedureFactory = class {
1684
2033
  }
1685
2034
  const otp = generateOtp();
1686
2035
  const expiresAt = new Date(Date.now() + this.config.tokenSettings.otpValidityMs);
1687
- await this.config.prisma.oTP.create({
1688
- data: { userId: user.id, code: otp, expiresAt }
1689
- });
2036
+ await this.config.database.otp.create({ userId: user.id, code: otp, expiresAt });
1690
2037
  if (this.config.emailService) {
1691
2038
  await this.config.emailService.sendOTPEmail(user.email, otp);
1692
2039
  }
@@ -1697,30 +2044,17 @@ var TwoFaProcedureFactory = class {
1697
2044
  return this.procedure.input(twoFaResetVerifySchema).mutation(async ({ input }) => {
1698
2045
  this.checkConfig();
1699
2046
  const { code, username } = input;
1700
- const user = await this.config.prisma.user.findFirst({
1701
- where: { username: { equals: username, mode: "insensitive" } },
1702
- select: { id: true }
1703
- });
2047
+ const user = await this.config.database.user.findByUsernameInsensitive(username);
1704
2048
  if (!user) {
1705
2049
  throw new import_server6.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1706
2050
  }
1707
- const otp = await this.config.prisma.oTP.findFirst({
1708
- where: { userId: user.id, code, expiresAt: { gte: /* @__PURE__ */ new Date() } }
1709
- });
2051
+ const otp = await this.config.database.otp.findValidByUserAndCode(user.id, code);
1710
2052
  if (!otp) {
1711
2053
  throw new import_server6.TRPCError({ code: "FORBIDDEN", message: "Invalid or expired OTP" });
1712
2054
  }
1713
- await this.config.prisma.oTP.delete({
1714
- where: { id: otp.id }
1715
- });
1716
- await this.config.prisma.user.update({
1717
- where: { id: user.id },
1718
- data: { twoFaEnabled: false }
1719
- });
1720
- await this.config.prisma.session.updateMany({
1721
- where: { userId: user.id },
1722
- data: { twoFaSecret: null }
1723
- });
2055
+ await this.config.database.otp.delete(otp.id);
2056
+ await this.config.database.user.update(user.id, { twoFaEnabled: false });
2057
+ await this.config.database.session.clearTwoFaSecrets(user.id);
1724
2058
  return { success: true, message: "2FA has been reset." };
1725
2059
  });
1726
2060
  }
@@ -1729,36 +2063,14 @@ var TwoFaProcedureFactory = class {
1729
2063
  this.checkConfig();
1730
2064
  const { userId, sessionId } = ctx;
1731
2065
  const { pushToken } = input;
1732
- await this.config.prisma.session.updateMany({
1733
- where: {
1734
- userId,
1735
- id: { not: sessionId },
1736
- revokedAt: null,
1737
- device: { pushToken }
1738
- },
1739
- data: { revokedAt: /* @__PURE__ */ new Date() }
1740
- });
1741
- const checkDevice = await this.config.prisma.device.findFirst({
1742
- where: {
1743
- pushToken,
1744
- sessions: { some: { id: sessionId } },
1745
- users: { some: { id: userId } }
1746
- },
1747
- select: { id: true }
1748
- });
2066
+ await this.config.database.session.revokeByDevicePushToken(userId, pushToken, sessionId);
2067
+ const checkDevice = await this.config.database.device.findByTokenSessionAndUser(
2068
+ pushToken,
2069
+ sessionId,
2070
+ userId
2071
+ );
1749
2072
  if (!checkDevice) {
1750
- await this.config.prisma.device.upsert({
1751
- where: { pushToken },
1752
- create: {
1753
- pushToken,
1754
- sessions: { connect: { id: sessionId } },
1755
- users: { connect: { id: userId } }
1756
- },
1757
- update: {
1758
- sessions: { connect: { id: sessionId } },
1759
- users: { connect: { id: userId } }
1760
- }
1761
- });
2073
+ await this.config.database.device.upsertByPushToken(pushToken, sessionId, userId);
1762
2074
  }
1763
2075
  return { registered: true };
1764
2076
  });
@@ -1768,30 +2080,13 @@ var TwoFaProcedureFactory = class {
1768
2080
  this.checkConfig();
1769
2081
  const { userId } = ctx;
1770
2082
  const { pushToken } = input;
1771
- const device = await this.config.prisma.device.findFirst({
1772
- where: {
1773
- users: { some: { id: userId } },
1774
- pushToken
1775
- },
1776
- select: { id: true }
1777
- });
2083
+ const device = await this.config.database.device.findByUserAndToken(userId, pushToken);
1778
2084
  if (device) {
1779
- await this.config.prisma.session.updateMany({
1780
- where: { userId, deviceId: device.id },
1781
- data: { deviceId: null }
1782
- });
1783
- await this.config.prisma.device.update({
1784
- where: { id: device.id },
1785
- data: { users: { disconnect: { id: userId } } }
1786
- });
1787
- const remainingUsers = await this.config.prisma.device.findUnique({
1788
- where: { id: device.id },
1789
- select: { users: { select: { id: true }, take: 1 } }
1790
- });
1791
- if (!remainingUsers?.users.length) {
1792
- await this.config.prisma.device.delete({
1793
- where: { id: device.id }
1794
- });
2085
+ await this.config.database.session.clearDeviceId(userId, device.id);
2086
+ await this.config.database.device.disconnectUser(device.id, userId);
2087
+ const hasUsers = await this.config.database.device.hasRemainingUsers(device.id);
2088
+ if (!hasUsers) {
2089
+ await this.config.database.device.delete(device.id);
1795
2090
  }
1796
2091
  }
1797
2092
  return { deregistered: true };
@@ -1949,8 +2244,10 @@ function createAuthRouter(config) {
1949
2244
  createAuthRouter,
1950
2245
  createAuthToken,
1951
2246
  createConsoleEmailAdapter,
2247
+ createDrizzleAdapter,
1952
2248
  createNoopEmailAdapter,
1953
2249
  createOAuthVerifier,
2250
+ createPrismaAdapter,
1954
2251
  decodeToken,
1955
2252
  defaultAuthConfig,
1956
2253
  defaultCookieSettings,