Skip to content

Commit

Permalink
Merge pull request #149 from modern-agile-team/feature/auth
Browse files Browse the repository at this point in the history
test(NicoDora/auth) : 카카오 로그인 에러 해결을 위해 log 추가
  • Loading branch information
NicoDora authored Nov 23, 2023
2 parents f80a50e + c37d550 commit 109a0b1
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 37 deletions.
122 changes: 88 additions & 34 deletions src/auth/services/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class AuthService {
private readonly userRepository: UserRepository,
private readonly userImageRepository: UserImageRepository,
private readonly tokenService: TokenService,
) {}
) {}

async naverLogin(authorizeCode: string) {
try {
Expand All @@ -32,19 +32,23 @@ export class AuthService {
redirect_uri: process.env.NAVER_CALLBACK_URL,
};

const naverToken = (await axios.post(naverTokenUrl, naverTokenBody, naverTokenHeader)).data;
const naverToken = (
await axios.post(naverTokenUrl, naverTokenBody, naverTokenHeader)
).data;

const naverAccessToken = naverToken.access_token;
const naverRefreshToken = naverToken.refresh_token;

const naverUserInfoUrl = 'https://openapi.naver.com/v1/nid/me';
const naverUserInfoHeader = {
headers: {
Authorization: `Bearer ${naverAccessToken}`,
},
};

const naverUserInfo = (await axios.get(naverUserInfoUrl, naverUserInfoHeader)).data;
const naverUserInfo = (
await axios.get(naverUserInfoUrl, naverUserInfoHeader)
).data;
const nickname = naverUserInfo.response.nickname;
const email = naverUserInfo.response.email;
const profileImage = naverUserInfo.response.profile_image;
Expand All @@ -58,33 +62,44 @@ export class AuthService {
};

const checkUser = await this.userRepository.findUser(email, provider);
if (checkUser) { // 이미 존재하는 사용자인 경우
if (checkUser) {
// 이미 존재하는 사용자인 경우
const userId = checkUser.id;

await this.userRepository.updateUserName(userId, nickname); // 이름 업데이트

const userImage = (await this.userImageRepository.checkUserImage(userId)).imageUrl; // DB 이미지
const userImage = (
await this.userImageRepository.checkUserImage(userId)
).imageUrl; // DB 이미지
const imageUrlParts = userImage.split('/');
const dbImageProvider = imageUrlParts[imageUrlParts.length - 2]; // 이미지 제공자 이름

if (dbImageProvider != 'ma6-main.s3.ap-northeast-2.amazonaws.com') { // S3에 업로드된 이미지가 아닌 경우
if (dbImageProvider != 'ma6-main.s3.ap-northeast-2.amazonaws.com') {
// S3에 업로드된 이미지가 아닌 경우
await this.userImageRepository.updateUserImage(userId, profileImage); // DB에 이미지 URL 업데이트
}

return { userId, naverAccessToken, naverRefreshToken };
} else { // 존재하지 않는 사용자인 경우
} else {
// 존재하지 않는 사용자인 경우
const newUser = await this.userRepository.createUser(userInfo);
const userId = newUser.id;
if (!profileImage) {
await this.userImageRepository.uploadUserImage(userId, process.env.DEFAULT_USER_IMAGE);
await this.userImageRepository.uploadUserImage(
userId,
process.env.DEFAULT_USER_IMAGE,
);
} else {
await this.userImageRepository.uploadUserImage(userId, profileImage);
}
return { userId, naverAccessToken, naverRefreshToken };
}
} catch (error) {
if (error.response.status == 401) {
throw new HttpException('유효하지 않은 인가코드입니다.', HttpStatus.UNAUTHORIZED);
throw new HttpException(
'유효하지 않은 인가코드입니다.',
HttpStatus.UNAUTHORIZED,
);
}
}
}
Expand All @@ -104,7 +119,9 @@ export class AuthService {
code: authorizeCode,
};

const kakaoToken = (await axios.post(kakaoTokenUrl, kakaoTokenBody, kakaoTokenHeader)).data;
const kakaoToken = (
await axios.post(kakaoTokenUrl, kakaoTokenBody, kakaoTokenHeader)
).data;
const kakaoAccessToken = kakaoToken.access_token;
const kakaoRefreshToken = kakaoToken.refresh_token;

Expand All @@ -116,7 +133,9 @@ export class AuthService {
},
};

const kakaoUserInfo = (await axios.get(kakaoUserInfoUrl, kakaoUserInfoHeader)).data;
const kakaoUserInfo = (
await axios.get(kakaoUserInfoUrl, kakaoUserInfoHeader)
).data;
const nickname = kakaoUserInfo.properties.nickname;
const email = kakaoUserInfo.kakao_account.email;
const profileImage = kakaoUserInfo.properties.profile_image;
Expand All @@ -127,45 +146,64 @@ export class AuthService {
nickname,
email,
gender,
}
};

