feat: introducing rate-limiting on queries, mutations and most of the REST endpoints (HBE-111) (#46)
* feat: rate-limiting guard added and configured in app module * feat: rate-limit annotation added in controllers and resolvers (query, mutation, not subscription) * docs: added comments
This commit is contained in:
@@ -5,6 +5,10 @@ DATABASE_URL=postgresql://postgres:testpass@dev-db:5432/hoppscotch
|
||||
MAILER_SMTP_URL="smtps://user@domain.com:pass@smtp.domain.com"
|
||||
MAILER_ADDRESS_FROM='"From Name Here" <from@example.com>'
|
||||
|
||||
# Rate Limit Config
|
||||
RATE_LIMIT_TTL=60 # In seconds
|
||||
RATE_LIMIT_MAX=100 # Max requests per IP
|
||||
|
||||
# Auth Tokens Config
|
||||
JWT_SECRET='add some secret here'
|
||||
TOKEN_SALT_COMPLEXITY=10
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"@nestjs/jwt": "^10.0.1",
|
||||
"@nestjs/passport": "^9.0.0",
|
||||
"@nestjs/platform-express": "^9.2.1",
|
||||
"@nestjs/throttler": "^4.0.0",
|
||||
"@prisma/client": "^4.7.1",
|
||||
"apollo-server-express": "^3.11.1",
|
||||
"apollo-server-plugin-base": "^3.7.1",
|
||||
|
||||
@@ -18,6 +18,7 @@ import { AdminModule } from './admin/admin.module';
|
||||
import { UserCollectionModule } from './user-collection/user-collection.module';
|
||||
import { ShortcodeModule } from './shortcode/shortcode.module';
|
||||
import { COOKIES_NOT_FOUND } from './errors';
|
||||
import { ThrottlerModule } from '@nestjs/throttler';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -60,6 +61,10 @@ import { COOKIES_NOT_FOUND } from './errors';
|
||||
}),
|
||||
driver: ApolloDriver,
|
||||
}),
|
||||
ThrottlerModule.forRoot({
|
||||
ttl: +process.env.RATE_LIMIT_TTL,
|
||||
limit: +process.env.RATE_LIMIT_MAX,
|
||||
}),
|
||||
UserModule,
|
||||
AuthModule,
|
||||
AdminModule,
|
||||
|
||||
@@ -2,8 +2,6 @@ import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Post,
|
||||
Req,
|
||||
Request,
|
||||
@@ -20,11 +18,14 @@ import { JwtAuthGuard } from './guards/jwt-auth.guard';
|
||||
import { GqlUser } from 'src/decorators/gql-user.decorator';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
import { RTCookie } from 'src/decorators/rt-cookie.decorator';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { authCookieHandler, throwHTTPErr } from './helper';
|
||||
import { GoogleSSOGuard } from './guards/google-sso.guard';
|
||||
import { GithubSSOGuard } from './guards/github-sso.guard';
|
||||
import { MicrosoftSSOGuard } from './guards/microsoft-sso-.guard';
|
||||
import { ThrottlerBehindProxyGuard } from 'src/guards/throttler-behind-proxy.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(ThrottlerBehindProxyGuard)
|
||||
@Controller({ path: 'auth', version: '1' })
|
||||
export class AuthController {
|
||||
constructor(private authService: AuthService) {}
|
||||
@@ -82,6 +83,7 @@ export class AuthController {
|
||||
* @see https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow#how-it-works
|
||||
*/
|
||||
@Get('google/callback')
|
||||
@SkipThrottle()
|
||||
@UseGuards(GoogleSSOGuard)
|
||||
async googleAuthRedirect(@Request() req, @Res() res) {
|
||||
const authTokens = await this.authService.generateAuthTokens(req.user.uid);
|
||||
@@ -106,6 +108,7 @@ export class AuthController {
|
||||
* @see https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow#how-it-works
|
||||
*/
|
||||
@Get('github/callback')
|
||||
@SkipThrottle()
|
||||
@UseGuards(GithubSSOGuard)
|
||||
async githubAuthRedirect(@Request() req, @Res() res) {
|
||||
const authTokens = await this.authService.generateAuthTokens(req.user.uid);
|
||||
@@ -130,6 +133,7 @@ export class AuthController {
|
||||
* @see https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow#how-it-works
|
||||
*/
|
||||
@Get('microsoft/callback')
|
||||
@SkipThrottle()
|
||||
@UseGuards(MicrosoftSSOGuard)
|
||||
async microsoftAuthRedirect(@Request() req, @Res() res) {
|
||||
const authTokens = await this.authService.generateAuthTokens(req.user.uid);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { ExecutionContext, Injectable } from '@nestjs/common';
|
||||
import { GqlExecutionContext } from '@nestjs/graphql';
|
||||
import { ThrottlerGuard } from '@nestjs/throttler';
|
||||
|
||||
@Injectable()
|
||||
export class GqlThrottlerGuard extends ThrottlerGuard {
|
||||
getRequestResponse(context: ExecutionContext) {
|
||||
const gqlCtx = GqlExecutionContext.create(context);
|
||||
const ctx = gqlCtx.getContext();
|
||||
return { req: ctx.req, res: ctx.res };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ThrottlerGuard } from '@nestjs/throttler';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class ThrottlerBehindProxyGuard extends ThrottlerGuard {
|
||||
protected getTracker(req: Record<string, any>): string {
|
||||
return req.ips.length ? req.ips[0] : req.ip; // individualize IP extraction to meet your own needs
|
||||
// learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For#directives
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,10 @@ import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
import { AuthUser } from '../types/AuthUser';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { PaginationArgs } from 'src/types/input-types.args';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => Shortcode)
|
||||
export class ShortcodeResolver {
|
||||
constructor(
|
||||
@@ -105,6 +108,7 @@ export class ShortcodeResolver {
|
||||
description: 'Listen for shortcode creation',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
myShortcodesCreated(@GqlUser() user: AuthUser) {
|
||||
return this.pubsub.asyncIterator(`shortcode/${user.uid}/created`);
|
||||
@@ -114,6 +118,7 @@ export class ShortcodeResolver {
|
||||
description: 'Listen for shortcode deletion',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
myShortcodesRevoked(@GqlUser() user: AuthUser): AsyncIterator<Shortcode> {
|
||||
return this.pubsub.asyncIterator(`shortcode/${user.uid}/revoked`);
|
||||
|
||||
@@ -29,7 +29,10 @@ import {
|
||||
} from './input-type.args';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { throwErr } from 'src/utils';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => TeamCollection)
|
||||
export class TeamCollectionResolver {
|
||||
constructor(
|
||||
@@ -312,6 +315,7 @@ export class TeamCollectionResolver {
|
||||
TeamMemberRole.EDITOR,
|
||||
TeamMemberRole.VIEWER,
|
||||
)
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
teamCollectionAdded(
|
||||
@Args({
|
||||
@@ -333,6 +337,7 @@ export class TeamCollectionResolver {
|
||||
TeamMemberRole.EDITOR,
|
||||
TeamMemberRole.VIEWER,
|
||||
)
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
teamCollectionUpdated(
|
||||
@Args({
|
||||
@@ -354,6 +359,7 @@ export class TeamCollectionResolver {
|
||||
TeamMemberRole.EDITOR,
|
||||
TeamMemberRole.VIEWER,
|
||||
)
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
teamCollectionRemoved(
|
||||
@Args({
|
||||
@@ -375,6 +381,7 @@ export class TeamCollectionResolver {
|
||||
TeamMemberRole.EDITOR,
|
||||
TeamMemberRole.VIEWER,
|
||||
)
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
teamCollectionMoved(
|
||||
@Args({
|
||||
@@ -396,6 +403,7 @@ export class TeamCollectionResolver {
|
||||
TeamMemberRole.EDITOR,
|
||||
TeamMemberRole.VIEWER,
|
||||
)
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
collectionOrderUpdated(
|
||||
@Args({
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { UseGuards } from '@nestjs/common';
|
||||
import { Resolver, Mutation, Args, Subscription, ID } from '@nestjs/graphql';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
import { pipe } from 'fp-ts/function';
|
||||
import * as TE from 'fp-ts/TaskEither';
|
||||
import { GqlAuthGuard } from 'src/guards/gql-auth.guard';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
import { RequiresTeamRole } from 'src/team/decorators/requires-team-role.decorator';
|
||||
import { GqlTeamMemberGuard } from 'src/team/guards/gql-team-member.guard';
|
||||
@@ -12,6 +14,7 @@ import { GqlTeamEnvTeamGuard } from './gql-team-env-team.guard';
|
||||
import { TeamEnvironment } from './team-environments.model';
|
||||
import { TeamEnvironmentsService } from './team-environments.service';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => 'TeamEnvironment')
|
||||
export class TeamEnvironmentsResolver {
|
||||
constructor(
|
||||
@@ -144,6 +147,7 @@ export class TeamEnvironmentsResolver {
|
||||
description: 'Listen for Team Environment Updates',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.OWNER,
|
||||
@@ -165,6 +169,7 @@ export class TeamEnvironmentsResolver {
|
||||
description: 'Listen for Team Environment Creation Messages',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.OWNER,
|
||||
@@ -186,6 +191,7 @@ export class TeamEnvironmentsResolver {
|
||||
description: 'Listen for Team Environment Deletion Messages',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.OWNER,
|
||||
|
||||
@@ -34,7 +34,10 @@ import { TeamInviteViewerGuard } from './team-invite-viewer.guard';
|
||||
import { TeamInviteTeamOwnerGuard } from './team-invite-team-owner.guard';
|
||||
import { UserService } from 'src/user/user.service';
|
||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => TeamInvitation)
|
||||
export class TeamInvitationResolver {
|
||||
constructor(
|
||||
@@ -199,6 +202,7 @@ export class TeamInvitationResolver {
|
||||
description: 'Listens to when a Team Invitation is added',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.OWNER,
|
||||
@@ -220,6 +224,7 @@ export class TeamInvitationResolver {
|
||||
description: 'Listens to when a Team Invitation is removed',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.OWNER,
|
||||
|
||||
@@ -30,7 +30,10 @@ import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import * as O from 'fp-ts/Option';
|
||||
import { throwErr } from 'src/utils';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => TeamRequest)
|
||||
export class TeamRequestResolver {
|
||||
constructor(
|
||||
@@ -242,6 +245,7 @@ export class TeamRequestResolver {
|
||||
description: 'Emits when a new request is added to a team',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.VIEWER,
|
||||
@@ -263,6 +267,7 @@ export class TeamRequestResolver {
|
||||
description: 'Emitted when a request has been updated',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.VIEWER,
|
||||
@@ -285,6 +290,7 @@ export class TeamRequestResolver {
|
||||
'Emitted when a request has been deleted. Only the id of the request is emitted.',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.VIEWER,
|
||||
@@ -307,6 +313,7 @@ export class TeamRequestResolver {
|
||||
'Emitted when a requests position has been changed in its collection',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.VIEWER,
|
||||
@@ -329,6 +336,7 @@ export class TeamRequestResolver {
|
||||
'Emitted when a request has been moved from one collection into another',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
@RequiresTeamRole(
|
||||
TeamMemberRole.VIEWER,
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
ID,
|
||||
} from '@nestjs/graphql';
|
||||
import { TeamService } from './team.service';
|
||||
import { User } from '../user/user.model';
|
||||
import { GqlAuthGuard } from '../guards/gql-auth.guard';
|
||||
import { GqlUser } from '../decorators/gql-user.decorator';
|
||||
import { UseGuards } from '@nestjs/common';
|
||||
@@ -21,7 +20,10 @@ import { PubSubService } from '../pubsub/pubsub.service';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { throwErr } from 'src/utils';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => Team)
|
||||
export class TeamResolver {
|
||||
constructor(
|
||||
@@ -271,6 +273,7 @@ export class TeamResolver {
|
||||
TeamMemberRole.EDITOR,
|
||||
TeamMemberRole.VIEWER,
|
||||
)
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
teamMemberAdded(
|
||||
@Args({
|
||||
@@ -293,6 +296,7 @@ export class TeamResolver {
|
||||
TeamMemberRole.EDITOR,
|
||||
TeamMemberRole.VIEWER,
|
||||
)
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
teamMemberUpdated(
|
||||
@Args({
|
||||
@@ -315,6 +319,7 @@ export class TeamResolver {
|
||||
TeamMemberRole.EDITOR,
|
||||
TeamMemberRole.VIEWER,
|
||||
)
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||
teamMemberRemoved(
|
||||
@Args({
|
||||
|
||||
@@ -31,7 +31,10 @@ import {
|
||||
} from './input-type.args';
|
||||
import { ReqType } from 'src/types/RequestTypes';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => UserCollection)
|
||||
export class UserCollectionResolver {
|
||||
constructor(
|
||||
@@ -352,6 +355,7 @@ export class UserCollectionResolver {
|
||||
description: 'Listen for User Collection Creation',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userCollectionCreated(@GqlUser() user: AuthUser) {
|
||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/created`);
|
||||
@@ -361,6 +365,7 @@ export class UserCollectionResolver {
|
||||
description: 'Listen to when a User Collection has been updated.',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userCollectionUpdated(@GqlUser() user: AuthUser) {
|
||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/updated`);
|
||||
@@ -370,6 +375,7 @@ export class UserCollectionResolver {
|
||||
description: 'Listen to when a User Collection has been deleted',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userCollectionRemoved(@GqlUser() user: AuthUser) {
|
||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/deleted`);
|
||||
@@ -379,6 +385,7 @@ export class UserCollectionResolver {
|
||||
description: 'Listen to when a User Collection has been moved',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userCollectionMoved(@GqlUser() user: AuthUser) {
|
||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/moved`);
|
||||
@@ -388,6 +395,7 @@ export class UserCollectionResolver {
|
||||
description: 'Listen to when a User Collections position has changed',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userCollectionOrderUpdated(@GqlUser() user: AuthUser) {
|
||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/order_updated`);
|
||||
|
||||
@@ -8,7 +8,10 @@ import { User } from '../user/user.model';
|
||||
import { UserEnvironmentsService } from './user-environments.service';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { throwErr } from 'src/utils';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver()
|
||||
export class UserEnvironmentsResolver {
|
||||
constructor(
|
||||
@@ -157,6 +160,7 @@ export class UserEnvironmentsResolver {
|
||||
description: 'Listen for User Environment Creation',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userEnvironmentCreated(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user_environment/${user.uid}/created`);
|
||||
@@ -166,6 +170,7 @@ export class UserEnvironmentsResolver {
|
||||
description: 'Listen for User Environment updates',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userEnvironmentUpdated(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user_environment/${user.uid}/updated`);
|
||||
@@ -175,6 +180,7 @@ export class UserEnvironmentsResolver {
|
||||
description: 'Listen for User Environment deletion',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userEnvironmentDeleted(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user_environment/${user.uid}/deleted`);
|
||||
@@ -184,6 +190,7 @@ export class UserEnvironmentsResolver {
|
||||
description: 'Listen for User Environment DeleteMany',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userEnvironmentDeleteMany(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(
|
||||
|
||||
@@ -8,7 +8,10 @@ import { GqlUser } from '../decorators/gql-user.decorator';
|
||||
import { User } from '../user/user.model';
|
||||
import { throwErr } from '../utils';
|
||||
import * as E from 'fp-ts/Either';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver()
|
||||
export class UserHistoryResolver {
|
||||
constructor(
|
||||
@@ -115,6 +118,7 @@ export class UserHistoryResolver {
|
||||
description: 'Listen for User History Creation',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userHistoryCreated(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user_history/${user.uid}/created`);
|
||||
@@ -124,6 +128,7 @@ export class UserHistoryResolver {
|
||||
description: 'Listen for User History update',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userHistoryUpdated(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user_history/${user.uid}/updated`);
|
||||
@@ -133,6 +138,7 @@ export class UserHistoryResolver {
|
||||
description: 'Listen for User History deletion',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userHistoryDeleted(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user_history/${user.uid}/deleted`);
|
||||
@@ -142,6 +148,7 @@ export class UserHistoryResolver {
|
||||
description: 'Listen for User History deleted many',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userHistoryDeletedMany(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user_history/${user.uid}/deleted_many`);
|
||||
|
||||
@@ -25,7 +25,10 @@ import {
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
import { User } from 'src/user/user.model';
|
||||
import { ReqType } from 'src/user-history/user-history.model';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => UserRequest)
|
||||
export class UserRequestResolver {
|
||||
constructor(
|
||||
@@ -232,6 +235,7 @@ export class UserRequestResolver {
|
||||
description: 'Listen for User Request Creation',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userRequestCreated(@GqlUser() user: AuthUser) {
|
||||
return this.pubSub.asyncIterator(`user_request/${user.uid}/created`);
|
||||
@@ -241,6 +245,7 @@ export class UserRequestResolver {
|
||||
description: 'Listen for User Request Update',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userRequestUpdated(@GqlUser() user: AuthUser) {
|
||||
return this.pubSub.asyncIterator(`user_request/${user.uid}/updated`);
|
||||
@@ -250,6 +255,7 @@ export class UserRequestResolver {
|
||||
description: 'Listen for User Request Deletion',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userRequestDeleted(@GqlUser() user: AuthUser) {
|
||||
return this.pubSub.asyncIterator(`user_request/${user.uid}/deleted`);
|
||||
@@ -259,6 +265,7 @@ export class UserRequestResolver {
|
||||
description: 'Listen for User Request Moved',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userRequestMoved(@GqlUser() user: AuthUser) {
|
||||
return this.pubSub.asyncIterator(`user_request/${user.uid}/moved`);
|
||||
|
||||
@@ -9,7 +9,10 @@ import { UserSettings } from './user-settings.model';
|
||||
import { UserSettingsService } from './user-settings.service';
|
||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver()
|
||||
export class UserSettingsResolver {
|
||||
constructor(
|
||||
@@ -63,6 +66,7 @@ export class UserSettingsResolver {
|
||||
description: 'Listen for user setting creation',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userSettingsCreated(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user_settings/${user.uid}/created`);
|
||||
@@ -72,6 +76,7 @@ export class UserSettingsResolver {
|
||||
description: 'Listen for user setting updates',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userSettingsUpdated(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user_settings/${user.uid}/updated`);
|
||||
|
||||
@@ -10,7 +10,10 @@ import * as TE from 'fp-ts/TaskEither';
|
||||
import { pipe } from 'fp-ts/function';
|
||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||
import { AuthUser } from 'src/types/AuthUser';
|
||||
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||
import { SkipThrottle } from '@nestjs/throttler';
|
||||
|
||||
@UseGuards(GqlThrottlerGuard)
|
||||
@Resolver(() => User)
|
||||
export class UserResolver {
|
||||
constructor(
|
||||
@@ -73,6 +76,7 @@ export class UserResolver {
|
||||
description: 'Listen for user updates',
|
||||
resolve: (value) => value,
|
||||
})
|
||||
@SkipThrottle()
|
||||
@UseGuards(GqlAuthGuard)
|
||||
userUpdated(@GqlUser() user: User) {
|
||||
return this.pubsub.asyncIterator(`user/${user.uid}/updated`);
|
||||
|
||||
Reference in New Issue
Block a user