mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-31 21:59:10 +08:00
feat: rate limiter (#4011)
This commit is contained in:
@@ -42,8 +42,6 @@ export class MailService {
|
||||
};
|
||||
}
|
||||
) {
|
||||
console.log('invitationInfo', invitationInfo);
|
||||
|
||||
const buttonUrl = `${this.config.baseUrl}/invite/${inviteId}`;
|
||||
const workspaceAvatar = invitationInfo.workspace.avatar;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
Query,
|
||||
Req,
|
||||
Res,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { hash, verify } from '@node-rs/argon2';
|
||||
import type { User } from '@prisma/client';
|
||||
@@ -19,6 +20,7 @@ import { AuthHandler } from 'next-auth/core';
|
||||
|
||||
import { Config } from '../../config';
|
||||
import { PrismaService } from '../../prisma/service';
|
||||
import { CloudThrottlerGuard, Throttle } from '../../throttler';
|
||||
import { NextAuthOptionsProvide } from './next-auth-options';
|
||||
import { AuthService } from './service';
|
||||
|
||||
@@ -41,6 +43,8 @@ export class NextAuthController {
|
||||
this.callbackSession = nextAuthOptions.callbacks!.session;
|
||||
}
|
||||
|
||||
@UseGuards(CloudThrottlerGuard)
|
||||
@Throttle(20, 60)
|
||||
@All('*')
|
||||
async auth(
|
||||
@Req() req: Request,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ForbiddenException } from '@nestjs/common';
|
||||
import { ForbiddenException, UseGuards } from '@nestjs/common';
|
||||
import {
|
||||
Args,
|
||||
Context,
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import type { Request } from 'express';
|
||||
|
||||
import { Config } from '../../config';
|
||||
import { CloudThrottlerGuard, Throttle } from '../../throttler';
|
||||
import { UserType } from '../users/resolver';
|
||||
import { CurrentUser } from './guard';
|
||||
import { AuthService } from './service';
|
||||
@@ -25,6 +26,13 @@ export class TokenType {
|
||||
refresh!: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auth resolver
|
||||
* Token rate limit: 20 req/m
|
||||
* Sign up/in rate limit: 10 req/m
|
||||
* Other rate limit: 5 req/m
|
||||
*/
|
||||
@UseGuards(CloudThrottlerGuard)
|
||||
@Resolver(() => UserType)
|
||||
export class AuthResolver {
|
||||
constructor(
|
||||
@@ -32,6 +40,7 @@ export class AuthResolver {
|
||||
private auth: AuthService
|
||||
) {}
|
||||
|
||||
@Throttle(20, 60)
|
||||
@ResolveField(() => TokenType)
|
||||
token(@CurrentUser() currentUser: UserType, @Parent() user: UserType) {
|
||||
if (user.id !== currentUser.id) {
|
||||
@@ -44,6 +53,7 @@ export class AuthResolver {
|
||||
};
|
||||
}
|
||||
|
||||
@Throttle(10, 60)
|
||||
@Mutation(() => UserType)
|
||||
async signUp(
|
||||
@Context() ctx: { req: Request },
|
||||
@@ -56,6 +66,7 @@ export class AuthResolver {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Throttle(10, 60)
|
||||
@Mutation(() => UserType)
|
||||
async signIn(
|
||||
@Context() ctx: { req: Request },
|
||||
@@ -67,6 +78,7 @@ export class AuthResolver {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Throttle(5, 60)
|
||||
@Mutation(() => UserType)
|
||||
async changePassword(
|
||||
@Context() ctx: { req: Request },
|
||||
@@ -78,6 +90,7 @@ export class AuthResolver {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Throttle(5, 60)
|
||||
@Mutation(() => UserType)
|
||||
async changeEmail(
|
||||
@Context() ctx: { req: Request },
|
||||
@@ -89,6 +102,7 @@ export class AuthResolver {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Throttle(5, 60)
|
||||
@Mutation(() => Boolean)
|
||||
async sendChangePasswordEmail(
|
||||
@Args('email') email: string,
|
||||
@@ -99,6 +113,7 @@ export class AuthResolver {
|
||||
return !res.rejected.length;
|
||||
}
|
||||
|
||||
@Throttle(5, 60)
|
||||
@Mutation(() => Boolean)
|
||||
async sendSetPasswordEmail(
|
||||
@Args('email') email: string,
|
||||
@@ -109,6 +124,7 @@ export class AuthResolver {
|
||||
return !res.rejected.length;
|
||||
}
|
||||
|
||||
@Throttle(5, 60)
|
||||
@Mutation(() => Boolean)
|
||||
async sendChangeEmail(
|
||||
@Args('email') email: string,
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
BadRequestException,
|
||||
ForbiddenException,
|
||||
HttpException,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
Args,
|
||||
@@ -19,6 +20,7 @@ import GraphQLUpload from 'graphql-upload/GraphQLUpload.mjs';
|
||||
|
||||
import { Config } from '../../config';
|
||||
import { PrismaService } from '../../prisma/service';
|
||||
import { CloudThrottlerGuard, Throttle } from '../../throttler';
|
||||
import type { FileUpload } from '../../types';
|
||||
import { Auth, CurrentUser, Public } from '../auth/guard';
|
||||
import { StorageService } from '../storage/storage.service';
|
||||
@@ -69,6 +71,11 @@ export class AddToNewFeaturesWaitingList {
|
||||
type!: NewFeaturesKind;
|
||||
}
|
||||
|
||||
/**
|
||||
* User resolver
|
||||
* All op rate limit: 10 req/m
|
||||
*/
|
||||
@UseGuards(CloudThrottlerGuard)
|
||||
@Auth()
|
||||
@Resolver(() => UserType)
|
||||
export class UserResolver {
|
||||
@@ -78,6 +85,7 @@ export class UserResolver {
|
||||
private readonly config: Config
|
||||
) {}
|
||||
|
||||
@Throttle(10, 60)
|
||||
@Query(() => UserType, {
|
||||
name: 'currentUser',
|
||||
description: 'Get current user',
|
||||
@@ -100,6 +108,7 @@ export class UserResolver {
|
||||
};
|
||||
}
|
||||
|
||||
@Throttle(10, 60)
|
||||
@Query(() => UserType, {
|
||||
name: 'user',
|
||||
description: 'Get user by email',
|
||||
@@ -135,6 +144,7 @@ export class UserResolver {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Throttle(10, 60)
|
||||
@Mutation(() => UserType, {
|
||||
name: 'uploadAvatar',
|
||||
description: 'Upload user avatar',
|
||||
@@ -155,6 +165,7 @@ export class UserResolver {
|
||||
});
|
||||
}
|
||||
|
||||
@Throttle(10, 60)
|
||||
@Mutation(() => DeleteAccount)
|
||||
async deleteAccount(@CurrentUser() user: UserType): Promise<DeleteAccount> {
|
||||
await this.prisma.user.delete({
|
||||
@@ -172,6 +183,7 @@ export class UserResolver {
|
||||
};
|
||||
}
|
||||
|
||||
@Throttle(10, 60)
|
||||
@Mutation(() => AddToNewFeaturesWaitingList)
|
||||
async addToNewFeaturesWaitingList(
|
||||
@CurrentUser() user: UserType,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import type { Storage } from '@affine/storage';
|
||||
import { ForbiddenException, Inject, NotFoundException } from '@nestjs/common';
|
||||
import {
|
||||
ForbiddenException,
|
||||
Inject,
|
||||
NotFoundException,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
Args,
|
||||
Field,
|
||||
@@ -24,6 +29,7 @@ import { applyUpdate, Doc } from 'yjs';
|
||||
|
||||
import { PrismaService } from '../../prisma';
|
||||
import { StorageProvide } from '../../storage';
|
||||
import { CloudThrottlerGuard, Throttle } from '../../throttler';
|
||||
import type { FileUpload } from '../../types';
|
||||
import { Auth, CurrentUser, Public } from '../auth';
|
||||
import { MailService } from '../auth/mailer';
|
||||
@@ -113,6 +119,12 @@ export class UpdateWorkspaceInput extends PickType(
|
||||
id!: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workspace resolver
|
||||
* Public apis rate limit: 10 req/m
|
||||
* Other rate limit: 120 req/m
|
||||
*/
|
||||
@UseGuards(CloudThrottlerGuard)
|
||||
@Auth()
|
||||
@Resolver(() => WorkspaceType)
|
||||
export class WorkspaceResolver {
|
||||
@@ -258,10 +270,11 @@ export class WorkspaceResolver {
|
||||
});
|
||||
}
|
||||
|
||||
@Throttle(10, 30)
|
||||
@Public()
|
||||
@Query(() => WorkspaceType, {
|
||||
description: 'Get public workspace by id',
|
||||
})
|
||||
@Public()
|
||||
async publicWorkspace(@Args('id') id: string) {
|
||||
const workspace = await this.prisma.workspace.findUnique({
|
||||
where: { id },
|
||||
@@ -463,6 +476,7 @@ export class WorkspaceResolver {
|
||||
}
|
||||
}
|
||||
|
||||
@Throttle(10, 30)
|
||||
@Public()
|
||||
@Query(() => InvitationType, {
|
||||
description: 'Update workspace',
|
||||
|
||||
Reference in New Issue
Block a user