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_SMTP_URL="smtps://user@domain.com:pass@smtp.domain.com"
|
||||||
MAILER_ADDRESS_FROM='"From Name Here" <from@example.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
|
# Auth Tokens Config
|
||||||
JWT_SECRET='add some secret here'
|
JWT_SECRET='add some secret here'
|
||||||
TOKEN_SALT_COMPLEXITY=10
|
TOKEN_SALT_COMPLEXITY=10
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
"@nestjs/jwt": "^10.0.1",
|
"@nestjs/jwt": "^10.0.1",
|
||||||
"@nestjs/passport": "^9.0.0",
|
"@nestjs/passport": "^9.0.0",
|
||||||
"@nestjs/platform-express": "^9.2.1",
|
"@nestjs/platform-express": "^9.2.1",
|
||||||
|
"@nestjs/throttler": "^4.0.0",
|
||||||
"@prisma/client": "^4.7.1",
|
"@prisma/client": "^4.7.1",
|
||||||
"apollo-server-express": "^3.11.1",
|
"apollo-server-express": "^3.11.1",
|
||||||
"apollo-server-plugin-base": "^3.7.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 { UserCollectionModule } from './user-collection/user-collection.module';
|
||||||
import { ShortcodeModule } from './shortcode/shortcode.module';
|
import { ShortcodeModule } from './shortcode/shortcode.module';
|
||||||
import { COOKIES_NOT_FOUND } from './errors';
|
import { COOKIES_NOT_FOUND } from './errors';
|
||||||
|
import { ThrottlerModule } from '@nestjs/throttler';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -60,6 +61,10 @@ import { COOKIES_NOT_FOUND } from './errors';
|
|||||||
}),
|
}),
|
||||||
driver: ApolloDriver,
|
driver: ApolloDriver,
|
||||||
}),
|
}),
|
||||||
|
ThrottlerModule.forRoot({
|
||||||
|
ttl: +process.env.RATE_LIMIT_TTL,
|
||||||
|
limit: +process.env.RATE_LIMIT_MAX,
|
||||||
|
}),
|
||||||
UserModule,
|
UserModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
AdminModule,
|
AdminModule,
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import {
|
|||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
Get,
|
Get,
|
||||||
HttpException,
|
|
||||||
HttpStatus,
|
|
||||||
Post,
|
Post,
|
||||||
Req,
|
Req,
|
||||||
Request,
|
Request,
|
||||||
@@ -20,11 +18,14 @@ import { JwtAuthGuard } from './guards/jwt-auth.guard';
|
|||||||
import { GqlUser } from 'src/decorators/gql-user.decorator';
|
import { GqlUser } from 'src/decorators/gql-user.decorator';
|
||||||
import { AuthUser } from 'src/types/AuthUser';
|
import { AuthUser } from 'src/types/AuthUser';
|
||||||
import { RTCookie } from 'src/decorators/rt-cookie.decorator';
|
import { RTCookie } from 'src/decorators/rt-cookie.decorator';
|
||||||
import { AuthGuard } from '@nestjs/passport';
|
|
||||||
import { authCookieHandler, throwHTTPErr } from './helper';
|
import { authCookieHandler, throwHTTPErr } from './helper';
|
||||||
import { GoogleSSOGuard } from './guards/google-sso.guard';
|
import { GoogleSSOGuard } from './guards/google-sso.guard';
|
||||||
import { GithubSSOGuard } from './guards/github-sso.guard';
|
import { GithubSSOGuard } from './guards/github-sso.guard';
|
||||||
import { MicrosoftSSOGuard } from './guards/microsoft-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' })
|
@Controller({ path: 'auth', version: '1' })
|
||||||
export class AuthController {
|
export class AuthController {
|
||||||
constructor(private authService: AuthService) {}
|
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
|
* @see https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow#how-it-works
|
||||||
*/
|
*/
|
||||||
@Get('google/callback')
|
@Get('google/callback')
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GoogleSSOGuard)
|
@UseGuards(GoogleSSOGuard)
|
||||||
async googleAuthRedirect(@Request() req, @Res() res) {
|
async googleAuthRedirect(@Request() req, @Res() res) {
|
||||||
const authTokens = await this.authService.generateAuthTokens(req.user.uid);
|
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
|
* @see https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow#how-it-works
|
||||||
*/
|
*/
|
||||||
@Get('github/callback')
|
@Get('github/callback')
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GithubSSOGuard)
|
@UseGuards(GithubSSOGuard)
|
||||||
async githubAuthRedirect(@Request() req, @Res() res) {
|
async githubAuthRedirect(@Request() req, @Res() res) {
|
||||||
const authTokens = await this.authService.generateAuthTokens(req.user.uid);
|
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
|
* @see https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow#how-it-works
|
||||||
*/
|
*/
|
||||||
@Get('microsoft/callback')
|
@Get('microsoft/callback')
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(MicrosoftSSOGuard)
|
@UseGuards(MicrosoftSSOGuard)
|
||||||
async microsoftAuthRedirect(@Request() req, @Res() res) {
|
async microsoftAuthRedirect(@Request() req, @Res() res) {
|
||||||
const authTokens = await this.authService.generateAuthTokens(req.user.uid);
|
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 { AuthUser } from '../types/AuthUser';
|
||||||
import { JwtService } from '@nestjs/jwt';
|
import { JwtService } from '@nestjs/jwt';
|
||||||
import { PaginationArgs } from 'src/types/input-types.args';
|
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)
|
@Resolver(() => Shortcode)
|
||||||
export class ShortcodeResolver {
|
export class ShortcodeResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -105,6 +108,7 @@ export class ShortcodeResolver {
|
|||||||
description: 'Listen for shortcode creation',
|
description: 'Listen for shortcode creation',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
myShortcodesCreated(@GqlUser() user: AuthUser) {
|
myShortcodesCreated(@GqlUser() user: AuthUser) {
|
||||||
return this.pubsub.asyncIterator(`shortcode/${user.uid}/created`);
|
return this.pubsub.asyncIterator(`shortcode/${user.uid}/created`);
|
||||||
@@ -114,6 +118,7 @@ export class ShortcodeResolver {
|
|||||||
description: 'Listen for shortcode deletion',
|
description: 'Listen for shortcode deletion',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
myShortcodesRevoked(@GqlUser() user: AuthUser): AsyncIterator<Shortcode> {
|
myShortcodesRevoked(@GqlUser() user: AuthUser): AsyncIterator<Shortcode> {
|
||||||
return this.pubsub.asyncIterator(`shortcode/${user.uid}/revoked`);
|
return this.pubsub.asyncIterator(`shortcode/${user.uid}/revoked`);
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ import {
|
|||||||
} from './input-type.args';
|
} from './input-type.args';
|
||||||
import * as E from 'fp-ts/Either';
|
import * as E from 'fp-ts/Either';
|
||||||
import { throwErr } from 'src/utils';
|
import { throwErr } from 'src/utils';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver(() => TeamCollection)
|
@Resolver(() => TeamCollection)
|
||||||
export class TeamCollectionResolver {
|
export class TeamCollectionResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -312,6 +315,7 @@ export class TeamCollectionResolver {
|
|||||||
TeamMemberRole.EDITOR,
|
TeamMemberRole.EDITOR,
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
)
|
)
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
teamCollectionAdded(
|
teamCollectionAdded(
|
||||||
@Args({
|
@Args({
|
||||||
@@ -333,6 +337,7 @@ export class TeamCollectionResolver {
|
|||||||
TeamMemberRole.EDITOR,
|
TeamMemberRole.EDITOR,
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
)
|
)
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
teamCollectionUpdated(
|
teamCollectionUpdated(
|
||||||
@Args({
|
@Args({
|
||||||
@@ -354,6 +359,7 @@ export class TeamCollectionResolver {
|
|||||||
TeamMemberRole.EDITOR,
|
TeamMemberRole.EDITOR,
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
)
|
)
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
teamCollectionRemoved(
|
teamCollectionRemoved(
|
||||||
@Args({
|
@Args({
|
||||||
@@ -375,6 +381,7 @@ export class TeamCollectionResolver {
|
|||||||
TeamMemberRole.EDITOR,
|
TeamMemberRole.EDITOR,
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
)
|
)
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
teamCollectionMoved(
|
teamCollectionMoved(
|
||||||
@Args({
|
@Args({
|
||||||
@@ -396,6 +403,7 @@ export class TeamCollectionResolver {
|
|||||||
TeamMemberRole.EDITOR,
|
TeamMemberRole.EDITOR,
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
)
|
)
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
collectionOrderUpdated(
|
collectionOrderUpdated(
|
||||||
@Args({
|
@Args({
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { UseGuards } from '@nestjs/common';
|
import { UseGuards } from '@nestjs/common';
|
||||||
import { Resolver, Mutation, Args, Subscription, ID } from '@nestjs/graphql';
|
import { Resolver, Mutation, Args, Subscription, ID } from '@nestjs/graphql';
|
||||||
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
import { pipe } from 'fp-ts/function';
|
import { pipe } from 'fp-ts/function';
|
||||||
import * as TE from 'fp-ts/TaskEither';
|
import * as TE from 'fp-ts/TaskEither';
|
||||||
import { GqlAuthGuard } from 'src/guards/gql-auth.guard';
|
import { GqlAuthGuard } from 'src/guards/gql-auth.guard';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||||
import { RequiresTeamRole } from 'src/team/decorators/requires-team-role.decorator';
|
import { RequiresTeamRole } from 'src/team/decorators/requires-team-role.decorator';
|
||||||
import { GqlTeamMemberGuard } from 'src/team/guards/gql-team-member.guard';
|
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 { TeamEnvironment } from './team-environments.model';
|
||||||
import { TeamEnvironmentsService } from './team-environments.service';
|
import { TeamEnvironmentsService } from './team-environments.service';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver(() => 'TeamEnvironment')
|
@Resolver(() => 'TeamEnvironment')
|
||||||
export class TeamEnvironmentsResolver {
|
export class TeamEnvironmentsResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -144,6 +147,7 @@ export class TeamEnvironmentsResolver {
|
|||||||
description: 'Listen for Team Environment Updates',
|
description: 'Listen for Team Environment Updates',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.OWNER,
|
TeamMemberRole.OWNER,
|
||||||
@@ -165,6 +169,7 @@ export class TeamEnvironmentsResolver {
|
|||||||
description: 'Listen for Team Environment Creation Messages',
|
description: 'Listen for Team Environment Creation Messages',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.OWNER,
|
TeamMemberRole.OWNER,
|
||||||
@@ -186,6 +191,7 @@ export class TeamEnvironmentsResolver {
|
|||||||
description: 'Listen for Team Environment Deletion Messages',
|
description: 'Listen for Team Environment Deletion Messages',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.OWNER,
|
TeamMemberRole.OWNER,
|
||||||
|
|||||||
@@ -34,7 +34,10 @@ import { TeamInviteViewerGuard } from './team-invite-viewer.guard';
|
|||||||
import { TeamInviteTeamOwnerGuard } from './team-invite-team-owner.guard';
|
import { TeamInviteTeamOwnerGuard } from './team-invite-team-owner.guard';
|
||||||
import { UserService } from 'src/user/user.service';
|
import { UserService } from 'src/user/user.service';
|
||||||
import { PubSubService } from 'src/pubsub/pubsub.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)
|
@Resolver(() => TeamInvitation)
|
||||||
export class TeamInvitationResolver {
|
export class TeamInvitationResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -199,6 +202,7 @@ export class TeamInvitationResolver {
|
|||||||
description: 'Listens to when a Team Invitation is added',
|
description: 'Listens to when a Team Invitation is added',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.OWNER,
|
TeamMemberRole.OWNER,
|
||||||
@@ -220,6 +224,7 @@ export class TeamInvitationResolver {
|
|||||||
description: 'Listens to when a Team Invitation is removed',
|
description: 'Listens to when a Team Invitation is removed',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.OWNER,
|
TeamMemberRole.OWNER,
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ import { PubSubService } from 'src/pubsub/pubsub.service';
|
|||||||
import * as E from 'fp-ts/Either';
|
import * as E from 'fp-ts/Either';
|
||||||
import * as O from 'fp-ts/Option';
|
import * as O from 'fp-ts/Option';
|
||||||
import { throwErr } from 'src/utils';
|
import { throwErr } from 'src/utils';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver(() => TeamRequest)
|
@Resolver(() => TeamRequest)
|
||||||
export class TeamRequestResolver {
|
export class TeamRequestResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -242,6 +245,7 @@ export class TeamRequestResolver {
|
|||||||
description: 'Emits when a new request is added to a team',
|
description: 'Emits when a new request is added to a team',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
@@ -263,6 +267,7 @@ export class TeamRequestResolver {
|
|||||||
description: 'Emitted when a request has been updated',
|
description: 'Emitted when a request has been updated',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
@@ -285,6 +290,7 @@ export class TeamRequestResolver {
|
|||||||
'Emitted when a request has been deleted. Only the id of the request is emitted.',
|
'Emitted when a request has been deleted. Only the id of the request is emitted.',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
@@ -307,6 +313,7 @@ export class TeamRequestResolver {
|
|||||||
'Emitted when a requests position has been changed in its collection',
|
'Emitted when a requests position has been changed in its collection',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
@@ -329,6 +336,7 @@ export class TeamRequestResolver {
|
|||||||
'Emitted when a request has been moved from one collection into another',
|
'Emitted when a request has been moved from one collection into another',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
@RequiresTeamRole(
|
@RequiresTeamRole(
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
ID,
|
ID,
|
||||||
} from '@nestjs/graphql';
|
} from '@nestjs/graphql';
|
||||||
import { TeamService } from './team.service';
|
import { TeamService } from './team.service';
|
||||||
import { User } from '../user/user.model';
|
|
||||||
import { GqlAuthGuard } from '../guards/gql-auth.guard';
|
import { GqlAuthGuard } from '../guards/gql-auth.guard';
|
||||||
import { GqlUser } from '../decorators/gql-user.decorator';
|
import { GqlUser } from '../decorators/gql-user.decorator';
|
||||||
import { UseGuards } from '@nestjs/common';
|
import { UseGuards } from '@nestjs/common';
|
||||||
@@ -21,7 +20,10 @@ import { PubSubService } from '../pubsub/pubsub.service';
|
|||||||
import * as E from 'fp-ts/Either';
|
import * as E from 'fp-ts/Either';
|
||||||
import { throwErr } from 'src/utils';
|
import { throwErr } from 'src/utils';
|
||||||
import { AuthUser } from 'src/types/AuthUser';
|
import { AuthUser } from 'src/types/AuthUser';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver(() => Team)
|
@Resolver(() => Team)
|
||||||
export class TeamResolver {
|
export class TeamResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -271,6 +273,7 @@ export class TeamResolver {
|
|||||||
TeamMemberRole.EDITOR,
|
TeamMemberRole.EDITOR,
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
)
|
)
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
teamMemberAdded(
|
teamMemberAdded(
|
||||||
@Args({
|
@Args({
|
||||||
@@ -293,6 +296,7 @@ export class TeamResolver {
|
|||||||
TeamMemberRole.EDITOR,
|
TeamMemberRole.EDITOR,
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
)
|
)
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
teamMemberUpdated(
|
teamMemberUpdated(
|
||||||
@Args({
|
@Args({
|
||||||
@@ -315,6 +319,7 @@ export class TeamResolver {
|
|||||||
TeamMemberRole.EDITOR,
|
TeamMemberRole.EDITOR,
|
||||||
TeamMemberRole.VIEWER,
|
TeamMemberRole.VIEWER,
|
||||||
)
|
)
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
||||||
teamMemberRemoved(
|
teamMemberRemoved(
|
||||||
@Args({
|
@Args({
|
||||||
|
|||||||
@@ -31,7 +31,10 @@ import {
|
|||||||
} from './input-type.args';
|
} from './input-type.args';
|
||||||
import { ReqType } from 'src/types/RequestTypes';
|
import { ReqType } from 'src/types/RequestTypes';
|
||||||
import * as E from 'fp-ts/Either';
|
import * as E from 'fp-ts/Either';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver(() => UserCollection)
|
@Resolver(() => UserCollection)
|
||||||
export class UserCollectionResolver {
|
export class UserCollectionResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -352,6 +355,7 @@ export class UserCollectionResolver {
|
|||||||
description: 'Listen for User Collection Creation',
|
description: 'Listen for User Collection Creation',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userCollectionCreated(@GqlUser() user: AuthUser) {
|
userCollectionCreated(@GqlUser() user: AuthUser) {
|
||||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/created`);
|
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.',
|
description: 'Listen to when a User Collection has been updated.',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userCollectionUpdated(@GqlUser() user: AuthUser) {
|
userCollectionUpdated(@GqlUser() user: AuthUser) {
|
||||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/updated`);
|
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',
|
description: 'Listen to when a User Collection has been deleted',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userCollectionRemoved(@GqlUser() user: AuthUser) {
|
userCollectionRemoved(@GqlUser() user: AuthUser) {
|
||||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/deleted`);
|
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',
|
description: 'Listen to when a User Collection has been moved',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userCollectionMoved(@GqlUser() user: AuthUser) {
|
userCollectionMoved(@GqlUser() user: AuthUser) {
|
||||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/moved`);
|
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',
|
description: 'Listen to when a User Collections position has changed',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userCollectionOrderUpdated(@GqlUser() user: AuthUser) {
|
userCollectionOrderUpdated(@GqlUser() user: AuthUser) {
|
||||||
return this.pubSub.asyncIterator(`user_coll/${user.uid}/order_updated`);
|
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 { UserEnvironmentsService } from './user-environments.service';
|
||||||
import * as E from 'fp-ts/Either';
|
import * as E from 'fp-ts/Either';
|
||||||
import { throwErr } from 'src/utils';
|
import { throwErr } from 'src/utils';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class UserEnvironmentsResolver {
|
export class UserEnvironmentsResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -157,6 +160,7 @@ export class UserEnvironmentsResolver {
|
|||||||
description: 'Listen for User Environment Creation',
|
description: 'Listen for User Environment Creation',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userEnvironmentCreated(@GqlUser() user: User) {
|
userEnvironmentCreated(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user_environment/${user.uid}/created`);
|
return this.pubsub.asyncIterator(`user_environment/${user.uid}/created`);
|
||||||
@@ -166,6 +170,7 @@ export class UserEnvironmentsResolver {
|
|||||||
description: 'Listen for User Environment updates',
|
description: 'Listen for User Environment updates',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userEnvironmentUpdated(@GqlUser() user: User) {
|
userEnvironmentUpdated(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user_environment/${user.uid}/updated`);
|
return this.pubsub.asyncIterator(`user_environment/${user.uid}/updated`);
|
||||||
@@ -175,6 +180,7 @@ export class UserEnvironmentsResolver {
|
|||||||
description: 'Listen for User Environment deletion',
|
description: 'Listen for User Environment deletion',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userEnvironmentDeleted(@GqlUser() user: User) {
|
userEnvironmentDeleted(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user_environment/${user.uid}/deleted`);
|
return this.pubsub.asyncIterator(`user_environment/${user.uid}/deleted`);
|
||||||
@@ -184,6 +190,7 @@ export class UserEnvironmentsResolver {
|
|||||||
description: 'Listen for User Environment DeleteMany',
|
description: 'Listen for User Environment DeleteMany',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userEnvironmentDeleteMany(@GqlUser() user: User) {
|
userEnvironmentDeleteMany(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(
|
return this.pubsub.asyncIterator(
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ import { GqlUser } from '../decorators/gql-user.decorator';
|
|||||||
import { User } from '../user/user.model';
|
import { User } from '../user/user.model';
|
||||||
import { throwErr } from '../utils';
|
import { throwErr } from '../utils';
|
||||||
import * as E from 'fp-ts/Either';
|
import * as E from 'fp-ts/Either';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class UserHistoryResolver {
|
export class UserHistoryResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -115,6 +118,7 @@ export class UserHistoryResolver {
|
|||||||
description: 'Listen for User History Creation',
|
description: 'Listen for User History Creation',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userHistoryCreated(@GqlUser() user: User) {
|
userHistoryCreated(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user_history/${user.uid}/created`);
|
return this.pubsub.asyncIterator(`user_history/${user.uid}/created`);
|
||||||
@@ -124,6 +128,7 @@ export class UserHistoryResolver {
|
|||||||
description: 'Listen for User History update',
|
description: 'Listen for User History update',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userHistoryUpdated(@GqlUser() user: User) {
|
userHistoryUpdated(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user_history/${user.uid}/updated`);
|
return this.pubsub.asyncIterator(`user_history/${user.uid}/updated`);
|
||||||
@@ -133,6 +138,7 @@ export class UserHistoryResolver {
|
|||||||
description: 'Listen for User History deletion',
|
description: 'Listen for User History deletion',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userHistoryDeleted(@GqlUser() user: User) {
|
userHistoryDeleted(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user_history/${user.uid}/deleted`);
|
return this.pubsub.asyncIterator(`user_history/${user.uid}/deleted`);
|
||||||
@@ -142,6 +148,7 @@ export class UserHistoryResolver {
|
|||||||
description: 'Listen for User History deleted many',
|
description: 'Listen for User History deleted many',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userHistoryDeletedMany(@GqlUser() user: User) {
|
userHistoryDeletedMany(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user_history/${user.uid}/deleted_many`);
|
return this.pubsub.asyncIterator(`user_history/${user.uid}/deleted_many`);
|
||||||
|
|||||||
@@ -25,7 +25,10 @@ import {
|
|||||||
import { AuthUser } from 'src/types/AuthUser';
|
import { AuthUser } from 'src/types/AuthUser';
|
||||||
import { User } from 'src/user/user.model';
|
import { User } from 'src/user/user.model';
|
||||||
import { ReqType } from 'src/user-history/user-history.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)
|
@Resolver(() => UserRequest)
|
||||||
export class UserRequestResolver {
|
export class UserRequestResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -232,6 +235,7 @@ export class UserRequestResolver {
|
|||||||
description: 'Listen for User Request Creation',
|
description: 'Listen for User Request Creation',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userRequestCreated(@GqlUser() user: AuthUser) {
|
userRequestCreated(@GqlUser() user: AuthUser) {
|
||||||
return this.pubSub.asyncIterator(`user_request/${user.uid}/created`);
|
return this.pubSub.asyncIterator(`user_request/${user.uid}/created`);
|
||||||
@@ -241,6 +245,7 @@ export class UserRequestResolver {
|
|||||||
description: 'Listen for User Request Update',
|
description: 'Listen for User Request Update',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userRequestUpdated(@GqlUser() user: AuthUser) {
|
userRequestUpdated(@GqlUser() user: AuthUser) {
|
||||||
return this.pubSub.asyncIterator(`user_request/${user.uid}/updated`);
|
return this.pubSub.asyncIterator(`user_request/${user.uid}/updated`);
|
||||||
@@ -250,6 +255,7 @@ export class UserRequestResolver {
|
|||||||
description: 'Listen for User Request Deletion',
|
description: 'Listen for User Request Deletion',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userRequestDeleted(@GqlUser() user: AuthUser) {
|
userRequestDeleted(@GqlUser() user: AuthUser) {
|
||||||
return this.pubSub.asyncIterator(`user_request/${user.uid}/deleted`);
|
return this.pubSub.asyncIterator(`user_request/${user.uid}/deleted`);
|
||||||
@@ -259,6 +265,7 @@ export class UserRequestResolver {
|
|||||||
description: 'Listen for User Request Moved',
|
description: 'Listen for User Request Moved',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userRequestMoved(@GqlUser() user: AuthUser) {
|
userRequestMoved(@GqlUser() user: AuthUser) {
|
||||||
return this.pubSub.asyncIterator(`user_request/${user.uid}/moved`);
|
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 { UserSettingsService } from './user-settings.service';
|
||||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||||
import { AuthUser } from 'src/types/AuthUser';
|
import { AuthUser } from 'src/types/AuthUser';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class UserSettingsResolver {
|
export class UserSettingsResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -63,6 +66,7 @@ export class UserSettingsResolver {
|
|||||||
description: 'Listen for user setting creation',
|
description: 'Listen for user setting creation',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userSettingsCreated(@GqlUser() user: User) {
|
userSettingsCreated(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user_settings/${user.uid}/created`);
|
return this.pubsub.asyncIterator(`user_settings/${user.uid}/created`);
|
||||||
@@ -72,6 +76,7 @@ export class UserSettingsResolver {
|
|||||||
description: 'Listen for user setting updates',
|
description: 'Listen for user setting updates',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userSettingsUpdated(@GqlUser() user: User) {
|
userSettingsUpdated(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user_settings/${user.uid}/updated`);
|
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 { pipe } from 'fp-ts/function';
|
||||||
import { PubSubService } from 'src/pubsub/pubsub.service';
|
import { PubSubService } from 'src/pubsub/pubsub.service';
|
||||||
import { AuthUser } from 'src/types/AuthUser';
|
import { AuthUser } from 'src/types/AuthUser';
|
||||||
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
||||||
|
import { SkipThrottle } from '@nestjs/throttler';
|
||||||
|
|
||||||
|
@UseGuards(GqlThrottlerGuard)
|
||||||
@Resolver(() => User)
|
@Resolver(() => User)
|
||||||
export class UserResolver {
|
export class UserResolver {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -73,6 +76,7 @@ export class UserResolver {
|
|||||||
description: 'Listen for user updates',
|
description: 'Listen for user updates',
|
||||||
resolve: (value) => value,
|
resolve: (value) => value,
|
||||||
})
|
})
|
||||||
|
@SkipThrottle()
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
userUpdated(@GqlUser() user: User) {
|
userUpdated(@GqlUser() user: User) {
|
||||||
return this.pubsub.asyncIterator(`user/${user.uid}/updated`);
|
return this.pubsub.asyncIterator(`user/${user.uid}/updated`);
|
||||||
|
|||||||
Reference in New Issue
Block a user