挂钩检查用户是否在Feathers中进行了身份验证(如果没有,则发送“未授权”错误,仅检查)

时间:2018-08-13 21:21:03

标签: feathersjs feathers-hook feathers-authentication

我想为数据库中的文档实现一个简单的“已发布”字段。

例如,如果用户未通过身份验证,我想始终在查询中为所有查找/获取请求插入{published:true},这样它将只返回已发布的文档(在前端有用)

但是,如果用户已通过身份验证并具有所需的角色,我想返回所有文档,而不仅仅是发布的文档(在admin中有用)。

所以我试图创建一个前钩子:

// AssignQuery.hook.js

const { some } = require('lodash');

const defaultOptions = {
  rolesField: 'roles',
  query: {},
  allowRoles: []
};
module.exports = function (options) {
  return async context => {

    options = Object.assign({}, defaultOptions, options);

    // If it was an internal call then skip this hook
    if (!context.params.provider) {
      return context;
    }

    const { user } = context.params;

    // Return unchanged context if user have some "allowRoles"
    if (user && options.allowRoles && options.allowRoles.length && some(options.allowRoles, (role) => {
      return (user[options.rolesField] || '').includes(role);
    })) return context;

    // else assign query filter
    context.params.query = Object.assign({}, context.params.query, options.query);

    return context;
  };
};

// service.hooks.js

module.exports = {
  before: {
    all: [],
    find: [
      assignQuery({ query: {published:true}, allowRoles: ['admin', 'edit'] }),
    ],
    get: [
      assignQuery({ query: {published:true}, allowRoles: ['admin', 'edit'] }),
    ],
    create: [ 
      authenticate('jwt'), 
      restrictToRoles({ roles: ['admin', 'edit']}),
    ],
    update: [ 
      authenticate('jwt'), 
      restrictToRoles({ roles: ['admin', 'edit']}),})
    ],
    patch: [ 
      authenticate('jwt'), 
      restrictToRoles({ roles: ['admin', 'edit']}),
    ],
    remove: [ 
      authenticate('jwt'),
      restrictToRoles({ roles: ['admin', 'edit']})
    ]
  },

};

问题是我必须对用户进行身份验证才能获得其角色,因此,如果用户未经过身份验证,则该服务将发送未经授权的错误,而不是允许对已过滤查询进行响应。

因此,我必须在分配查询之前调用身份验证。在这种情况下,它对于管理员来说可以正常工作,但是前端的未授权用户无法检索已发布的文章。

如果我在assignQuery之前不进行身份验证,则它在前端运行良好,未经授权的用户只能看到已发布的文章,但在管理员中不再起作用,因此管理员也将始终只收到已发布的文章,因为AssignQuery挂钩,context.params.user是未定义的(因为我们之前未进行身份验证...)

因此,我需要一种方法来检查用户是否已通过身份验证,但是如果用户未经授权,则不会向他发送未经授权的错误,我只想发送修改后的查询的响应。

我认为我需要这样的东西:

before: {
    all: [],
    find: [
      unless(isAuthenticateAndHaveRoles({roles:['admin', 'edit']}), 
        assignQuery({ query: {published:true} })
      )
    ],
    ...

但是我不知道如何进行“无阻塞”身份验证或isAuthenticate挂钩。有可能吗?

我希望我的解释不要这么混乱,目的只是为我的文档实现一个发布/草稿(可见/隐藏)(在线/离线)字段。

欢迎任何帮助。 非常感谢!

1 个答案:

答案 0 :(得分:1)

authenticate钩具有当前未公开的allowUnauthenticated选项,如果将其设置为true,则仅广告一个params.authenticated标志。所以

find: [
  authenticate('jwt', {
    allowUnauthenticated: true
  }),
  assignQuery({ query: {published:true}, allowRoles: ['admin', 'edit'] }),
]

应该这样做。