오늘은 차근차근 회원가입부터 구현을 다시 시작했습니다
src/user/dto/user.dto.ts
import { ApiProperty, PickType } from '@nestjs/swagger';
import { User } from '../user.schema';
export class ReadOnlyUserDto extends PickType(User, ['email', 'name']) {
@ApiProperty({
example: '3280199',
description: 'id',
})
id: string;
}
src/user/dto/user.request.dto.ts
import { PickType } from '@nestjs/swagger';
import { User } from '../user.schema';
export class UserRequestDto extends PickType(User, [
'email',
'name',
'password',
] as const) {}
src/user/user.controller.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { UserController } from './user.controller';
describe('UserController', () => {
let controller: UserController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [UserController],
}).compile();
controller = module.get<UserController>(UserController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
src/user/user.controller.ts
import { Body, UseFilters, UseInterceptors } from '@nestjs/common';
import { Controller, Get, Post, Put } from '@nestjs/common';
import { UserService } from './user.service';
import { SuccessInterceptor } from 'src/common/interceptors/success.interceptor';
import { HttpExceptionFilter } from 'src/common/exceptions/http-exception.filter';
import { UserRequestDto } from './dto/user.request.dto';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { ReadOnlyUserDto } from './dto/user.dto';
@Controller('user')
@UseInterceptors(SuccessInterceptor)
@UseFilters(HttpExceptionFilter)
export class UserController {
constructor(private readonly userService: UserService) {}
@ApiOperation({ summary: '현재 유저 가져오기' })
@Get()
getCurrentUser() {
return 'current user';
}
@ApiResponse({
status: 500,
description: 'Server Error...',
})
@ApiResponse({
status: 200,
description: '성공!',
type: ReadOnlyUserDto,
})
@ApiOperation({ summary: '회원가입' })
@Post()
signUp(@Body() body: UserRequestDto) {
return this.userService.signUp(body);
}
@ApiOperation({ summary: '로그인' })
@Post('login')
logIn() {
return 'login';
}
@ApiOperation({ summary: '로그아웃' })
@Post('logout')
logOut() {
return 'logout';
}
}
src/user/user.module.ts
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { MongooseModule } from '@nestjs/mongoose';
import { User, UserSchema } from './user.schema';
@Module({
imports: [
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
],
controllers: [UserController],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}
src/user/user.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
import { Document, SchemaOptions } from 'mongoose';
import { ApiProperty } from '@nestjs/swagger';
const options: SchemaOptions = {
timestamps: true,
};
export type UserDocument = User & Document;
@Schema(options)
export class User extends Document {
@ApiProperty({
example: 'vldzm4268@gmail.com',
description: 'email',
required: true,
})
@Prop({
required: true,
unique: true,
})
@IsEmail()
@IsNotEmpty()
email: string;
@ApiProperty({
example: '1106',
description: 'password',
required: true,
})
@Prop({
required: true,
})
@IsString()
@IsNotEmpty()
password: string;
@ApiProperty({
example: 'JangJaeKyun',
description: 'name',
required: true,
})
@Prop({
required: true,
})
@IsString()
@IsNotEmpty()
name: string;
readonly readOnlyData: { id: string; email: string; name: string };
}
export const UserSchema = SchemaFactory.createForClass(User);
UserSchema.virtual('readOnlyData').get(function (this: User) {
return {
id: this.id,
email: this.email,
name: this.name,
};
});
src/user/user.service.ts
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import * as bcrypt from 'bcrypt';
import { User } from './user.schema';
import { UserRequestDto } from './dto/user.request.dto';
@Injectable()
export class UserService {
constructor(
@InjectModel(User.name) private readonly userModel: Model<User>,
) {}
async signUp(body: UserRequestDto) {
const { email, name, password } = body;
const isUserExist = await this.userModel.exists({ email });
if (isUserExist) {
throw new UnauthorizedException('해당하는 이메일는 이미 존재합니다.');
}
const hashedPassword = await bcrypt.hash(password, 10);
const user = await this.userModel.create({
email,
name,
password: hashedPassword,
});
return user.readOnlyData;
}
}
이걸로 회원가입 구현에 성공했습니다
내일은 다시 로그인과 jwt 구현을 다시 해볼 생각입니다!
글이 잘 정리되어 있네요. 감사합니다.