I am trying to develop a Role Based Access Control System in Sequelize (Postgresql). But cant figure out how should I go with my relationships in Sequelize.
Problem Statement:
So the hierarchy goes like this:-
There's a Company table which has many Branches
Each Branch can have many Employess and many custom Roles and many default Modules
Roles will provide access to the Modules
based on the roles employees can read the module or make changes in the module or have access to the modules
So far I have developed a DB structure like this:
// Company & Branch
Company.hasMany(Branch);
Branch.belongsTo(Company);
// Branch & Employee
Branch.hasMany(Employee);
Employee.belongsTo(Branch);
// Branch & Roles
Branch.hasMany(Role);
Role.belongsTo(Branch);
// Modules & Roles
Role.belongsToMany(Module, { through: Permission }); //Permission is where I have added read, write as a boolean datatype
Module.belongsToMany(Role, { through: Permission });
// Employee & Roles
Employee.hasOne(EmployeeRole);
EmployeeRole.belongsTo(Employee);
Role.hasMany(EmployeeRole);
But I think its all a mess, Can anyone please help me develop a solution for this problem.
(I am using sequelize as my ORM).
Related
I'm developing a Xamarin.Forms app which uses an Azure app service with SQL database linked through EasyTables. I've run the samples and successfully tested querying tables etc on the server and enabled offline sync so as a localdb is created.
I've created the store, defined the table & sync'd it, however I want to be able to query it somehow with a where clause - is that possible? Can I add a where clause to the client.GetSyncTable line?
var store = new MobileServiceSQLiteStore("localstore.db");
store.DefineTable<Journey_Stages>();
client.SyncContext.InitializeAsync(store);
tbl_Stages = client.GetSyncTable<Journey_Stages>();
Some of the tables I'm pulling down will grow over time & are linked to individual user profiles, so I only want data which belongs to that user and I don't want to be bringing down masses of data each time, preferably let the server handle that and only bring down what I need on a user by user basis.
Thanks,
Steve
You should add this filtering logic on the server side, so that each user's data isn't exposed to all your other users. See for example this sample if you are using the Node.js backend -- line 17 adds a WHERE clause for the table read query. If you have the .Net backend, similar logic would go in your table controller.
// Configure specific code when the client does a request
// READ - only return records belonging to the authenticated user
table.read(function (context) {
context.query.where({ userId: context.user.id });
return context.execute();
});
I'm trying to implement some kind of permission framework in Node js, using sequelize as an ORM (with Postgres). After hours of research, the closest thing I can find to do this with existing npm modules is using acl with acl sequelize to support my stack.
The problem is that it looks like the acl module assigns a role, where that role would get a set of permissions to all instances of a specific resource. However, I need to do permissioning for instances based on existing relationships of that user.
As an example, consider a permissioning system for a simple forum. It gives these permissions for each role:
// allow guests to view posts
acl.allow("guest", "post", "view");
// allow registered users to view and create posts
acl.allow("registered users", "post", ["view", "create"]);
// allow administrators to perform any action on posts
acl.allow("administrator", "post", "*");
Suppose that I want to also add the ability for registered users to also edit their own posts, and the user has a relationship to all the posts they've created.
Is there any way for this module to do this, or any other module that can support this kind of behavior on the database / ORM level?
If not, and I have to implement a custom one, what would the best approach to creating something like this.
There is relatively new library CASL. I'm the author of this library. And it's possible to implement your usecase quite easily:
const { AbilityBuilder } = require('casl')
const ability = AbilityBuilder.define((can, cannot) => {
can('read', 'all')
can(['update', 'delete'], 'Article', { author_id: loggedInUser.id })
})
The code above basically says:
- anyone can read everything
- anyone can update and delete articles where author_id equals logged in user id
Later you can do:
ability.can('delete', 'Post')
//or
ability.can('update', post)
// where post variable is an instance of your Post model
Also there is an article which explains how to integrate CASL with MongoDB and Express exactly for your usecase.
I built a Social Network web app in Node. I added a group model for create a group of Users like facebook.
I've been looking everywhere for a npm modules that i could use and i have searched google and stackoverflow but i haven't found anything.
This is my the Group Model I add to my proyect.
var groupSchema = mongoose.Schema({
name: String,
motivation: String,
destination: String,
days: String,
members: [String],
profile: String
});
module.exports = mongoose.model('Group', groupSchema);
Does anyone has a good way to do this?
Note: I use a groupController and I thought to use 3 actions. One for show Users, One for add the User and One to create but it did not work.
Unfortunately, there aren't any really well rounded authorization frameworks for node yet (afaik).
I'm the author of the express-stormpath library which does some of this, but isn't a catch-all for authorization rules yet.
The way the express-stormpath library works is like so:
You have an Account object.
You have a Group object.
You can create Groups, and assign Accounts to those Groups. So you might have groups called:
admins
users
anonymousUsers
etc.
Then, on each Group, you can store permission data using this JSON blob thing. So you might do something like:
Group.customData.permissions = ['can_read', 'can_write', ...];
The library also provides some middleware tools for working with users / groups, for instance, you can say something like:
app.get('/secret', stormpath.groupsRequired(['admins']), function(req, res) {
// if you get here, you must be in the admins group
});
If you'd like to check it out, you can read more about it here: https://docs.stormpath.com/nodejs/express/
I am trying to create an application for sports event management system using MEAN.io
Since it uses the modular approach, there are different packages that comes in skeleton application like system, users, access. What i want to do is make a new package called players and it should extend the users package. The players schema would contain extra fields section and teams.So how do I extend the User Schema of users package in players package?
You can make your players package be dependent on users.
Players.register(function(app, auth, users, database) {...});
You now have access to the database and can load the user schema with
var userModel = database.connection.model('User');
and you can use the schema.add function to extend the schema
userModel.schema.add({ scrore: 'string'});
This should add the score field to the user model
I think this might work for you. But I was told from a member of mongoose team that schema.add only works before compiling the model. See this link for more info about schema add http://mongoosejs.com/docs/api.html#schema_Schema-add
If a post has been made to /user, and my data model says that ever user must have a group, how, after successfully creating a user, would I trigger a new group to be created in sails.js? For that matter, how can I get into another controller from a lifecycle callback like afterCreate or via other means?
You cannot call a controller inside a model, that would violate MVC pattern. You can create the group via
Group.create(obj)
or put your creation logic inside a service.
It sounds like you might be confusing models and controllers, which is easy to do if you're new to Sails because of the blueprints functionality it provides. That is to say: you don't need GroupController to create a Group model instances, and GroupController.create is not the correct way to create a new Group programatically. GroupController.create is a method that's called automatically when you POST to /group because Sails has set up a "blueprint" create action at that location.
The correct way to create a Group programmatically is by using the create method of the Group model class, which is globally available in a Sails app. So in your afterCreate, you could have:
afterCreate: function(values, cb) {
Group.create({user: values.id}).exec(cb);
}
Note that the latest version of Sails (v0.10.0-rc5) supports nested creates, so if you've defined User and Group to be associated with each other, you could just POST something like this to /user:
{
name: "Joe Blow",
age: 25,
group: {
name: "Joe's group"
}
}
and the group will be created and associated with the user automatically. If you POST an embedded Group with a primary key, it will search for an existing group with that key and link it to the new User instead of creating a new Group.