Skip to content

Commit bc80aed

Browse files
authored
Merge pull request #354 from boostcampwm2023/BE-feature/refresh-tokens
Refresh Token 모듈 분리
2 parents d782176 + 9b114e8 commit bc80aed

10 files changed

+137
-151
lines changed

nestjs-BE/server/src/auth/auth.controller.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { AuthController } from './auth.controller';
33
import { RefreshToken, User } from '@prisma/client';
44
import { AuthService } from './auth.service';
55
import { UsersService } from '../users/users.service';
6-
import { RefreshTokensService } from './refresh-tokens.service';
6+
import { RefreshTokensService } from '../refresh-tokens/refresh-tokens.service';
77
import { ProfilesService } from '../profiles/profiles.service';
88
import { BadRequestException, NotFoundException } from '@nestjs/common';
99
import { ConfigModule } from '@nestjs/config';

nestjs-BE/server/src/auth/auth.controller.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { UsersService } from '../users/users.service';
1212
import { RefreshTokenDto } from './dto/refresh-token.dto';
1313
import { ProfilesService } from '../profiles/profiles.service';
1414
import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger';
15-
import { RefreshTokensService } from './refresh-tokens.service';
15+
import { RefreshTokensService } from '../refresh-tokens/refresh-tokens.service';
1616
import { ConfigService } from '@nestjs/config';
1717

1818
@Controller('auth')

nestjs-BE/server/src/auth/auth.module.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,21 @@ import { JwtStrategy } from './jwt.strategy';
88
import { APP_GUARD } from '@nestjs/core';
99
import { JwtAuthGuard } from './jwt-auth.guard';
1010
import { ProfilesModule } from '../profiles/profiles.module';
11-
import { RefreshTokensService } from './refresh-tokens.service';
11+
import { RefreshTokensModule } from '../refresh-tokens/refresh-tokens.module';
1212

1313
@Module({
14-
imports: [UsersModule, PassportModule, JwtModule, ProfilesModule],
14+
imports: [
15+
UsersModule,
16+
PassportModule,
17+
JwtModule,
18+
ProfilesModule,
19+
RefreshTokensModule,
20+
],
1521
controllers: [AuthController],
1622
providers: [
1723
AuthService,
1824
JwtStrategy,
1925
{ provide: APP_GUARD, useClass: JwtAuthGuard },
20-
RefreshTokensService,
2126
],
2227
exports: [AuthService],
2328
})

nestjs-BE/server/src/auth/auth.service.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing';
22
import { AuthService } from './auth.service';
33
import { RefreshToken } from '@prisma/client';
44
import { JwtModule, JwtService } from '@nestjs/jwt';
5-
import { RefreshTokensService } from './refresh-tokens.service';
5+
import { RefreshTokensService } from '../refresh-tokens/refresh-tokens.service';
66
import { ConfigModule } from '@nestjs/config';
77

88
const fetchSpy = jest.spyOn(global, 'fetch');

nestjs-BE/server/src/auth/auth.service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Injectable, UnauthorizedException } from '@nestjs/common';
22
import { JwtService } from '@nestjs/jwt';
33
import { stringify } from 'qs';
4-
import { RefreshTokensService } from './refresh-tokens.service';
4+
import { RefreshTokensService } from '../refresh-tokens/refresh-tokens.service';
55
import { ConfigService } from '@nestjs/config';
66

77
@Injectable()

nestjs-BE/server/src/auth/refresh-tokens.service.spec.ts

