Skip to content

Commit

Permalink
Merge pull request #226 from songbuild00/feature-be-#74#77
Browse files Browse the repository at this point in the history
[BE] feat#74#77 νšŒμ›κ°€μž…, 둜그인 κ΅¬ν˜„
  • Loading branch information
songbuild00 authored Nov 20, 2024
2 parents 2ed98f3 + ed34cbd commit 1300288
Show file tree
Hide file tree
Showing 19 changed files with 832 additions and 95 deletions.
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);
}

@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;
}
}
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
44 changes: 27 additions & 17 deletions BE/src/user/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { UserModel } from './entities/user.entity';
import * as bcrypt from 'bcrypt';
import { SignupDto } from '../auth/dto/signup.dto';

@Injectable()
export class UserService {
create(createUserDto: CreateUserDto) {
return 'This action adds a new user';
}

findAll() {
return `This action returns all user`;
}

findOne(id: number) {
return `This action returns a #${id} user`;
}
constructor(
@InjectRepository(UserModel)
private readonly userRepository: Repository<UserModel>
) {}

update(id: number, updateUserDto: UpdateUserDto) {
return `This action updates a #${id} user`;
async create(signupDto: SignupDto) {
const salt = await bcrypt.genSalt();
const hashedPassword = await bcrypt.hash(signupDto.password, salt);
const newUser = this.userRepository.create({
email: signupDto.email,
password: hashedPassword,
nickname: signupDto.nickname,
status: '?'
});
return this.userRepository.save(newUser);
}

remove(id: number) {
return `This action removes a #${id} user`;
async findOne(email: string) {
const user = await this.userRepository.findOne({
where: { email }
});
if (!user) {
return null;
}
return user;
}
}

0 comments on commit 1300288

Please sign in to comment.