Loopbackjs 如何根据环回(服务器端)中的角色和当前用户上下文筛选REST调用结果

Loopbackjs 如何根据环回(服务器端)中的角色和当前用户上下文筛选REST调用结果,loopbackjs,Loopbackjs,鉴于以下情况: 共有3种型号: 公司 雇员(来自用户) 位置 公司通过职位链接到员工(有很多,有很多) 有两个角色: 管理员 使用者 我想按如下方式配置我的REST api: 登录管理员后,可以访问所有REST功能 "accessType": "*", "principalType": "ROLE", "principalId": "admin", "permission": "ALLOW" 用户登录时: 获取/公司:仅返回当前用户任职的公司 GET/companys/#id:

鉴于以下情况:

共有3种型号:

  • 公司
  • 雇员(来自用户)
  • 位置
  • 公司通过职位链接到员工(有很多,有很多)

    有两个角色:

  • 管理员
  • 使用者
  • 我想按如下方式配置我的REST api:

    登录管理员后,可以访问所有REST功能

      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "admin",
      "permission": "ALLOW"
    
    用户登录时:

    获取/公司:仅返回当前用户任职的公司

    GET/companys/#id:仅当当前用户在该公司有职位时才允许使用。

    基于的评论,我编写了以下函数

    请注意,该函数没有覆盖模型ACL


    该程序遵循以下步骤:

    1:通过环回当前上下文访问当前用户用户ID

    如果没有经过身份验证的用户,请退出该函数

    2:使用角色映射表加载当前用户的角色

    如果当前用户角色不是“用户”,请退出该功能

    3:加载当前用户的职位,并创建他工作的公司Id数组

    4:重写当前查询

    • 对于/companys调用,为id注入where条件
    • 对于/companys/#id,测试请求的id是否与允许的id之一匹配,如果不匹配,则返回错误401


    您可以潜在地添加在调用任何
    /companys
    端点之后发生的生命周期方法,并修改
    where
    include
    过滤器,以仅包括
    位置
    模型中存在记录的公司。然后,您可以在返回数据之前手动筛选出结果。不幸的是,环回不允许您基于(内部联接)进行过滤-尽管在这个问题上给出+1可能会加快意识。
    Company.observe('access', function (ctx, next) {
        /* Observe the access to companies
         *  If the role of the logged user is 'user', will restrict access to only custom set of data
         *  Otherwise, will access all data */
    
        // Access loopback current Context to get userID through accessToken
        var loopbackCtx = loopback.getCurrentContext();
        var accessToken = loopbackCtx && loopbackCtx.get('accessToken');
        var userId = accessToken && accessToken.userId;
    
        if (!userId) {
          // without connected user. proceed without hook
          return next();
        }
    
        // Will perform a query in the RoleMapping Model to findout the current role of connected user
        var RoleMapping = app.models.RoleMapping;
        var roleQuery = {
          where: {
            "principalId": userId,
            "roleId": 2 // role 2: user
          }
        };
    
        RoleMapping.findOne(roleQuery, function (err, result) {
    
          if (!result) {
            //no matching role, proceed without hook
            return next();
          }
    
          // found one match in the RoleMapping table. must now restrict results in accordance with positions of the current employee
    
          // Looking for positions for the current employee
          var position = app.models.position;
          var positionQuery = {
            where: {
              "employeeId": userId
            }
          };
    
          position.find(positionQuery, function (err, results) {
            // from the position list, create a list of companies
    
            var allowedCompanies = [];
            results.forEach(function (result) {
              allowedCompanies.push(result.companyId);
            });
    
            //use the list of allowed companies to restrict results
            if (!ctx.query.where) {
              // typically call from a find() without arguments (findall)
              // will inject a new condition
              ctx.query = {
                where: {
                  "id": { inq: allowedCompanies}
                }
              }
            }
            else {
              if (ctx.query.where.id && Number.isInteger(ctx.query.where.id)) {
                // typically call from a find({ id: .. )}
                // will authorize or not access to the company data
                console.log(ctx.query.where.id);
                if ( allowedCompanies.indexOf(ctx.query.where.id) == -1 ) {
                  // the id is not in the permited scope, will return a 401 error
                  var error = new Error();
                  error.name = "Error";
                  error.status = 401;
                  error.statusCode = 401;
                  error.message = 'Authorization Required';
                  error.code = 'AUTHORIZATION_REQUIRED';
                  return next(error);
                }
              }
              // other calls (with inq) are not yet implemented
            }
    
            return next();
          });
    
        });
    
    });