Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] feat#74#77 회원가입, 로그인 구현 #226

Merged
merged 3 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
610 changes: 594 additions & 16 deletions BE/package-lock.json

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions BE/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,24 @@
"@nestjs/common": "^10.4.7",
"@nestjs/config": "^3.3.0",
"@nestjs/core": "^10.4.7",
"@nestjs/jwt": "^10.2.0",
"@nestjs/mapped-types": "*",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-socket.io": "^10.4.6",
"@nestjs/swagger": "^8.0.5",
"@nestjs/typeorm": "^10.0.2",
"@nestjs/websockets": "^10.4.7",
"axios": "^1.7.7",
"bcrypt": "^5.1.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dotenv": "^16.4.5",
"ioredis": "^5.4.1",
"mysql2": "^3.11.4",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"redis": "^4.7.0",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
Expand All @@ -56,10 +62,13 @@
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.4.6",
"@types/bcrypt": "^5.0.2",
"@types/express": "^4.17.17",
"@types/ioredis-mock": "^8.2.5",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/passport-jwt": "^4.0.1",
"@types/passport-local": "^1.0.38",
"@types/socket.io": "^3.0.2",
"@types/supertest": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
Expand Down
4 changes: 3 additions & 1 deletion BE/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { InitDBModule } from './InitDB/InitDB.module';
import { UserModule } from './user/user.module';
import { QuizSetModule } from './quiz-set/quiz-set.module';
import { WaitingRoomModule } from './waiting-room/waiting-room.module';
import { AuthModule } from './auth/auth.module';

@Module({
imports: [
Expand Down Expand Up @@ -45,7 +46,8 @@ import { WaitingRoomModule } from './waiting-room/waiting-room.module';
QuizSetModule,
UserModule,
InitDBModule,
WaitingRoomModule
WaitingRoomModule,
AuthModule
],
controllers: [AppController],
providers: [AppService]
Expand Down
18 changes: 18 additions & 0 deletions BE/src/auth/auth.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AuthController } from './auth.controller';

describe('AuthController', () => {
let controller: AuthController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [AuthController]
}).compile();

controller = module.get<AuthController>(AuthController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
27 changes: 27 additions & 0 deletions BE/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Body, Controller, Get, Post, Request, UseGuards } from '@nestjs/common';
import { AuthService } from './auth.service';
import { LocalAuthGuard } from './guard/local-auth.guard';
import { JwtAuthGuard } from './guard/jwt-auth.guard';
import { SignupDto } from './dto/signup.dto';

@Controller('/api/auth')
export class AuthController {
constructor(private authService: AuthService) {}

@Post('signup')
async signup(@Body() signupDto: SignupDto) {
return this.authService.signup(signupDto);
}

@UseGuards(LocalAuthGuard)
@Post('login')
async login(@Request() req) {
return this.authService.login(req.user);
}
Comment on lines +16 to +20
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로컬 가드는 역할이 뭔가요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로그인할때 body로 email, pw 얻어와서 jwt로 바꾸는역할


@UseGuards(JwtAuthGuard)
@Get('profile')
async profile(@Request() req) {
return req.user;
}
}
26 changes: 26 additions & 0 deletions BE/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { UserModule } from '../user/user.module';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import { JwtStrategy } from './guard/jwt.strategy';
import { LocalStrategy } from './guard/local.strategy';
import { ConfigModule } from '@nestjs/config';

@Module({
imports: [
UserModule,
PassportModule,
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: () => ({
secret: process.env.JWT_SECRET || 'SECRET_KEY',
signOptions: { expiresIn: '1d' }
})
})
],
providers: [AuthService, LocalStrategy, JwtStrategy],
controllers: [AuthController]
})
export class AuthModule {}
18 changes: 18 additions & 0 deletions BE/src/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AuthService } from './auth.service';

describe('AuthService', () => {
let service: AuthService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AuthService],
}).compile();

service = module.get<AuthService>(AuthService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
45 changes: 45 additions & 0 deletions BE/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Injectable } from '@nestjs/common';
import { UserService } from '../user/user.service';
import { JwtService } from '@nestjs/jwt';
import { UserModel } from '../user/entities/user.entity';
import * as bcrypt from 'bcrypt';
import { SignupDto } from './dto/signup.dto';