-132
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Module } from '@nestjs/common';
2+
import { RefreshTokensService } from './refresh-tokens.service';
3+
import { JwtModule } from '@nestjs/jwt';
4+
import { PrismaModule } from '../prisma/prisma.module';
5+
6+
@Module({
7+
imports: [JwtModule, PrismaModule],
8+
providers: [RefreshTokensService],
9+
exports: [RefreshTokensService],
10+
})
11+
export class RefreshTokensModule {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
import { RefreshTokensService } from './refresh-tokens.service';
3+
import { PrismaService } from '../prisma/prisma.service';
4+
import { JwtModule } from '@nestjs/jwt';
5+
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
6+
import { ConfigModule } from '@nestjs/config';
7+
import { getExpiryDate } from '../utils/date';
8+
import { v4 as uuid } from 'uuid';
9+
10+
jest.useFakeTimers();
11+
12+
describe('RefreshTokensService', () => {
13+
let service: RefreshTokensService;
14+
let prisma: PrismaService;
15+
16+
beforeEach(async () => {
17+
const module: TestingModule = await Test.createTestingModule({
18+
imports: [JwtModule, ConfigModule.forRoot()],
19+
providers: [
20+
RefreshTokensService,
21+
{
22+
provide: PrismaService,
23+
useValue: {
24+
refreshToken: {
25+
create: jest.fn(),
26+
delete: jest.fn(),
27+
},
28+
},
29+
},
30+
],
31+
}).compile();
32+
33+
service = module.get<RefreshTokensService>(RefreshTokensService);
34+
prisma = module.get<PrismaService>(PrismaService);
35+
});
36+
37+
afterEach(() => {
38+
jest.clearAllTimers();
39+
});
40+
41+
it('createRefreshToken created', async () => {
42+
const TWO_WEEK = 14;
43+
44+
const testUserUuid = uuid();
45+
const twoWeek = new Date();
46+
twoWeek.setDate(twoWeek.getDate() + TWO_WEEK);
47+
48+
(prisma.refreshToken.create as jest.Mock).mockImplementation(
49+
async ({ data }) => {
50+
return {
51+
id: 0,
52+
token: data.token,
53+
expiryDate: data.expiryDate,
54+
userUuid: data.userUuid,
55+
};
56+
},
57+
);
58+
59+
const token = await service.createRefreshToken(testUserUuid);
60+
61+
expect(token.token).toMatch(
62+
/^[A-Za-z0-9-_]+?\.[A-Za-z0-9-_]+?\.[A-Za-z0-9-_]+$/,
63+
);
64+
expect(token.expiryDate.toISOString()).toBe(twoWeek.toISOString());
65+
expect(token.userUuid).toBe(testUserUuid);
66+
});
67+
68+
it('deleteRefreshToken deleted', async () => {
69+
const testToken = {
70+
id: 0,
71+
token: 'Token',
72+
expiryDate: getExpiryDate({ week: 2 }),
73+
userUuid: 'userId',
74+
};
75+
(prisma.refreshToken.delete as jest.Mock).mockResolvedValue(testToken);
76+
77+
const token = service.deleteRefreshToken(testToken.token);
78+
79+
await expect(token).resolves.toEqual(testToken);
80+
});
81+
82+
it('deleteRefreshToken not found', async () => {
83+
(prisma.refreshToken.delete as jest.Mock).mockRejectedValue(
84+
new PrismaClientKnownRequestError(
85+
'An operation failed because it depends on one or more records that were required but not found. Record to delete not found.',
86+
{ code: 'P2025', clientVersion: '' },
87+
),
88+
);
89+
90+
const token = service.deleteRefreshToken('Token');
91+
92+
await expect(token).resolves.toBeNull();
93+
});
94+
});

nestjs-BE/server/src/auth/refresh-tokens.service.ts nestjs-BE/server/src/refresh-tokens/refresh-tokens.service.ts

+5-12
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Injectable } from '@nestjs/common';
22
import { JwtService } from '@nestjs/jwt';
33
import { PrismaService } from '../prisma/prisma.service';
4-
import generateUuid from '../utils/uuid';
4+
import { v4 as uuid } from 'uuid';
55
import { Prisma, RefreshToken } from '@prisma/client';
6-
import { REFRESH_TOKEN_EXPIRY_DAYS } from '../config/magic-number';
76
import { ConfigService } from '@nestjs/config';
7+
import { getExpiryDate } from '../utils/date';
88

99
@Injectable()
1010
export class RefreshTokensService {
@@ -18,7 +18,7 @@ export class RefreshTokensService {
1818
return this.prisma.refreshToken.create({
1919
data: {
2020
token: this.createToken(),
21-
expiryDate: this.getExpiryDate(),
21+
expiryDate: getExpiryDate({ week: 2 }),
2222
userUuid,
2323
},
2424
});
@@ -44,21 +44,14 @@ export class RefreshTokensService {
4444
}
4545
}
4646

47-
createToken(): string {
47+
private createToken(): string {
4848
const refreshToken = this.jwtService.sign(
49-
{ uuid: generateUuid() },
49+
{ uuid: uuid() },
5050
{
5151
secret: this.configService.get<string>('JWT_REFRESH_SECRET'),
5252
expiresIn: '14d',
5353
},
5454
);
5555
return refreshToken;
5656
}
57-
58-
getExpiryDate(): Date {
59-
const currentDate = new Date();
60-
const expiryDate = new Date(currentDate);
61-
expiryDate.setDate(currentDate.getDate() + REFRESH_TOKEN_EXPIRY_DAYS);
62-
return expiryDate;
63-
}
6457
}

nestjs-BE/server/src/utils/date.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const WEEK_DAY = 7;
2+
3+
export function getExpiryDate({
4+
week = 0,
5+
day = 0,
6+
}: {
7+
week?: number;
8+
day?: number;
9+
}): Date {
10+
const expiryDate = new Date();
11+
12+
expiryDate.setDate(expiryDate.getDate() + week * WEEK_DAY + day);
13+
14+
return expiryDate;
15+
}

0 commit comments

Comments
 (0)