|
1 | 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */ |
2 | | -import { Injectable } from '@nestjs/common'; |
| 2 | +import { Injectable, Logger } from '@nestjs/common'; |
3 | 3 | import { JwtService } from '@nestjs/jwt'; |
4 | 4 |
|
5 | 5 | import { ErrorAuth, ErrorUser } from '../../common/constants/errors'; |
@@ -39,6 +39,8 @@ import { ApiKeyRepository } from './apikey.repository'; |
39 | 39 |
|
40 | 40 | @Injectable() |
41 | 41 | export class AuthService { |
| 42 | + private readonly logger = new Logger(AuthService.name); |
| 43 | + |
42 | 44 | constructor( |
43 | 45 | private readonly jwtService: JwtService, |
44 | 46 | private readonly userService: UserService, |
@@ -80,19 +82,7 @@ export class AuthService { |
80 | 82 | } |
81 | 83 |
|
82 | 84 | public async signup(data: UserCreateDto, ip?: string): Promise<UserEntity> { |
83 | | - if ( |
84 | | - !( |
85 | | - await verifyToken( |
86 | | - this.authConfigService.hcaptchaProtectionUrl, |
87 | | - this.authConfigService.hCaptchaSiteKey, |
88 | | - this.authConfigService.hCaptchaSecret, |
89 | | - data.hCaptchaToken, |
90 | | - ip, |
91 | | - ) |
92 | | - ).success |
93 | | - ) { |
94 | | - throw new ForbiddenError(ErrorAuth.InvalidCaptchaToken); |
95 | | - } |
| 85 | + await this.ensureCaptchaValid(data.hCaptchaToken, ip); |
96 | 86 | const storedUser = await this.userRepository.findByEmail(data.email); |
97 | 87 | if (storedUser) { |
98 | 88 | throw new ConflictError(ErrorUser.DuplicatedEmail); |
@@ -185,19 +175,7 @@ export class AuthService { |
185 | 175 | data: ForgotPasswordDto, |
186 | 176 | ip?: string, |
187 | 177 | ): Promise<void> { |
188 | | - if ( |
189 | | - !( |
190 | | - await verifyToken( |
191 | | - this.authConfigService.hcaptchaProtectionUrl, |
192 | | - this.authConfigService.hCaptchaSiteKey, |
193 | | - this.authConfigService.hCaptchaSecret, |
194 | | - data.hCaptchaToken, |
195 | | - ip, |
196 | | - ) |
197 | | - ).success |
198 | | - ) { |
199 | | - throw new ForbiddenError(ErrorAuth.InvalidCaptchaToken); |
200 | | - } |
| 178 | + await this.ensureCaptchaValid(data.hCaptchaToken, ip); |
201 | 179 | const userEntity = await this.userRepository.findByEmail(data.email); |
202 | 180 |
|
203 | 181 | if (!userEntity) { |
@@ -245,19 +223,7 @@ export class AuthService { |
245 | 223 | data: RestorePasswordDto, |
246 | 224 | ip?: string, |
247 | 225 | ): Promise<void> { |
248 | | - if ( |
249 | | - !( |
250 | | - await verifyToken( |
251 | | - this.authConfigService.hcaptchaProtectionUrl, |
252 | | - this.authConfigService.hCaptchaSiteKey, |
253 | | - this.authConfigService.hCaptchaSecret, |
254 | | - data.hCaptchaToken, |
255 | | - ip, |
256 | | - ) |
257 | | - ).success |
258 | | - ) { |
259 | | - throw new ForbiddenError(ErrorAuth.InvalidCaptchaToken); |
260 | | - } |
| 226 | + await this.ensureCaptchaValid(data.hCaptchaToken, ip); |
261 | 227 |
|
262 | 228 | const tokenEntity = await this.tokenRepository.findOneByUuidAndType( |
263 | 229 | data.token, |
@@ -426,4 +392,24 @@ export class AuthService { |
426 | 392 |
|
427 | 393 | return null; |
428 | 394 | } |
| 395 | + |
| 396 | + private async ensureCaptchaValid(token: string, ip?: string): Promise<void> { |
| 397 | + const verification = await verifyToken( |
| 398 | + this.authConfigService.hcaptchaProtectionUrl, |
| 399 | + this.authConfigService.hCaptchaSiteKey, |
| 400 | + this.authConfigService.hCaptchaSecret, |
| 401 | + token, |
| 402 | + ip, |
| 403 | + ); |
| 404 | + |
| 405 | + if (verification.success) { |
| 406 | + return; |
| 407 | + } |
| 408 | + |
| 409 | + this.logger.error(ErrorAuth.InvalidCaptchaToken, { |
| 410 | + error: verification.error, |
| 411 | + }); |
| 412 | + |
| 413 | + throw new ForbiddenError(ErrorAuth.InvalidCaptchaToken); |
| 414 | + } |
429 | 415 | } |
0 commit comments