Skip to content

Commit

Permalink
Merge pull request #72 from boostcampwm-2024/be/fix/JWT_options
Browse files Browse the repository at this point in the history
[Be/fix] JWT 타입 방식 수정 및 일부 오탈자 수정
  • Loading branch information
HBLEEEEE authored Nov 21, 2024
2 parents e321ce6 + bd94b7a commit f87c792
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 40 deletions.
9 changes: 6 additions & 3 deletions apps/backend/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { JwtAuthGuard } from 'src/global/utils/jwtAuthGuard';
import { Request } from 'express';
import { logoutResponseDecorator } from './decorator/logout.decorator';
import { UpdateIntroduceDto } from './dto/updateIntroduce.dto';
import { MemberData } from 'src/global/utils/requestInterface';
import { updateIntroduceResponseDecorator } from './decorator/updateIntroduce.decorator';
import { User } from 'src/global/utils/memberData';

@Controller('api/auth')
export class AuthController {
Expand Down Expand Up @@ -79,8 +79,11 @@ export class AuthController {
@UseGuards(JwtAuthGuard)
@ApiOperation({ summary: '유저 소개글 변경 API' })
@updateIntroduceResponseDecorator()
async updateIntroduce(@Req() req: Request, @Body() updateIntroduceDto: UpdateIntroduceDto) {
const { memberId } = req.user as MemberData;
async updateIntroduce(
@User() user: { memberId: number },
@Body() updateIntroduceDto: UpdateIntroduceDto
) {
const { memberId } = user;
const { introduce } = updateIntroduceDto;
await this.authService.updateIntroduce(memberId, introduce);
return successhandler(successMessage.INTRODUCE_UPDATE_SUCCESS);
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/auth/auth.queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ export const authQueries = {
signUpQuery: 'INSERT INTO members (email, password, nickname) VALUES ($1, $2, $3) RETURNING *',
findByEmailQuery:
'SELECT member_id, email, password, nickname FROM members WHERE email = $1 LIMIT 1',
upateMemberQuery: 'UPDATE members SET introduce = $1 WHERE member_id = $2'
updateMemberQuery: 'UPDATE members SET introduce = $1 WHERE member_id = $2'
};
48 changes: 24 additions & 24 deletions apps/backend/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { JwtService } from '@nestjs/jwt';
import { GoogleLoginDto } from './dto/googleLogin.dto';
import { KakaoLoginDto } from './dto/kakaoLogin.dto';
import { RedisClientType } from 'redis';
import { Nullable, Optional } from 'src/global/utils/dataCustomType';

@Injectable()
export class AuthService {
Expand Down Expand Up @@ -61,45 +62,44 @@ export class AuthService {
if (!isPasswordValid)
throw new HttpException('이메일 또는 비밀번호가 올바르지 않습니다.', HttpStatus.UNAUTHORIZED);

const payload = {
memberId: member.rows[0].member_id,
email,
nickname: member.rows[0].nickname
};
const accessToken = this.jwtService.sign(payload, { expiresIn: '1h' });
const refreshToken = this.jwtService.sign(payload, { expiresIn: '7d' });
return { accessToken, refreshToken };
return this.generateTokens(member.rows[0].member_id);
}

async loginWithSocialMedia(email: string, nickname: string) {
private async verifyUser(email: string, nickname: string) {
const existingUser = await this.databaseService.query(authQueries.findByEmailQuery, [email]);

if (!existingUser) {
const hashedPassword = await bcrypt.hash('default', 10);
await this.databaseService.query(authQueries.signUpQuery, [email, hashedPassword, nickname]);
}
const member = await this.databaseService.query(authQueries.findByEmailQuery, [email]);
const payload = {
memberId: member.rows[0].member_id,
if (existingUser?.rows?.length) return existingUser.rows[0].memberId;
const hashedPassword = await bcrypt.hash('default', 10);
const newMember = await this.databaseService.query(authQueries.signUpQuery, [
email,
nickname: member.rows[0].nickname
};
hashedPassword,
nickname
]);
return newMember.rows[0].memberId;
}

async SocialLogin(email: string, nickname: string) {
const memberId = await this.verifyUser(email, nickname);
return this.generateTokens(memberId);
}

private async generateTokens(memberId: number) {
const payload = { memberId };
const accessToken = this.jwtService.sign(payload, { expiresIn: '1h' });
const refreshToken = this.jwtService.sign(payload, { expiresIn: '7d' });
return { accessToken, refreshToken };
}

async googleLogin(googleLoginDto: GoogleLoginDto) {
const { email, name } = googleLoginDto;
return this.loginWithSocialMedia(email, name);
return this.SocialLogin(email, name);
}

async kakaoLogin(kakaoLoginDto: KakaoLoginDto) {
const { email, nickname } = kakaoLoginDto;
return this.loginWithSocialMedia(email, nickname);
return this.SocialLogin(email, nickname);
}

async logout(token: string | undefined) {
async logout(token: Optional<string>) {
if (!token) throw new HttpException('토큰이 필요합니다.', HttpStatus.BAD_REQUEST);

const decodedToken = this.jwtService.decode(token) as { exp: number };
Expand All @@ -111,7 +111,7 @@ export class AuthService {
await this.redisClient.set(`blacklist:${token}`, 'true', { PX: remainingTime });
}

async updateIntroduce(memberId: number, introduce: string | null) {
await this.databaseService.query(authQueries.upateMemberQuery, [introduce, memberId]);
async updateIntroduce(memberId: number, introduce: Nullable<string>) {
await this.databaseService.query(authQueries.updateMemberQuery, [introduce, memberId]);
}
}
2 changes: 2 additions & 0 deletions apps/backend/src/global/utils/dataCustomType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type Nullable<T> = T | null;
export type Optional<T> = T | undefined;
4 changes: 2 additions & 2 deletions apps/backend/src/global/utils/jwtAuthGuard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export class JwtAuthGuard {
throw new HttpException('만료된 토큰입니다.', HttpStatus.UNAUTHORIZED);
}

const { memberId, email, nickname } = decoded;
request.user = { memberId, email, nickname };
const { memberId } = decoded;
request.member = { memberId };
return true;
} catch {
throw new HttpException('잘못된 토큰입니다.', HttpStatus.UNAUTHORIZED);
Expand Down
8 changes: 8 additions & 0 deletions apps/backend/src/global/utils/memberData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const User = createParamDecorator((data: string | undefined, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;

return data ? user?.[data] : user;
});
5 changes: 0 additions & 5 deletions apps/backend/src/global/utils/requestInterface.ts

This file was deleted.

9 changes: 4 additions & 5 deletions apps/backend/src/lotto/lotto.controller.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Controller, Post, Req, UseGuards } from '@nestjs/common';
import { Controller, Post, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
import { JwtAuthGuard } from 'src/global/utils/jwtAuthGuard';
import { LottoService } from './lotto.service';
import { successhandler, successMessage } from 'src/global/successhandler';
import { lottoResponseDecorator } from './decorator/lotto.decorator';
import { MemberData } from 'src/global/utils/requestInterface';
import { Request } from 'express';
import { User } from 'src/global/utils/memberData';

@Controller('api/lotto')
@ApiBearerAuth()
Expand All @@ -16,8 +15,8 @@ export class LottoController {
@Post()
@ApiOperation({ summary: '복권 긁기 요청 API' })
@lottoResponseDecorator()
async buyLotto(@Req() req: Request) {
const { memberId } = req.user as MemberData;
async buyLotto(@User() user: { memberId: number }) {
const { memberId } = user;
if (!memberId) {
throw new Error('올바르지 않은 사용자입니다.');
}
Expand Down

0 comments on commit f87c792

Please sign in to comment.