Skip to content

Commit cda8127

Browse files
committed
fix(read-relations.resolver): use relation's authorizer to resolve auth filter
1 parent ee475aa commit cda8127

File tree

2 files changed

+38
-16
lines changed

2 files changed

+38
-16
lines changed

packages/query-graphql/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export { AuthorizationContext, Authorizer, AuthorizerOptions, CustomAuthorizer, OperationGroup } from './auth'
1+
export { AuthorizationContext, Authorizer, AuthorizerOptions, CustomAuthorizer, getAuthorizerToken, OperationGroup } from './auth'
22
export { DTONamesOpts } from './common'
33
export {
44
Authorize,

packages/query-graphql/src/resolvers/relations/read-relations.resolver.ts

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { ExecutionContext } from '@nestjs/common'
1+
import { ExecutionContext, Inject, Optional } from '@nestjs/common'
22
import { Args, ArgsType, Context, Parent, Resolver } from '@nestjs/graphql'
3-
import { Class, Filter, mergeQuery, QueryService } from '@ptc-org/nestjs-query-core'
3+
import { Class, mergeQuery, QueryService } from '@ptc-org/nestjs-query-core'
44

5-
import { OperationGroup } from '../../auth'
5+
import { Authorizer, getAuthorizerToken, OperationGroup } from '../../auth'
66
import { getDTONames } from '../../common'
7-
import { GraphQLResolveInfoResult, GraphQLResultInfo, RelationAuthorizerFilter, ResolverField } from '../../decorators'
7+
import { GraphQLResolveInfoResult, GraphQLResultInfo, ResolverField } from '../../decorators'
88
import { InjectDataLoaderConfig } from '../../decorators/inject-dataloader-config.decorator'
99
import { AuthorizerInterceptor } from '../../interceptors'
1010
import { CountRelationsLoader, DataLoaderFactory, FindRelationsLoader, QueryRelationsLoader } from '../../loader'
@@ -30,10 +30,16 @@ const ReadOneRelationMixin =
3030
const { baseNameLower, baseName } = getDTONames(relationDTO, { dtoName: relation.dtoName })
3131
const relationName = relation.relationName ?? baseNameLower
3232
const loaderName = `load${baseName}For${DTOClass.name}`
33+
const authorizerKey = Symbol(`authorizerFor${DTOClass.name}`)
34+
const relationAuthorizerKey = Symbol(`authorizerFor${relation.dtoName}`)
3335
const findLoader = new FindRelationsLoader<DTO, Relation>(relationDTO, relationName)
3436

3537
@Resolver(() => DTOClass, { isAbstract: true })
3638
class ReadOneMixin extends Base {
39+
@Optional() @Inject(getAuthorizerToken(DTOClass)) [authorizerKey]?: Authorizer<Relation>;
40+
41+
@Optional() @Inject(getAuthorizerToken(relationDTO)) [relationAuthorizerKey]?: Authorizer<Relation>
42+
3743
@ResolverField(
3844
baseNameLower,
3945
() => relationDTO,
@@ -49,16 +55,21 @@ const ReadOneRelationMixin =
4955
async [`find${baseName}`](
5056
@Parent() dto: DTO,
5157
@Context() context: ExecutionContext,
52-
@RelationAuthorizerFilter(baseNameLower, {
53-
operationGroup: OperationGroup.READ,
54-
many: false
55-
})
56-
authFilter?: Filter<Relation>,
5758
@GraphQLResultInfo(DTOClass)
5859
resolveInfo?: GraphQLResolveInfoResult<Relation>,
5960
@InjectDataLoaderConfig()
6061
dataLoaderConfig?: DataLoaderOptions
6162
): Promise<Relation | undefined> {
63+
const authContext = {
64+
operationName: baseNameLower,
65+
operationGroup: OperationGroup.READ,
66+
readonly: true,
67+
many: false
68+
}
69+
const authFilter = relation.auth
70+
? await relation.auth?.authorize(context, authContext)
71+
: ((await this[authorizerKey]?.authorizeRelation(baseNameLower, context, authContext)) ??
72+
(await this[relationAuthorizerKey]?.authorize(context, authContext)))
6273
return DataLoaderFactory.getOrCreateLoader(
6374
context,
6475
loaderName,
@@ -93,6 +104,8 @@ const ReadManyRelationMixin =
93104
const relationName = relation.relationName ?? baseNameLower
94105
const relationLoaderName = `load${baseName}For${DTOClass.name}`
95106
const countRelationLoaderName = `count${baseName}For${DTOClass.name}`
107+
const authorizerKey = Symbol(`authorizerFor${DTOClass.name}`)
108+
const relationAuthorizerKey = Symbol(`authorizerFor${relation.dtoName}`)
96109
const queryLoader = new QueryRelationsLoader<DTO, Relation>(relationDTO, relationName)
97110
const countLoader = new CountRelationsLoader<DTO, Relation>(relationDTO, relationName)
98111
const connectionName = `${dtoName}${baseName}Connection`
@@ -109,6 +122,10 @@ const ReadManyRelationMixin =
109122

110123
@Resolver(() => DTOClass, { isAbstract: true })
111124
class ReadManyMixin extends Base {
125+
@Optional() @Inject(getAuthorizerToken(DTOClass)) [authorizerKey]?: Authorizer<Relation>;
126+
127+
@Optional() @Inject(getAuthorizerToken(relationDTO)) [relationAuthorizerKey]?: Authorizer<Relation>
128+
112129
@ResolverField(
113130
baseNameLower,
114131
() => CT.resolveType,
@@ -125,16 +142,21 @@ const ReadManyRelationMixin =
125142
@Parent() dto: DTO,
126143
@Args() q: RelationQA,
127144
@Context() context: ExecutionContext,
128-
@RelationAuthorizerFilter(baseNameLower, {
129-
operationGroup: OperationGroup.READ,
130-
many: true
131-
})
132-
relationFilter?: Filter<Relation>,
133145
@GraphQLResultInfo(DTOClass)
134146
resolveInfo?: GraphQLResolveInfoResult<Relation>,
135147
@InjectDataLoaderConfig()
136148
dataLoaderConfig?: DataLoaderOptions
137149
): Promise<InstanceType<typeof CT>> {
150+
const authContext = {
151+
operationName: baseNameLower,
152+
operationGroup: OperationGroup.READ,
153+
readonly: true,
154+
many: true
155+
}
156+
const authFilter = relation.auth
157+
? await relation.auth?.authorize(context, authContext)
158+
: ((await this[authorizerKey]?.authorizeRelation(baseNameLower, context, authContext)) ??
159+
(await this[relationAuthorizerKey]?.authorize(context, authContext)))
138160
const relationQuery = await transformAndValidate(RelationQA, q)
139161
const relationLoader = DataLoaderFactory.getOrCreateLoader(
140162
context,
@@ -152,7 +174,7 @@ const ReadManyRelationMixin =
152174

153175
return CT.createFromPromise(
154176
(query) => relationLoader.load({ dto, query }),
155-
mergeQuery(relationQuery, { filter: relationFilter, relations: resolveInfo?.relations }),
177+
mergeQuery(relationQuery, { filter: authFilter, relations: resolveInfo?.relations }),
156178
(filter) => relationCountLoader.load({ dto, filter })
157179
)
158180
}

0 commit comments

Comments
 (0)