Reputation: 6356
Is it possible and how to filter the data based on the role ?
For example, I have an app with entities Customer and Salesrep. Each customer is assigned exactly one Salesrep. I need a Salesrep with role "sales" to see/edit only the customers assigned to her, but her boss (which has role "supervisor") to list but not edit all the customers assigned to one of his employee.
In SQL, I would add WHERE role="sales" AND employee.name=user.name OR role="supervisor" AND employee.group=user.group
to each query.
Upvotes: 0
Views: 44
Reputation: 1758
First of all, you can define the sales
role to have the read/write rights (see/edit), and role supervisor
to have read right (not write).
That being said, the answer is no, you can't filter the customers list only using roles. Roles only give you basic CRUD action control over entities.
To do so, you're gonna need some custom dev on the route of your customer entity
controller /customer/datalist
.
By default, this route look like this :
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();
});
});
It is called using ajax from the list view of customer entity.
The filterDataTable
function handles the filtering/ordering/pagination of your datalist. It takes two optional parameters: speInclude
and speWhere
that allows you to customize the sequelize ORM query that will be generated (see Sequelize where and Sequelize include).
Depending on how your relation/foreign keys are defined, you can choose between these solutions. It's up to you to use the best one for your situation :
Using the speWhere
parameter :
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();
});
});
With the speWhere
parameter, only customers associated with your salesrep will be fetched from database.
Using the speInclude
parameter :
You can change the entity on which you do the query (salesrep
), and ask to include every customers associated with this entity.
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();
});
});
With this solution, you'll query the salesrep model instead of the customer model, and get an array of customers associated to your salesrep.
Filtering the query's result
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();
});
});
This method should be used only as a last solution since you will need to redefine the pagination.
These pieces of code haven't been tested and might need some adjustements. They only show what is possible and how to proceed.
Upvotes: 1