fork
Configure Feed
Select the types of activity you want to include in your feed.
A social knowledge tool for researchers built on ATProto
fork
Configure Feed
Select the types of activity you want to include in your feed.
1import jwt from 'jsonwebtoken';
2import { v4 as uuidv4 } from 'uuid';
3import { Result, ok, err } from 'src/shared/core/Result';
4import { ITokenService } from '../../application/services/ITokenService';
5import { ITokenRepository } from '../../domain/repositories/ITokenRepository';
6import { TokenPair } from '../../application/dtos/TokenDTO';
7
8export class FakeJwtTokenService implements ITokenService {
9 private jwtSecret: string;
10 private accessTokenExpiresIn: number = 3600; // 1 hour
11 private refreshTokenExpiresIn: number = 2592000; // 30 days
12
13 constructor(private tokenRepository: ITokenRepository) {
14 this.jwtSecret = process.env.MOCK_ACCESS_TOKEN || 'mock-access-token-123';
15 }
16
17 async generateToken(did: string): Promise<Result<TokenPair>> {
18 try {
19 // Generate actual JWT access token
20 const accessToken = jwt.sign(
21 { did, iat: Math.floor(Date.now() / 1000) },
22 this.jwtSecret,
23 { expiresIn: this.accessTokenExpiresIn },
24 );
25
26 // Generate refresh token
27 const refreshToken = uuidv4();
28 const tokenId = uuidv4();
29 const now = new Date();
30 const expiresAt = new Date(
31 now.getTime() + this.refreshTokenExpiresIn * 1000,
32 );
33
34 // Store refresh token
35 const saveResult = await this.tokenRepository.saveRefreshToken({
36 tokenId,
37 userDid: did,
38 refreshToken,
39 issuedAt: now,
40 expiresAt,
41 revoked: false,
42 });
43
44 if (saveResult.isErr()) {
45 return err(saveResult.error);
46 }
47
48 return ok({
49 accessToken,
50 refreshToken,
51 expiresIn: this.accessTokenExpiresIn,
52 });
53 } catch (error: any) {
54 return err(error);
55 }
56 }
57
58 async validateToken(token: string): Promise<Result<string | null>> {
59 try {
60 const decoded = jwt.verify(token, this.jwtSecret) as { did: string };
61 return ok(decoded.did);
62 } catch (error) {
63 return ok(null); // Token is invalid or expired
64 }
65 }
66
67 async refreshToken(refreshToken: string): Promise<Result<TokenPair | null>> {
68 try {
69 // Find the refresh token
70 const findResult =
71 await this.tokenRepository.findRefreshToken(refreshToken);
72
73 if (findResult.isErr()) {
74 return err(findResult.error);
75 }
76
77 const tokenData = findResult.unwrap();
78 if (!tokenData) {
79 return ok(null);
80 }
81
82 // Check if token is expired
83 if (new Date() > tokenData.expiresAt) {
84 await this.revokeToken(refreshToken);
85 return ok(null);
86 }
87
88 // Generate new tokens
89 const newTokens = await this.generateToken(tokenData.userDid);
90
91 // Revoke old token
92 await this.revokeToken(refreshToken);
93
94 return newTokens;
95 } catch (error: any) {
96 return err(error);
97 }
98 }
99
100 async revokeToken(refreshToken: string): Promise<Result<void>> {
101 try {
102 const revokeResult =
103 await this.tokenRepository.revokeRefreshToken(refreshToken);
104
105 if (revokeResult.isErr()) {
106 return err(revokeResult.error);
107 }
108
109 return ok(undefined);
110 } catch (error: any) {
111 return err(error);
112 }
113 }
114}