This repository has no description
3.8 kB
121 lines
1import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
2import { eq, and } from 'drizzle-orm';
3import { Result, err, ok } from 'src/shared/core/Result';
4import {
5 ITokenRepository,
6 RefreshToken,
7} from '../../domain/repositories/ITokenRepository';
8import { authRefreshTokens } from './schema/authToken.sql';
9
10export class DrizzleTokenRepository implements ITokenRepository {
11 constructor(private db: PostgresJsDatabase) {}
12
13 async saveRefreshToken(token: RefreshToken): Promise<Result<void>> {
14 try {
15 const tokenPreview = '...' + token.refreshToken.slice(-8);
16 console.log(
17 `[DrizzleTokenRepository] Saving new refresh token: ${tokenPreview} for user: ${token.userDid}, expiresAt: ${token.expiresAt.toISOString()}`,
18 );
19
20 await this.db.insert(authRefreshTokens).values({
21 tokenId: token.tokenId,
22 userDid: token.userDid,
23 refreshToken: token.refreshToken,
24 issuedAt: token.issuedAt,
25 expiresAt: token.expiresAt,
26 revoked: token.revoked,
27 });
28
29 console.log(
30 `[DrizzleTokenRepository] Successfully saved refresh token: ${tokenPreview}`,
31 );
32 return ok(undefined);
33 } catch (error: any) {
34 console.log(
35 `[DrizzleTokenRepository] Failed to save refresh token: ${error.message}`,
36 );
37 return err(error);
38 }
39 }
40
41 async findRefreshToken(
42 refreshToken: string,
43 ): Promise<Result<RefreshToken | null>> {
44 try {
45 const tokenPreview = '...' + refreshToken.slice(-8);
46 console.log(
47 `[DrizzleTokenRepository] Searching for token: ${tokenPreview}`,
48 );
49
50 const result = await this.db
51 .select()
52 .from(authRefreshTokens)
53 .where(
54 and(
55 eq(authRefreshTokens.refreshToken, refreshToken),
56 eq(authRefreshTokens.revoked, false),
57 ),
58 )
59 .limit(1);
60
61 console.log(
62 `[DrizzleTokenRepository] Query returned ${result.length} results`,
63 );
64
65 if (result.length === 0) {
66 // Check if token exists but is revoked
67 const revokedResult = await this.db
68 .select()
69 .from(authRefreshTokens)
70 .where(eq(authRefreshTokens.refreshToken, refreshToken))
71 .limit(1);
72
73 if (revokedResult.length > 0) {
74 console.log(
75 `[DrizzleTokenRepository] Token exists but is revoked: ${tokenPreview}`,
76 );
77 } else {
78 console.log(
79 `[DrizzleTokenRepository] Token does not exist in database: ${tokenPreview}`,
80 );
81 }
82
83 return ok(null);
84 }
85
86 const token = result[0]!;
87 console.log(
88 `[DrizzleTokenRepository] Token found - userDid: ${token.userDid}, revoked: ${token.revoked}, expiresAt: ${token.expiresAt.toISOString()}`,
89 );
90
91 return ok({ ...token, revoked: token.revoked === true });
92 } catch (error: any) {
93 console.log(`[DrizzleTokenRepository] Database error: ${error.message}`);
94 return err(error);
95 }
96 }
97
98 async revokeRefreshToken(refreshToken: string): Promise<Result<void>> {
99 try {
100 const tokenPreview = '...' + refreshToken.slice(-8);
101 console.log(
102 `[DrizzleTokenRepository] Revoking refresh token: ${tokenPreview}`,
103 );
104
105 const result = await this.db
106 .update(authRefreshTokens)
107 .set({ revoked: true })
108 .where(eq(authRefreshTokens.refreshToken, refreshToken));
109
110 console.log(
111 `[DrizzleTokenRepository] Successfully revoked refresh token: ${tokenPreview}`,
112 );
113 return ok(undefined);
114 } catch (error: any) {
115 console.log(
116 `[DrizzleTokenRepository] Failed to revoke refresh token: ${error.message}`,
117 );
118 return err(error);
119 }
120 }
121}