Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

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 any);

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('uuid-1234', 'ip', 'agent')).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