email 보내는 api 가 구현됐다면 email로 인증 코드를 보내 인증하는 기능을 구현하고자 한다.
인증 코드를 일정 시간 보관하는데 redis를 사용한다.
패키지 설치 명령어
npm install cache-manager@^4.1.0 cache-manager-redis-store@^2.0
환경변수 (.env)에
REDIS_HOST
REDIS_PORT
REDIS_USER
REDIS_PASSWORD
REDIS_TTL 항목을 추가하고 app.module에 유효성검사를 추가해준다.
redis cloud 회원가입을 하고 subscription을 생성한다(무료 버전). 이때 region은 tokyo로 설정한다.
REDIS_HOST 값으로 Public endpoint 값( :기준 왼쪽 )과
REDIS_PORT 값 ( :기준 오른쪽) 을 입력하고
Security 항목에 REDIS_USER 값과 REDIS_PASSWORD 값이 있으니 환경변수에 입력한다. REDIS_TTL은 생성된 데이터 유지 시간이다.
환경변수 세팅이 끝나면 redis modul을 생성해주자 (database 모듈을 생성했을때와 같은 과정)
//redis.module.ts파일
@Module({
imports: [
CachModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (cfg: ConfigService) => ({
store: redisStore,
host: cfg.get('REDIS_HOST'),
port: cfg.get('REDIS_PORT'),
user: cfg.get('REDIS_USER'),
password: cfg.get('REDIS_PASSWORD'),
ttl: cfg.get('REDIS_TTL')
}),
isGlobal: true, //CachModule을 전역적으로 사용할지 여부를 결정 true일경우 모든 module에서 접근 가능
}),
],
})
export class RedisModule {}
해당 모듈을 app.module에 import 시켜준다.(전역에서 사용할 예정이기 때문)
redis는 이메일 인증에 사용할 목적이며 이메일과 인증코드 두가지 정보를 사용한다. 때문에 user 리소스에 관련 dto를 생성해주어야함
//verification.email.dto.ts 파일
export class VerificationEmailDto {
email: string;
code: string;
}
다음은 인증코드를 메일로 보내는 api를 구현해보자
//auth.service.ts파일
constructor(
+ //CHCHE_MANAGER 는 nestjs/common/cache 패키지, Cache 는 cache-manager 패키지로 부터 가져온다.
@Inject(CACHE_MANAGER) private cacheManager: Cache,
){}
generateOTP() {
let OTP = '';
for (let i = 1; i<=6; i++){ //6자리 code 생성
OTP += Math.floor(Math.random() * 10); //Math.random() 매소드는 0<x<1 난수를 생성
}
return OTP;
}
async sendEmail(email: string): Promise<boolean>{ //이메일로 인증코드를 보내면서 해당 이메일에 대한 인증코드를 redis에 임시로 저장
const generatenumber = this.generateOTP();
await this.emailService.sendMail({
to: email,
subject: '이메일 인증코드',
text: `이메일 인증코드 ${generatenumber}`,
});
await this.cacheManager.set(email, generatenumber);
}
async confirmEmailVerification(
verificationEmailDto: VerificationEmailDto
): Promise<boolean> {
const eamilCode = await this.cacheManager.get(verificationEmailDto.email);
if(emailCode !== verificationEmailDto.code) {
throw new HttpException('worng code provided', HttpStatus.CONFLICT);
}
return true;
}
//auth.controller.ts 파일
+
@Post('verify/email')
async verificationEmail(
@Body() verificationEmailDto: VerificationEmailDto
): Promise<boolean> {
return await this.authService.confirmEmailVerification( verificationEmailDto );
}