Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/controllers/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class UserController {
const ip = typeof req.headers['x-forwarded-for'] === 'string' ? req.headers['x-forwarded-for'].split(',')[0].trim() : req.ip ?? '';
const userAgent = req.headers['user-agent'] || '';

const token = await this.userService.create(user.id, ip, userAgent);
const token = await this.userService.create(user.velog_uuid, ip, userAgent);
const typedToken = token as Token10;

const response = new QRLoginTokenResponseDto(
Expand Down Expand Up @@ -147,7 +147,7 @@ export class UserController {
}

const { decryptedAccessToken, decryptedRefreshToken } =
await this.userService.findUserAndTokensByVelogUUID(found.user.toString());
await this.userService.findUserAndTokensByVelogUUID(String(found.user));

res.clearCookie('access_token', this.cookieOption());
res.clearCookie('refresh_token', this.cookieOption());
Expand Down
37 changes: 29 additions & 8 deletions src/services/__test__/qr.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,44 @@ describe('UserService 의 QRService', () => {
});

describe('create', () => {
const velogUUID = 'uuid-1234';
const ip = '127.0.0.1';
const userAgent = 'Chrome';

const mockUser = {
id: 1,
velog_uuid: velogUUID,
access_token: 'token',
refresh_token: 'token',
group_id: 1,
email: 'test@example.com',
is_active: true,
created_at: new Date(),
updated_at: new Date(),
};

it('QR 토큰을 생성하고 반환해야 한다', async () => {
const userId = 1;
const ip = '127.0.0.1';
const userAgent = 'Chrome';

const token = await service.create(userId, ip, userAgent);

repo.findByUserVelogUUID.mockResolvedValueOnce(mockUser);

const token = await service.create(velogUUID, ip, userAgent);

expect(typeof token).toBe('string');
expect(token.length).toBe(10);
expect(/^[A-Za-z0-9\-_.~!]{10}$/.test(token)).toBe(true);
expect(repo.createQRLoginToken).toHaveBeenCalledWith(token, userId, ip, userAgent);
expect(repo.createQRLoginToken).toHaveBeenCalledWith(token, mockUser.id, ip, userAgent);
});

it('유저 조회 실패 시 예외 발생', async () => {
repo.findByUserVelogUUID.mockResolvedValueOnce(null as unknown as typeof mockUser);

await expect(service.create(velogUUID, ip, userAgent)).rejects.toThrow('QR 토큰 생성 실패: 유저 없음');
});

it('QR 토큰 생성 중 오류 발생 시 예외 발생', async () => {
repo.findByUserVelogUUID.mockResolvedValueOnce(mockUser);
repo.createQRLoginToken.mockRejectedValueOnce(new DBError('생성 실패'));

await expect(service.create(1, 'ip', 'agent')).rejects.toThrow('생성 실패');
await expect(service.create(velogUUID, ip, userAgent)).rejects.toThrow('생성 실패');
});
});

Expand Down
9 changes: 7 additions & 2 deletions src/services/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,14 @@ export class UserService {
return { user, decryptedAccessToken, decryptedRefreshToken };
}

async create(userId: number, ip: string, userAgent: string): Promise<string> {
async create(velogUUID: string, ip: string, userAgent: string): Promise<string> {
const user = await this.userRepo.findByUserVelogUUID(velogUUID);
if (!user) {
throw new NotFoundError('QR 토큰 생성 실패: 유저 없음');
}

const token = generateRandomToken(10);
await this.userRepo.createQRLoginToken(token, userId, ip, userAgent);
await this.userRepo.createQRLoginToken(token, user.id, ip, userAgent);
return token;
}

Expand Down
Loading