#graphql
Вопрос:
Я хочу проверить, что каждое поле (включая поле, аргумент и поле ввода) в запрашиваемой строке запроса доступно запрашивающему до выполнения соответствующих распознавателей.
Для этого я создал пользовательскую директиву @authorized()
, которая получает аргумент requires
, представляющий собой массив роли пользователя, который может получить доступ к полю. Например, в следующей схеме:
input UpdateUserInput {
name: String
email: String @authorized(requires: [ADMIN])
}
type User {
id: ID!
name: String!
email: String! @authorized(requires: [ADMIN])
}
type Mutation {
updateUser(userId: ID!, data: UpdateUserInput!): User! @authorized(requires: [ADMIN])
}
только пользователи с ролью ADMIN
могут
- Вызов
updateUser
мутации email
поле запросаUser
- Вызов
updateUser
мутации сdata
аргументом, включающимemail
поле ввода
Реализация @authorized()
директивы заключается в следующем:
export class AuthorizedDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field: GraphQLField<any, Context>) {
const { resolve = defaultFieldResolver } = field;
const fieldResolver: GraphQLFieldResolver<any, Context> = (
parent,
args,
context,
info,
) => {
const { requestor } = context;
if (!requestor)
throw new AuthenticationError(
`You have to be authenticated to access field '${field.name}'`,
);
if (!this.args.requires?.includes(requestor.role))
throw new ForbiddenError(
`You are not authorized to access field '${field.name}'`,
);
return resolve.apply(this, [parent, args, context, info]);
};
field.resolve = fieldResolver;
}
visitArgumentDefinition() {}
visitFieldDefinition() {}
}
С помощью этой реализации я могу достичь поведения 1 и 2. Однако я не могу достичь поведения 3. Для достижения поведения 3 я думаю, что мне нужно
- Traverse AST nodes starting from the nodes of arguments
- Проверьте, применяется ли директива ‘@authorized()’ к узлу
- проверьте необходимые роли, если применяется директива
- Бросьте
ForbiddenError
, если у запрашивающего нет требуемой роли
Является ли это правильным подходом?. Если да, то как я могу обойти узлы AST в распознавателе полей GraphQL? Если нет, то есть ли какой-либо способ добиться поведения 3, используя только директиву GraphQL?