const checkUser = await this.userRepository.findUser(email, provider);
if (checkUser) { // 이미 존재하는 사용자인 경우
if (checkUser) {
// 이미 존재하는 사용자인 경우
const userId = checkUser.id;

await this.userRepository.updateUserName(userId, nickname); // 이름 업데이트

const userImage = (await this.userImageRepository.checkUserImage(userId)).imageUrl; // DB 이미지

const userImage = (
await this.userImageRepository.checkUserImage(userId)
).imageUrl; // DB 이미지
const imageUrlParts = userImage.split('/');
const dbImageProvider = imageUrlParts[imageUrlParts.length - 2]; // 이미지 제공자 이름

if (dbImageProvider != 'ma6-main.s3.ap-northeast-2.amazonaws.com') { // S3에 업로드된 이미지가 아닌 경우
if (dbImageProvider != 'ma6-main.s3.ap-northeast-2.amazonaws.com') {
// S3에 업로드된 이미지가 아닌 경우
await this.userImageRepository.updateUserImage(userId, profileImage); // DB에 이미지 URL 업데이트
}

return { userId, kakaoAccessToken, kakaoRefreshToken };
} else { // 존재하지 않는 사용자인 경우
} else {
// 존재하지 않는 사용자인 경우
const newUser = await this.userRepository.createUser(userInfo);
const userId = newUser.id;
if (!profileImage) {
await this.userImageRepository.uploadUserImage(userId, process.env.DEFAULT_USER_IMAGE);
await this.userImageRepository.uploadUserImage(
userId,
process.env.DEFAULT_USER_IMAGE,
);
} else {
await this.userImageRepository.uploadUserImage(userId, profileImage);
}
return { userId, kakaoAccessToken, kakaoRefreshToken };
}
} catch (error) {
if (error.response.status == 400) {
throw new HttpException('유효하지 않은 인가코드입니다.', HttpStatus.UNAUTHORIZED);
throw new HttpException(
'유효하지 않은 인가코드입니다.',
HttpStatus.UNAUTHORIZED,
);
} else {
console.log(error);
throw new HttpException(
'카카오 로그인 중 오류가 발생했습니다.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}

async kakaoLogout(accessToken: string, refreshToken: string) {
try {
const checkValidKakaoToken = await this.tokenService.checkValidKakaoToken(accessToken);
const checkValidKakaoToken =
await this.tokenService.checkValidKakaoToken(accessToken);
if (checkValidKakaoToken === 401) {
const newKakaoToken = await this.tokenService.getNewKakaoToken(refreshToken);
const newKakaoToken =
await this.tokenService.getNewKakaoToken(refreshToken);
accessToken = newKakaoToken.access_token;
}

Expand All @@ -177,18 +215,23 @@ export class AuthService {
};

axios.post(kakaoLogoutUrl, {}, kakaoLogoutHeader);
return { message: "카카오 로그아웃이 완료되었습니다." };
return { message: '카카오 로그아웃이 완료되었습니다.' };
} catch (error) {
console.log(error);
throw new HttpException('카카오 로그아웃 중 오류가 발생했습니다.', HttpStatus.INTERNAL_SERVER_ERROR)
throw new HttpException(
'카카오 로그아웃 중 오류가 발생했습니다.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}

async kakaoUnlink(accessToken: string, refreshToken: string) {
try {
const checkValidKakaoToken = await this.tokenService.checkValidKakaoToken(accessToken);
const checkValidKakaoToken =
await this.tokenService.checkValidKakaoToken(accessToken);
if (checkValidKakaoToken === 401) {
const newKakaoToken = await this.tokenService.getNewKakaoToken(refreshToken);
const newKakaoToken =
await this.tokenService.getNewKakaoToken(refreshToken);
accessToken = newKakaoToken.access_token;
}

Expand All @@ -200,18 +243,23 @@ export class AuthService {
};

axios.post(kakaoUnlinkUrl, {}, kakaoUnlinkHeader);
return { message: "카카오 연결 끊기가 완료되었습니다." };
return { message: '카카오 연결 끊기가 완료되었습니다.' };
} catch (error) {
console.log(error);
throw new HttpException('카카오 연결 끊기 중 오류가 발생했습니다.', HttpStatus.INTERNAL_SERVER_ERROR)
throw new HttpException(
'카카오 연결 끊기 중 오류가 발생했습니다.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}

async naverUnlink(accessToken: string, refreshToken: string) {
try {
const checkValidNaverToken = await this.tokenService.checkValidNaverToken(accessToken);
const checkValidNaverToken =
await this.tokenService.checkValidNaverToken(accessToken);
if (checkValidNaverToken === 401) {
const newNaverToken = await this.tokenService.getNewNaverToken(refreshToken);
const newNaverToken =
await this.tokenService.getNewNaverToken(refreshToken);
accessToken = newNaverToken.access_token;
}

Expand All @@ -229,18 +277,24 @@ export class AuthService {
};

axios.post(naverUnlinkUrl, naverUnlinkBody, naverUnlinkHeader);
return { message: "네이버 연동 해제가 완료되었습니다." };
return { message: '네이버 연동 해제가 완료되었습니다.' };
} catch (error) {
console.log(error);
throw new HttpException('네이버 연결 끊기 중 오류가 발생했습니다.', HttpStatus.INTERNAL_SERVER_ERROR)
throw new HttpException(
'네이버 연결 끊기 중 오류가 발생했습니다.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}

async accountDelete(userId: number) {
const deleteUser = await this.userRepository.deleteUser(userId);
if (!deleteUser) {
throw new HttpException('사용자를 찾을 수 없습니다.', HttpStatus.NOT_FOUND);
throw new HttpException(
'사용자를 찾을 수 없습니다.',
HttpStatus.NOT_FOUND,
);
}
return { message: "사용자 계정 삭제가 완료되었습니다." };
return { message: '사용자 계정 삭제가 완료되었습니다.' };
}
}
4 changes: 3 additions & 1 deletion src/common/decorators/get-userId.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { ExecutionContext, createParamDecorator } from '@nestjs/common';
export const GetUserId = createParamDecorator(
(data, ctx: ExecutionContext): number => {
const req = ctx.switchToHttp().getRequest();

if (!req.user) {
return null;
}
return req.user.userId;
},
);
2 changes: 1 addition & 1 deletion src/config/guards/jwt-access-token.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class JwtAccessTokenGuard {
const accessToken = request.headers['access_token'];

if (!accessToken) {
return false;
return true;
}

const userId = await this.tokenService.decodeToken(accessToken);
Expand Down
8 changes: 7 additions & 1 deletion src/users/services/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable } from '@nestjs/common';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { UserRepository } from '../repositories/user.repository';
import { UserImageRepository } from '../repositories/user-image.repository';

Expand All @@ -10,6 +10,12 @@ export class UserService {
) {}

async getMyInfo(userId: number) {
if (!userId) {
throw new HttpException(
'토큰이 제공되지 않았습니다.',
HttpStatus.LENGTH_REQUIRED,
);
}
const { name, email, gender, admin, provider } =
await this.userRepository.getUserInfo(userId);
const userImage = (await this.userImageRepository.checkUserImage(userId))
Expand Down

0 comments on commit 109a0b1

Please sign in to comment.