feat: 后端也添加了写了一半的人机验证模块
This commit is contained in:
@@ -12,6 +12,7 @@ import { BlogModule } from './blog/blog.module';
|
|||||||
import { AdminModule } from './admin/admin.module';
|
import { AdminModule } from './admin/admin.module';
|
||||||
import { OssModule } from './oss/oss.module';
|
import { OssModule } from './oss/oss.module';
|
||||||
import { ThrottlerModule } from '@nestjs/throttler';
|
import { ThrottlerModule } from '@nestjs/throttler';
|
||||||
|
import { CaptchaModule } from './captcha/captcha.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -43,6 +44,7 @@ import { ThrottlerModule } from '@nestjs/throttler';
|
|||||||
BlogModule,
|
BlogModule,
|
||||||
AdminModule,
|
AdminModule,
|
||||||
OssModule,
|
OssModule,
|
||||||
|
CaptchaModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
|
|||||||
18
apps/backend/src/captcha/captcha.controller.spec.ts
Normal file
18
apps/backend/src/captcha/captcha.controller.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { CaptchaController } from './captcha.controller';
|
||||||
|
|
||||||
|
describe('CaptchaController', () => {
|
||||||
|
let controller: CaptchaController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [CaptchaController],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get<CaptchaController>(CaptchaController);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
10
apps/backend/src/captcha/captcha.controller.ts
Normal file
10
apps/backend/src/captcha/captcha.controller.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { Controller, Get } from '@nestjs/common';
|
||||||
|
import { GetCaptchaDto } from './dto/get-captcha.dto';
|
||||||
|
|
||||||
|
@Controller('captcha')
|
||||||
|
export class CaptchaController {
|
||||||
|
@Get()
|
||||||
|
async getCaptcha(dto: GetCaptchaDto) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
11
apps/backend/src/captcha/captcha.module.ts
Normal file
11
apps/backend/src/captcha/captcha.module.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { CaptchaService } from './captcha.service';
|
||||||
|
import { CaptchaController } from './captcha.controller';
|
||||||
|
import { CaptchaRateLimitService } from './service/rate-limit';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [CaptchaService, CaptchaRateLimitService],
|
||||||
|
controllers: [CaptchaController],
|
||||||
|
imports: [],
|
||||||
|
})
|
||||||
|
export class CaptchaModule { }
|
||||||
18
apps/backend/src/captcha/captcha.service.spec.ts
Normal file
18
apps/backend/src/captcha/captcha.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { CaptchaService } from './captcha.service';
|
||||||
|
|
||||||
|
describe('CaptchaService', () => {
|
||||||
|
let service: CaptchaService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [CaptchaService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<CaptchaService>(CaptchaService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
27
apps/backend/src/captcha/captcha.service.ts
Normal file
27
apps/backend/src/captcha/captcha.service.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { ErrorCode } from 'src/common/constants/error-codes';
|
||||||
|
import { BusinessException } from 'src/common/exceptions/business.exception';
|
||||||
|
|
||||||
|
export enum CaptchaContext {
|
||||||
|
SEND_SMS = 'send_sms',
|
||||||
|
PASSKEY = 'passkey',
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CaptchaService {
|
||||||
|
public async generate(context: CaptchaContext, ip: string, userId?: string) {
|
||||||
|
await this.checkRateLimit(ip, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async verify(token: string, ip: string, userId?: string) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkRateLimit(ip: string, context: CaptchaContext) {
|
||||||
|
/** @todo */
|
||||||
|
throw new BusinessException({
|
||||||
|
code: ErrorCode.CAPTCHA_RARE_LIMIT,
|
||||||
|
message: '服务器处理不过来了,过会儿再试试吧',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
16
apps/backend/src/captcha/dto/get-captcha.dto.ts
Normal file
16
apps/backend/src/captcha/dto/get-captcha.dto.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { IsEnum, IsOptional, IsUUID } from "class-validator";
|
||||||
|
|
||||||
|
export enum CaptchaContext {
|
||||||
|
SEND_SMS = 'send_sms',
|
||||||
|
PASSKEY = 'passkey',
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GetCaptchaDto {
|
||||||
|
|
||||||
|
@IsEnum(CaptchaContext, { message: '无效的context' })
|
||||||
|
context: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsUUID('4', { message: 'userId不合法' })
|
||||||
|
userId?: string;
|
||||||
|
}
|
||||||
3
apps/backend/src/captcha/service/rate-limit.ts
Normal file
3
apps/backend/src/captcha/service/rate-limit.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export class CaptchaRateLimitService {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -29,8 +29,7 @@ export const ErrorCode = {
|
|||||||
BLOG_PERMISSION_DENIED: -3002,
|
BLOG_PERMISSION_DENIED: -3002,
|
||||||
|
|
||||||
// 验证模块(4000 ~ 4999)
|
// 验证模块(4000 ~ 4999)
|
||||||
VERIFICATION_CODE_EXPIRED: -4001,
|
CAPTCHA_RARE_LIMIT: -4001,
|
||||||
VERIFICATION_CODE_INCORRECT: -4002,
|
|
||||||
|
|
||||||
// 通知模块(5000 ~ 5999)
|
// 通知模块(5000 ~ 5999)
|
||||||
NOTIFICATION_SEND_FAILED: -5001,
|
NOTIFICATION_SEND_FAILED: -5001,
|
||||||
|
|||||||
Reference in New Issue
Block a user