基于角色的数据访问

时间:2017-09-05 07:12:00

标签: newmips

是否可以以及如何根据角色过滤数据?

例如,我有一个实体Customer和Salesrep的应用程序。每个客户只分配一个Salesrep。我需要一个具有角色"销售"的Salesrep。只查看/编辑分配给她的客户,但她的老板(有角色"主管")列出但不编辑分配给他的一名员工的所有客户。

在SQL中,我会为每个查询添加WHERE role="sales" AND employee.name=user.name OR role="supervisor" AND employee.group=user.group

1 个答案:

答案 0 :(得分:1)

首先,您可以定义sales角色以具有读/写权限(请参阅/编辑),并将角色supervisor定义为具有正确读取(不写入)。

话虽如此,答案是否定的,您不能仅使用角色过滤客户列表。角色仅为您提供对实体的基本CRUD操作控制。

为此,您需要在客户实体的路线上使用一些自定义开发 控制器/customer/datalist

如何运作

默认情况下,此路线如下所示:

router.post('/datalist', block_access.isLoggedIn, block_access.actionAccessMiddleware("customer", "read"), function(req, res) {
    filterDataTable("E_customer", req.body).then(function(data) {
        res.send(data).end();
    }).catch(function(err) {
        logger.debug(err);
        res.end();
    });
});

从客户实体的列表视图中使用ajax调用它。

filterDataTable函数处理数据列表的过滤/排序/分页。它需要两个可选参数:speIncludespeWhere,允许您自定义将生成的续集ORM查询(请参阅Sequelize whereSequelize include)。

解决方案

根据您的关系/外键的定义方式,您可以选择这些解决方案。您可以根据自己的情况使用最好的一个:

使用speWhere参数:

router.post('/datalist', block_access.isLoggedIn, block_access.actionAccessMiddleware("customer", "read"), function(req, res) {
    var user = req.session.passport.user;
    var speWhere;
    if (user.r_role.f_label == 'sales')
        speWhere = {f_id_salesrep: user.id};

    filterDataTable("E_customer", req.body, null, speWhere).then(function(data) {
        res.send(data).end();
    }).catch(function(err) {
        logger.debug(err);
        res.end();
    });
});

使用speWhere参数,只会从数据库中提取与salesrep关联的客户。

使用speInclude参数:

您可以更改执行查询的实体(salesrep),并要求包含与此实体关联的每个客户。

router.post('/datalist', block_access.isLoggedIn, block_access.actionAccessMiddleware("customer", "read"), function(req, res) {
    var user = req.session.passport.user;
    var speInclude;var targetEntity = 'E_customer';
    if (user.r_role.f_label == 'sales') {
        targetEntity = 'E_salesrep';
        speInclude = [
            model: models.E_customer,
            as: 'r_customer'
        ];
    }

    filterDataTable(targetEntity, req.body, speInclude).then(function(data) {
        if (speInclude)
            data.data = data.data.r_customer; // Set the salesrep's customers to the returned data
        res.send(data).end();
    }).catch(function(err) {
        logger.debug(err);
        res.end();
    });
});

使用此解决方案,您将查询salesrep模型而不是客户模型,并获得与salesrep相关联的客户数组。

过滤查询结果

router.post('/datalist', block_access.isLoggedIn, block_access.actionAccessMiddleware("customer", "read"), function(req, res) {
    filterDataTable("E_customer", req.body).then(function(data) {
        var filteredCustomers = [];
        var user = req.session.passport.user;
        for (var i = 0; i < data.data.length; i++)
            if (data.data[i].f_id_salesrep == user.id)
                filteredCustomers.push(data.data[i]);
        data.data = filteredCustomers;
        res.send(data).end();
    }).catch(function(err) {
        logger.debug(err);
        res.end();
    });
});

此方法应仅用作最后一个解决方案,因为您需要重新定义分页。

这些代码片段尚未经过测试,可能需要一些调整。它们仅显示可能的内容以及如何继续。