Skip to content

Commit

Permalink
Merge pull request #33 from boostcampwm-2024/feature/api/login-#4
Browse files Browse the repository at this point in the history
[#4] 2.03 로그인 기능 구현
  • Loading branch information
jinddings authored Nov 7, 2024
2 parents e9f5950 + abbc19b commit 5c28839
Show file tree
Hide file tree
Showing 8 changed files with 1,379 additions and 10,776 deletions.
12,039 changes: 1,268 additions & 10,771 deletions BE/package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions BE/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.3.0",
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-socket.io": "^10.4.7",
"@nestjs/schedule": "^4.1.1",
"@nestjs/swagger": "^8.0.1",
"@nestjs/typeorm": "^10.0.2",
"@types/passport-jwt": "^4.0.1",
"@nestjs/websockets": "^10.4.7",
"axios": "^1.7.7",
"bcrypt": "^5.1.1",
Expand All @@ -38,6 +41,8 @@
"dotenv": "^16.4.5",
"fastify-swagger": "^5.1.1",
"mysql2": "^3.11.3",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
"socket.io": "^4.8.1",
Expand Down
28 changes: 27 additions & 1 deletion BE/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
import { Controller, Post, Body, ValidationPipe } from '@nestjs/common';
import {
Controller,
Post,
Get,
Body,
Req,
ValidationPipe,
UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiOperation } from '@nestjs/swagger';
import { AuthService } from './auth.service';
import { AuthCredentialsDto } from './dto/authCredentials.dto';

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

@ApiOperation({ summary: '회원 가입 API' })
@Post('/signup')
signUp(@Body(ValidationPipe) authCredentialsDto: AuthCredentialsDto) {
return this.authService.signUp(authCredentialsDto);
}

@ApiOperation({ summary: '로그인 API' })
@Get('/login')
loginWithCredentials(
@Body(ValidationPipe) authCredentialsDto: AuthCredentialsDto,
) {
return this.authService.loginUser(authCredentialsDto);
}

@ApiOperation({ summary: 'Token 인증 테스트 API' })
@Get('/test')
@UseGuards(AuthGuard())
test(@Req() req: Request) {
return req;
}
}
17 changes: 15 additions & 2 deletions BE/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { User } from './user.entity';
import { UserRepository } from './user.repository';
import { JwtStrategy } from './jwt.strategy';

@Module({
imports: [TypeOrmModule.forFeature([User])],
imports: [
TypeOrmModule.forFeature([User]),
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
secret: 'Juga16',
signOptions: {
expiresIn: 3600,
},
}),
],
controllers: [AuthController],
providers: [AuthService, UserRepository],
providers: [AuthService, UserRepository, JwtStrategy],
exports: [JwtStrategy, PassportModule],
})
export class AuthModule {}
21 changes: 19 additions & 2 deletions BE/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Injectable } from '@nestjs/common';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcrypt';
import { UserRepository } from './user.repository';
import { AuthCredentialsDto } from './dto/authCredentials.dto';

Expand All @@ -8,9 +10,24 @@ export class AuthService {
constructor(
@InjectRepository(UserRepository)
private userRepository: UserRepository,
private jwtService: JwtService,
) {}

async signUp(authCredentialsDto: AuthCredentialsDto) {
async signUp(authCredentialsDto: AuthCredentialsDto): Promise<void> {
return this.userRepository.registerUser(authCredentialsDto);
}

async loginUser(
authCredentialsDto: AuthCredentialsDto,
): Promise<{ accessToken: string }> {
const { email, password } = authCredentialsDto;
const user = await this.userRepository.findOne({ where: { email } });

if (user && (await bcrypt.compare(password, user.password))) {
const payload = { email };
const accessToken = this.jwtService.sign(payload);
return { accessToken };
}
throw new UnauthorizedException('Please check your login credentials');
}
}
13 changes: 13 additions & 0 deletions BE/src/auth/dto/authCredentials.dto.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import { IsString, Matches, MaxLength, MinLength } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class AuthCredentialsDto {
@ApiProperty({
description: '유저 이메일',
minLength: 4,
maxLength: 20,
type: 'string',
})
@IsString()
@MinLength(4)
@MaxLength(20)
email: string;

@ApiProperty({
description: '유저 비밀번호',
minLength: 4,
maxLength: 20,
type: 'string',
})
@IsString()
@MinLength(4)
@MaxLength(20)
Expand Down
26 changes: 26 additions & 0 deletions BE/src/auth/jwt.strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { PassportStrategy } from '@nestjs/passport';
import { InjectRepository } from '@nestjs/typeorm';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { UserRepository } from './user.repository';
import { User } from './user.entity';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
@InjectRepository(UserRepository) private userRepository: UserRepository,
) {
super({
secretOrKey: 'Juga16',
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
});
}

async validate(payload) {
const { email } = payload;
const user: User = await this.userRepository.findOne({ where: { email } });
if (!user) throw new UnauthorizedException();

return user;
}
}
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5c28839

Please sign in to comment.