-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(api/guards): renamed RejectNestedCreateGuard to ForbidNestedCrea…
…teGuard & added options Created options for ForbidNestedCreateGuard of type { allow: string[] } to list fields to allow nested creates while forbidding all other nested creates within mutation arguments. This maximizes flexibility to describe what is safe to expose on the API surface layer. BREAKING CHANGE: Renamed RejectNestedCreateGuard to ForbidNestedCreateGuard
- Loading branch information
1 parent
020edea
commit 9744b8c
Showing
11 changed files
with
103 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
apps/api/src/app/auth/guards/forbid-nested-create.guard.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { containsNestedCreate } from './forbid-nested-create.guard'; | ||
|
||
describe('ForbidNestedCreateGuard', () => { | ||
it(`determines if args contains a "create" field`, () => { | ||
const args1 = { | ||
data: { | ||
text: 'sample', | ||
author: { connect: { id: 1 } }, | ||
comment: { create: { text: 'commenting' } }, | ||
}, | ||
}; | ||
expect(containsNestedCreate(args1)).toEqual(true); | ||
expect(containsNestedCreate(args1, { allow: ['comment'] })).toEqual(false); | ||
|
||
const args2 = { | ||
data: { | ||
stub: null, | ||
stub2: undefined, | ||
author: { create: { username: 'user1' } }, | ||
comment: { create: { text: 'commenting' } }, | ||
}, | ||
}; | ||
expect(containsNestedCreate(args2)).toEqual(true); | ||
expect(containsNestedCreate(args2, { allow: ['author'] })).toEqual(true); | ||
expect(containsNestedCreate(args2, { allow: ['comment'] })).toEqual(true); | ||
expect(containsNestedCreate(args2, { allow: ['author', 'comment'] })).toEqual(false); | ||
}); | ||
}); |
63 changes: 63 additions & 0 deletions
63
apps/api/src/app/auth/guards/forbid-nested-create.guard.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { CanActivate, ExecutionContext, HttpException, Logger, mixin } from '@nestjs/common'; | ||
import { GqlExecutionContext } from '@nestjs/graphql'; | ||
|
||
type Options = { allow: string[] }; | ||
|
||
export function containsNestedCreate(args: any, options: Options = undefined) { | ||
if (args !== null && args !== undefined) { | ||
for (const [key, value] of Object.entries(args)) { | ||
if (options?.allow.includes(key)) { | ||
continue; | ||
} | ||
|
||
if (key === 'create') { | ||
return true; | ||
} | ||
|
||
if (typeof value === 'object' && containsNestedCreate(value, options) === true) { | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Rejects mutations with nested create arguments | ||
*/ | ||
export const ForbidNestedCreateGuard = (options: Options = undefined) => { | ||
class ForbidNestedCreateGuardMixin implements CanActivate { | ||
async canActivate(context: ExecutionContext) { | ||
const ctx = GqlExecutionContext.create(context); | ||
|
||
if (ctx.getInfo()?.operation?.operation === 'mutation') { | ||
const args = ctx.getArgs(); | ||
|
||
if (containsNestedCreate(args, options)) { | ||
const errorMessage = 'Nested create arguments for mutations are forbidden'; | ||
const req = ctx.getContext()?.req; | ||
|
||
Logger.error(errorMessage, { | ||
userId: req?.user?.id, | ||
ip: req?.ip, | ||
class: ctx.getClass()?.name, | ||
handler: ctx.getHandler()?.name, | ||
args: args?.data, | ||
}); | ||
|
||
throw new HttpException(errorMessage, 403); | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
getRequest(context: ExecutionContext) { | ||
const ctx = GqlExecutionContext.create(context); | ||
return ctx.getContext().req; | ||
} | ||
} | ||
|
||
return mixin(ForbidNestedCreateGuardMixin); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
export * from './gql-throttle.guard'; | ||
export * from './gql.guard'; | ||
export * from './http.guard'; | ||
export { RejectNestedCreateGuard } from './reject-nested-create.guard'; | ||
export { ForbidNestedCreateGuard } from './forbid-nested-create.guard'; |
36 changes: 0 additions & 36 deletions
36
apps/api/src/app/auth/guards/reject-nested-create.guard.spec.ts
This file was deleted.
Oops, something went wrong.
51 changes: 0 additions & 51 deletions
51
apps/api/src/app/auth/guards/reject-nested-create.guard.ts
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "zen", | ||
"version": "4.1.0", | ||
"version": "4.2.0", | ||
"license": "MIT", | ||
"private": true, | ||
"scripts": { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters