首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用graphql-tools/utils在阿波罗中使用自定义指令实现授权?

如何使用graphql-tools/utils在阿波罗中使用自定义指令实现授权?
EN

Stack Overflow用户
提问于 2022-01-29 17:28:35
回答 1查看 359关注 0票数 0

我知道阿波罗2通过扩展类“SchemaDirectiveVisitor”允许定制指令。然而,我正在使用阿波罗3,我知道现在实现这一目标的方法是使用graphql-tools/utils和graphql-tools/schema。

在我的index.js中,我有以下代码:

代码语言:javascript
复制
const serverServer = async () => {
   app.use(AuthMiddleware);

   app.use(
      cors({
         origin: 'mydomain',
      })
   );

   let schema = makeExecutableSchema({
      typeDefs: [typeDefsLibrary, typeDefsDynamicContent, userTypeDefs],
      resolvers: {
         Query,
         Mutation,
         Article,
         Blog,
         Podcast,
         SermonNotes,
         Sermon,
         // dynamic Content
         Friday,
         Thursday,
         // Post Content
         Commentary,
         Quote,
         Thought,
         UserContent_SermonNotes,
         // User Content
         User,
         All_Posts,
      },
   });

   schema = AuthorizationDirective(schema, 'auth');

   const apolloServer = new ApolloServer({
      schema,
      context: ({ req }) => {
         const { isAuth, user } = req;
         return {
            req,
            isAuth,
            user,
         };
      },
   });

   await apolloServer.start();
   apolloServer.applyMiddleware({ app: app, path: '/api' });

   app.listen(process.env.PORT, () => {
      console.log(`listening on port 4000`);
   });
};

serverServer();

然后,在我的模式文件上有:

代码语言:javascript
复制
  directive @auth(requires: [RoleName] ) on OBJECT | FIELD_DEFINITION 
  
  enum RoleName {
    SUPERADMIN
    ADMIN
  }

   type Commentary @auth(requires: [SUPERADMIN, ADMIN]) {
      ID: ID
      USER_ID: ID
      VERSE_ID: String
      body: String
      category_tags: String
      referenced_verses: String
      verse_citation: String
      created_date: String
      posted_on: String
      creator(avatarOnly: Boolean): User
      comments(showComment: Boolean): [Commentary_Comment]
      approvals: [Commentary_Approval]
      total_count: Int
   }

这是我的自定义指令代码:

代码语言:javascript
复制
const { mapSchema, getDirective, MapperKind } = require('@graphql-tools/utils');
const { defaultFieldResolver } = require('graphql');
const { ApolloError } = require('apollo-server-express');
//const { logging } = require('../../helpers');

module.exports.AuthorizationDirective = (schema, directiveName) => {
   return mapSchema(schema, {
      [MapperKind.FIELD]: (fieldConfig, _fieldName, typeName) => {
         const authDirective = getDirective(schema, fieldConfig, directiveName);
         console.log('auth Directive line 10: ', authDirective);
         if (authDirective && authDirective.length) {
            const requiredRoles = authDirective[0].requires;

            if (requiredRoles && requiredRoles.length) {
               const { resolve = defaultFieldResolver } = fieldConfig;
               fieldConfig.resolve = function (source, args, context, info) {
                  if (requiredRoles.includes('PUBLIC')) {
                     console.log(
                        `==> ${context.code || 'ANONYMOUS'} ACCESSING PUBLIC RESOLVER: ${
                           info.fieldName
                        }`
                     );
                     //logging(context, info.fieldName, args);

                     return resolve(source, args, context, info);
                  }

                  if (!requiredRoles.includes(context.code)) {
                     throw new ApolloError('NOT AUTHORIZED', 'NO_AUTH');
                  }
                  console.log(`==> ${context.code} ACCESSING PRIVATE RESOLVER: ${info.fieldName}`);
                  //logging(context, info.fieldName, args);

                  return resolve(source, args, context, info);
               };

               return fieldConfig;
            }
         }
      },
   });
};

但不起作用。它似乎甚至没有调用自定义指令。正如您所看到的,我在我的模式指令函数上有一个“console.log(‘auth指令第10行:',authDirective)”,该函数返回“未定义”。

我知道这个帖子太灵了,但我希望有人能帮忙!

提前感谢!

EN

回答 1

Stack Overflow用户

发布于 2022-08-19 20:20:42

下面的是为我工作的代码,

我使用过MapperKind.OBJECT_FIELD:而不是MapperKind.FIELD

我是从@graphql-tools -> https://www.graphql-tools.com/docs/schema-directives#enforcing-access-permissions中引用的

‘const { mapSchema,getDirective,MapperKind }= require('@graphql-tools/utils');const { defaultFieldResolver }= require('graphql');

const HasRoleDirective = (schema,directiveName) => {返回mapSchema(模式,{

代码语言:javascript
复制
// Executes once for each object field in the schems
[MapperKind.OBJECT_FIELD]: (fieldConfig, _fieldName, typeName) => {

  // Check whether this field has the specified directive
  const authDirective = getDirective(schema, fieldConfig, directiveName);

  if (authDirective && authDirective.length) {
    const requiredRoles = authDirective[0].requires;
    // console.log("requiredRoles: ", requiredRoles);

    if (requiredRoles && requiredRoles.length) {
      // Get this field's original resolver
      const { resolve = defaultFieldResolver } = fieldConfig;

      // Replace the original resolver with function that "first" calls 
      fieldConfig.resolve = function (source, args, context, info) {
        // console.log("Context Directive:  ", context);
        const { currentUser } = context;
        if(!currentUser) throw new Error("Not Authenticated");

        const { type } = currentUser['userInfo']
        const isAuthorized = hasRole(type, requiredRoles);
        if(!isAuthorized) throw new Error("You Have Not Enough Permissions!")

        //logging(context, info.fieldName, args);
        return resolve(source, args, context, info);
      };
      return fieldConfig;
    }
  }
}

}}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70907997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档