728x90
signup api를 구현하고 virtual 필드로 민감 정보를 가리는 조치를 취해보자.
Controller 레이어
// cats.controller.ts
...
@Controller('cats')
@UseInterceptors(SuccessInterceptor)
@UseFilters(HttpExceptionFilter)
export class CatsController {
// catsService 종속성 주입
constructor(private readonly catsService: CatsService) {}
@Get()
getCurrentCat() {
return 'current cat';
}
@Post()
async signUp(@Body() body: CatRequestDto) {
return await this.catsService.signUp(body);
}
@Post('login')
login() {
return 'login';
}
@Post('logout')
logOut() {
return 'log out';
}
@Post('upload/cats')
uploadCatImg() {
return 'uploadImg';
}
}
signUp API가 있다. 생성자 주입으로 받은 catsService의 signUp 메소드를 호출한다.
service 레이어
// cats.service
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import * as bcrypt from 'bcrypt';
import { Cat } from './cats.schema';
import { CatRequestDto } from './dto/cats.request.dto';
@Injectable()
export class CatsService {
// cats.schema의 Cat 클래스를 @InjectModel 메소드로 종속성 주입.
// 사전에 현재 module에 MongooseModule import 해야함
constructor(@InjectModel(Cat.name) private readonly catModel: Model<Cat>) {}
async signUp(body: CatRequestDto) {
const { email, name, password } = body;
const isCatExist = await this.catModel.exists({ email });
if (isCatExist) {
throw new UnauthorizedException('해당하는 고양이는 이미 존재합니다.');
}
// 비밀번호 해시화
const hashedPassword = await bcrypt.hash(password, 10);
// DB 저장
const cat = await this.catModel.create({
email,
name,
password: hashedPassword,
});
// virtual field로 반환하여 비밀번호 숨김처리
return cat.readOnlyData;
}
}
@InjectModel 데코레이터로 Cat 스키마를 생성자 주입받아서, signUp에서 사용한다. 요청 시 전달받은 body 값을 해체하고, 이중 email이 이미 등록된 것인지 확인한 후 등록되었다면 403에러를 반환한다. 만약 등록되지 않았다면, 즉 회원가입이 가능한 상태이면 비밀번호를 해쉬화한 뒤 저장을 완료한다.
module 레이어
// cats.module
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
import { MongooseModule } from '@nestjs/mongoose';
import { Cat, CatSchema } from './cats.schema';
@Module({
// Schema 사용을 위한 등록import
imports: [MongooseModule.forFeature([{ name: Cat.name, schema: CatSchema }])],
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService], //캡슐화된 것을 공개
})
export class CatsModule {}
참고로 몽구스모듈을 의존성 주입하려면 모듈에 등록해주어야 한다.
테스트
잘 작동된다.
password는 해시화되었고, createdAt, updatedAt는 timpestamp 옵션으로 인해 반환된다.
실제 DB에도 정상적으로 저장되었다.
가상 필드 생성하여 엔티티 일부만 리턴하도록 조작하기
password는 반환되면 안되니 숨겨야 한다. 숨기기 보다는 password만 제외한 나머지 필드들만 반환하는 가상의 엔티티를 생성해준다고 보면 된다
// cats 폴더 내 cats.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
import { Document, SchemaOptions } from 'mongoose';
const options: SchemaOptions = {
timestamps: true,
};
@Schema(options)
export class Cat extends Document {
@Prop({
required: true,
unique: true,
})
@IsEmail()
@IsNotEmpty()
email: string;
@Prop({
required: true,
})
@IsString()
@IsNotEmpty()
name: string;
@Prop({
required: true,
})
@IsString()
@IsNotEmpty()
password: string;
@Prop()
@IsString()
imgUrl: string;
// 가상 엔티티 추가
readonly readOnlyData: { id: string; email: string; name: string };
}
// Cat 클래스를 CatSchema 스키마로 생성
export const CatSchema = SchemaFactory.createForClass(Cat);
// virtual 메소드로 가상 엔티티 생성. 불필요한 password는 숨김처리하기 위함
CatSchema.virtual('readOnlyData').get(function (this: Cat) {
return {
id: this.id,
email: this.email,
name: this.name,
};
});
하단에 virtual 메소드로 생성한 후 Cat 클래스 내에 추가해준다. 여기서 this는 db 객체를 의미한다.
// cats.service
...
async signUp(body: CatRequestDto) {
const { email, name, password } = body;
const isCatExist = await this.catModel.exists({ email });
if (isCatExist) {
throw new UnauthorizedException('해당하는 고양이는 이미 존재합니다.');
}
// 비밀번호 해시화
const hashedPassword = await bcrypt.hash(password, 10);
// DB 저장
const cat = await this.catModel.create({
email,
name,
password: hashedPassword,
});
// virtual field로 반환하여 비밀번호 숨김처리
return cat.readOnlyData;
}
}
서비스 레이어에서 readOnlyData 라는 가상필드를 리턴하도록 변경했다.
확인해보면 비밀번호를 리턴하지 않음을 알 수 있다.
728x90
'Research > Nest.js' 카테고리의 다른 글
nestjs_CORS 허용하기 (0) | 2023.04.05 |
---|---|
nestjs_swagger 적용 및 dto OOP적 리팩토링 (0) | 2023.04.05 |
nestjs_DTO 만들고 붙이기 (0) | 2023.04.05 |
nestjs_mongoose 스키마 설계 후 class-validator 적용 (0) | 2023.04.05 |
nestjs_배포 환경에 따른 mongoDB 로깅 설정 (0) | 2023.04.05 |
댓글