@Injectable()
export class AuthService {
constructor(
private userService: UserService,
private jwtService: JwtService
) {}

async validateUserInLocal(email: string, password: string) {
const user = await this.userService.findOne(email);
if (user && (await bcrypt.compare(password, user.password))) {
return user;
}
return null;
}

async validateUserInJwt(id: number, email: string) {
const user = await this.userService.findOne(email);
if (user && user.id === id) {
return user;
}
return null;
}

async login(user: UserModel) {
const payload = { sub: user.id, email: user.email };
return {
access_token: this.jwtService.sign(payload)
};
}

async signup(signupDto: SignupDto) {
const user = await this.userService.create(signupDto);
if (user) {
return user;
}
return null;
}
}
12 changes: 12 additions & 0 deletions BE/src/auth/dto/signup.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { IsEmail, IsString } from 'class-validator';

export class SignupDto {
@IsEmail()
email: string;

@IsString()
password: string;

@IsString()
nickname: string;
}
5 changes: 5 additions & 0 deletions BE/src/auth/guard/jwt-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { AuthGuard } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
24 changes: 24 additions & 0 deletions BE/src/auth/guard/jwt.strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthService } from '../auth.service';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.JWT_SECRET || 'SECRET_KEY'
});
}

async validate(payload: any) {
console.log(`TEST VALIDATE ${payload}`);
const user = await this.authService.validateUserInJwt(payload.sub, payload.username);
if (!user) {
throw new UnauthorizedException('잘못된 토큰입니다.');
}
return user;
}
}
5 changes: 5 additions & 0 deletions BE/src/auth/guard/local-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {}
19 changes: 19 additions & 0 deletions BE/src/auth/guard/local.strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthService } from '../auth.service';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) {
super({ usernameField: 'email', passwordField: 'password' });
}

async validate(email: string, password: string): Promise<any> {
const user = await this.authService.validateUserInLocal(email, password);
if (!user) {
throw new UnauthorizedException('이메일 혹은 비밀번호를 확인해주세요.');
}
return user;
}
}
19 changes: 4 additions & 15 deletions BE/src/game/service/game.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,21 +199,10 @@ export class GameService {
const correctPlayers = [];
for (const clientId of clients) {
const player = await this.redis.hgetall(REDIS_KEY.PLAYER(clientId));
// 임시로 4개 선택지의 경우만 선정 (1 2 / 3 4)
let selectAnswer = 0;
if (parseFloat(player.positionY) < 0.5) {
if (parseFloat(player.positionX) < 0.5) {
selectAnswer = 1;
} else {
selectAnswer = 2;
}
} else {
if (parseFloat(player.positionX) < 0.5) {
selectAnswer = 3;
} else {
selectAnswer = 4;
}
}
const x = parseFloat(player.positionY);
const y = parseFloat(player.positionX);
const selectAnswer =
Math.round(x) + Math.floor(y * Math.ceil(parseInt(quiz.choiceCount) / 2)) * 2;
await this.redis.set(`${REDIS_KEY.PLAYER(clientId)}:Changes`, 'AnswerCorrect');
if (selectAnswer.toString() === quiz.answer) {
correctPlayers.push(clientId);
Expand Down
1 change: 0 additions & 1 deletion BE/src/user/dto/create-user.dto.ts

This file was deleted.

4 changes: 0 additions & 4 deletions BE/src/user/dto/update-user.dto.ts

This file was deleted.

20 changes: 0 additions & 20 deletions BE/src/user/user.controller.spec.ts

This file was deleted.

34 changes: 0 additions & 34 deletions BE/src/user/user.controller.ts

This file was deleted.

2 changes: 0 additions & 2 deletions BE/src/user/user.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserModel } from './entities/user.entity';
import { UserQuizArchiveModel } from './entities/user-quiz-archive.entity';

@Module({
imports: [TypeOrmModule.forFeature([UserModel, UserQuizArchiveModel])],
controllers: [UserController],
providers: [UserService],
exports: [UserService]
})
Expand Down
Loading
Loading