Skip to content

Commit

Permalink
refactor: 카카오 로그인 로직 서비스로 이동
Browse files Browse the repository at this point in the history
  • Loading branch information
Conut-1 committed Oct 17, 2024
1 parent 758469f commit 12e5c67
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 57 deletions.
36 changes: 7 additions & 29 deletions nestjs-BE/server/src/auth/auth.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { HttpStatus, NotFoundException } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { User } from '@prisma/client';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UsersService } from '../users/users.service';
import { ProfilesService } from '../profiles/profiles.service';

describe('AuthController', () => {
let controller: AuthController;
let usersService: UsersService;
let authService: AuthService;

beforeEach(async () => {
Expand All @@ -20,47 +16,26 @@ describe('AuthController', () => {
{
provide: AuthService,
useValue: {
getKakaoAccount: jest.fn(),
login: jest.fn(),
kakaoLogin: jest.fn(),
renewAccessToken: jest.fn(),
logout: jest.fn(),
},
},
{
provide: UsersService,
useValue: {
findUserByEmailAndProvider: jest.fn(),
getOrCreateUser: jest.fn(),
},
},
{
provide: ProfilesService,
useValue: {
getOrCreateProfile: jest.fn(),
},
},
],
}).compile();

controller = module.get<AuthController>(AuthController);
authService = module.get<AuthService>(AuthService);
usersService = module.get<UsersService>(UsersService);
});

it('kakaoLogin', async () => {
const requestMock = { kakaoUserId: 0 };
const kakaoUserAccountMock = { email: 'kakao email' };
const tokenMock = {
refresh_token: 'refresh token',
access_token: 'access token',
};
jest
.spyOn(authService, 'getKakaoAccount')
.mockResolvedValue(kakaoUserAccountMock);
jest.spyOn(usersService, 'getOrCreateUser').mockResolvedValue({
uuid: 'user uuid',
} as User);
jest.spyOn(authService, 'login').mockResolvedValue(tokenMock);

jest.spyOn(authService, 'kakaoLogin').mockResolvedValue(tokenMock);

const response = controller.kakaoLogin(requestMock);

Expand All @@ -73,7 +48,10 @@ describe('AuthController', () => {

it('kakaoLogin kakao login fail', async () => {
const requestMock = { kakaoUserId: 0 };
jest.spyOn(authService, 'getKakaoAccount').mockResolvedValue(null);

jest
.spyOn(authService, 'kakaoLogin')
.mockRejectedValue(new NotFoundException());

const response = controller.kakaoLogin(requestMock);

Expand Down
30 changes: 3 additions & 27 deletions nestjs-BE/server/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
import {
Controller,
Post,
Body,
NotFoundException,
HttpStatus,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Controller, Post, Body, HttpStatus } from '@nestjs/common';
import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger';
import { AuthService } from './auth.service';
import { Public } from './decorators/public.decorator';
import { KakaoUserDto } from './dto/kakao-user.dto';
import { RefreshTokenDto } from './dto/refresh-token.dto';
import { UsersService } from '../users/users.service';
import { ProfilesService } from '../profiles/profiles.service';

@Controller('auth')
@ApiTags('auth')
export class AuthController {
constructor(
private authService: AuthService,
private usersService: UsersService,
private profilesService: ProfilesService,
private configService: ConfigService,
) {}
constructor(private authService: AuthService) {}

@Post('kakao-oauth')
@Public()
Expand All @@ -36,19 +22,9 @@ export class AuthController {
description: 'Not Found.',
})
async kakaoLogin(@Body() kakaoUserDto: KakaoUserDto) {
const kakaoUserAccount = await this.authService.getKakaoAccount(
const tokenData = await this.authService.kakaoLogin(
kakaoUserDto.kakaoUserId,
);
if (!kakaoUserAccount) throw new NotFoundException();
const userData = { email: kakaoUserAccount.email };
const user = await this.usersService.getOrCreateUser(userData);
const profileData = {
userUuid: user.uuid,
image: this.configService.get<string>('BASE_IMAGE_URL'),
nickname: '익명의 사용자',
};
await this.profilesService.getOrCreateProfile(profileData);
const tokenData = await this.authService.login(user.uuid);
return { statusCode: HttpStatus.OK, message: 'OK', data: tokenData };
}

Expand Down
41 changes: 41 additions & 0 deletions nestjs-BE/server/src/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { Test, TestingModule } from '@nestjs/testing';
import { JwtModule, JwtService } from '@nestjs/jwt';
import { ConfigModule } from '@nestjs/config';
import { NotFoundException } from '@nestjs/common';
import { RefreshToken } from '@prisma/client';
import { AuthService } from './auth.service';
import { RefreshTokensService } from '../refresh-tokens/refresh-tokens.service';
import { UsersService } from '../users/users.service';
import { ProfilesService } from '../profiles/profiles.service';

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

describe('AuthService', () => {
let service: AuthService;
let jwtService: JwtService;
let refreshTokensService: RefreshTokensService;
let usersService: UsersService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
Expand All @@ -24,6 +28,14 @@ describe('AuthService', () => {
findRefreshToken: jest.fn(),
},
},
{
provide: UsersService,
useValue: { getOrCreateUser: jest.fn() },
},
{
provide: ProfilesService,
useValue: { getOrCreateProfile: jest.fn() },
},
],
})
.overrideProvider(JwtService)
Expand All @@ -34,12 +46,41 @@ describe('AuthService', () => {
jwtService = module.get<JwtService>(JwtService);
refreshTokensService =
module.get<RefreshTokensService>(RefreshTokensService);
usersService = module.get<UsersService>(UsersService);
});

afterEach(() => {
fetchSpy.mockRestore();
});

describe('kakaoLogin', () => {
const kakaoUserId = 0;
const kakaoUser = { email: '[email protected]' };
const user = { uuid: 'user uuid' };
const tokens = {
access_token: 'access token',
refresh_token: 'refresh token',
};

it('kakao user exist', async () => {
jest.spyOn(service, 'getKakaoAccount').mockResolvedValue(kakaoUser);
jest.spyOn(service, 'login').mockResolvedValue(tokens);
(usersService.getOrCreateUser as jest.Mock).mockResolvedValue(user);

const tokenData = service.kakaoLogin(kakaoUserId);

await expect(tokenData).resolves.toEqual(tokens);
});

it('kakao user not exist', async () => {
jest.spyOn(service, 'getKakaoAccount').mockResolvedValue(null);

const tokenData = service.kakaoLogin(kakaoUserId);

await expect(tokenData).rejects.toThrow(NotFoundException);
});
});

it('login success', async () => {
jest.spyOn(jwtService, 'signAsync').mockResolvedValue('access token');
jest.spyOn(refreshTokensService, 'createRefreshToken').mockResolvedValue({
Expand Down
25 changes: 24 additions & 1 deletion nestjs-BE/server/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import {
Injectable,
NotFoundException,
UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
import { stringify } from 'qs';
import { RefreshTokensService } from '../refresh-tokens/refresh-tokens.service';
import { UsersService } from '../users/users.service';
import { ProfilesService } from '../profiles/profiles.service';

@Injectable()
export class AuthService {
constructor(
private jwtService: JwtService,
private configService: ConfigService,
private refreshTokensService: RefreshTokensService,
private usersService: UsersService,
private profilesService: ProfilesService,
) {}

async kakaoLogin(kakaoUserId: number) {
const kakaoUserAccount = await this.getKakaoAccount(kakaoUserId);
if (!kakaoUserAccount) throw new NotFoundException();
const userData = { email: kakaoUserAccount.email };
const user = await this.usersService.getOrCreateUser(userData);
const profileData = {
userUuid: user.uuid,
image: this.configService.get<string>('BASE_IMAGE_URL'),
nickname: '익명의 사용자',
};
await this.profilesService.getOrCreateProfile(profileData);
const tokenData = await this.login(user.uuid);
return tokenData;
}

async getKakaoAccount(kakaoUserId: number) {
const url = `https://kapi.kakao.com/v2/user/me`;
const queryParams = { target_id_type: 'user_id', target_id: kakaoUserId };
Expand Down

0 comments on commit 12e5c67

Please sign in to comment.