tolicodes / hunt-mongoose-rest

Abstract Mongoose to REST interface CRUD
MIT License
0 stars 0 forks source link

Where to store ACL checks? #2

Open vodolaz095 opened 10 years ago

vodolaz095 commented 10 years ago

This is mainly a question to discuss with @avbrychak and @nycitt.

We will use this module with http://mongoosejs.com/docs/guide.html or http://sequelizejs.com/ ORM.

Both of them use the Active record pattern


  Model
   .find({'id':1})
   .limit(1)
   .exec(function(error, itemFound){
      if(error) {
        throw error;
      } else {
        //do stuff
      }
    });

The thing, i want to propose, is that we have to propose static and instance specific methods to test the ACL agains the current user and the current model.

Something like described in my comment here https://oselot.atlassian.net/browse/ACR-373

I'll try to explain method, that worked for me. It is something similiar to linux users and groups. Right now there is orthogonal permissions based role model (like symfony 1.4 sf_doctrine_guard module) and group model (not used). Every User object in database has hash of roles - right now it is { "owner":true, "seller":true, "buyer":true } also, there is boolean of root; First, how can we implement ACL with existing mongoose database and users models. We need to implement 4 functions for each mongoose orm models. 1) static(http://mongoosejs.com/docs/guide.html#statics) method of canCreate with call like this model.canCreate(user, function(error, canCreate) {...});

2) static function getListFilter

model.getListFilter(user, function(error, filter, fields){...} ); for example, we have user with role buyer, and filter returns {'active':true } , so, we can list ONLY tradelines, that are on active state if user has seller role, he get the filter of {'sellerId': user.id} , so he can list only HIS/HER tradelines, and owner get filter of {} - so he can list ALL tradelines. fields has is some sort of formater for each role. FOr example, Owners see all tradeline info, seller do not see notes, etc.... 3) method (http://mongoosejs.com/docs/guide.html#methods) canRead tradeLine.canRead(user, function(error, canRead, fields) {...});

if canRead = true, this particular user can read access. For example, if user is root, he can read every document, and so on, if active=true, so buyer can read, and if sellerId=user.id, this is seller, and he can read the document. fields are the object fields, that are accessible by user

4) method canWrite

tradeLine.canWrite(user, function(error, canWrite, fields) {...} ); is analogous to canRead. The strong part of this approach are 1) it works (i have 2 project, where it worked ok for 15k (mysql) and 3k users(mongo) 2) it allows to hard code all roles' rights in code (it is easier to maintain, than populating the database), but we can easily assing role to every user required 3) It allows to simply etract users from database, that has role required - the roles are index of collection, and queries like db.users.find( {'roles.owner':true} ) are realy fast 4) this approach is scallable 5) it is easier to add next role bad sides 1) when we delete role globally, it is quite hard to maintain consistency of database and code 2) looks like it have to be done from the scratch, but the infrastucture for this is already done (roles for user entries in database) why do i don't like the approach in https://www.npmjs.org/package/acl 1) If we have 100 users, 100 objects and 5 operations on them ( list, readOne, delete,edit, delete), we need 100_100_5 = 50.000 database records for it 2) it use separate data storage for rights - redis database (it is not intented to be permanent and fail proof storage), or mongo (we need separate collection just for storing the permissions!) As a bad example, i can told about one case i have encountered. It was a Zend 1.12 framework project, started on 2007 year. It has about 300k customers and about 100 managers, and about 500 sellers. Rights were done in big XML file (about 15 mb). And once per 3-4 month they have issues with database, and they have to recover the users from dump. And about 10% users has lost their rights, because their id was changed (there was different delta id, because they used replication, and one server issued odd ids (2,4,6,....) and second - even (1,2,3,4)... So, the main thing i want to warn everybody, that ACL permissions have to be stored in users account in primary database or in object in collections in primary database, and it have to be done in simply recoverable way. thats all

So, we have to set up the ACL in model, with input parameters of current document and current user.

So, tests will be like this

//owner can edit documents
if(document.ownerId === user.id){
  callback(null, true);
}
nycitt commented 10 years ago

This sounds like a good strategy.

Can you please post on confluence (for better formatting and to keep consistent history).

If you want we can schedule a talk tomorrow to go over this in more detail.

Truly Yours, Anatoliy Zaslavskiy

President, Oselot Consulting Direct Phone: (347) 882-9902 Business Hours: 5:30AM-10:00PM, 7 Days a week See My Live Calendar For Scheduling

“Do What You Do Best, We’ll Provide The Rest”

On Jun 23, 2014, at 2:00 PM, vodolaz095 notifications@github.com wrote:

This is mainly a question to discuss with @avbrychak and @nycitt.

We will use this module with http://mongoosejs.com/docs/guide.html or http://sequelizejs.com/ ORM.

Both of them use the Active record pattern

Model .find({'id':1}) .limit(1) .exec(function(error, itemFound){ if(error) { throw error; } else { //do stuff } });

The thing, i want to propose, is that we have to propose static and instance specific methods to test the ACL agains the current user and the current model.

Something like described in my comment here https://oselot.atlassian.net/browse/ACR-373

I'll try to explain method, that worked for me. It is something similiar to linux users and groups. Right now there is orthogonal permissions based role model (like symfony 1.4 sf_doctrine_guard module) and group model (not used). Every User object in database has hash of roles - right now it is { "owner":true, "seller":true, "buyer":true } also, there is boolean of root; First, how can we implement ACL with existing mongoose database and users models. We need to implement 4 functions for each mongoose orm models. 1) static(http://mongoosejs.com/docs/guide.html#statics) method of canCreate with call like this model.canCreate(user, function(error, canCreate) {...});

2) static function getListFilter

model.getListFilter(user, function(error, filter, fields){...} ); for example, we have user with role buyer, and filter returns {'active':true } , so, we can list ONLY tradelines, that are on active state if user has seller role, he get the filter of {'sellerId': user.id} , so he can list only HIS/HER tradelines, and owner get filter of {} - so he can list ALL tradelines. fields has is some sort of formater for each role. FOr example, Owners see all tradeline info, seller do not see notes, etc.... 3) method (http://mongoosejs.com/docs/guide.html#methods) canRead tradeLine.canRead(user, function(error, canRead, fields) {...});

if canRead = true, this particular user can read access. For example, if user is root, he can read every document, and so on, if active=true, so buyer can read, and if sellerId=user.id, this is seller, and he can read the document. fields are the object fields, that are accessible by user

4) method canWrite

tradeLine.canWrite(user, function(error, canWrite, fields) {...} ); is analogous to canRead. The strong part of this approach are 1) it works (i have 2 project, where it worked ok for 15k (mysql) and 3k users(mongo) 2) it allows to hard code all roles' rights in code (it is easier to maintain, than populating the database), but we can easily assing role to every user required 3) It allows to simply etract users from database, that has role required - the roles are index of collection, and queries like db.users.find( {'roles.owner':true} ) are realy fast 4) this approach is scallable 5) it is easier to add next role bad sides 1) when we delete role globally, it is quite hard to maintain consistency of database and code 2) looks like it have to be done from the scratch, but the infrastucture for this is already done (roles for user entries in database) why do i don't like the approach in https://www.npmjs.org/package/acl 1) If we have 100 users, 100 objects and 5 operations on them ( list, readOne, delete,edit, delete), we need 100_100_5 = 50.000 database records for it 2) it use separate data storage for rights - redis database (it is not intented to be permanent and fail proof storage), or mongo (we need separate collection just for storing the permissions!) As a bad example, i can told about one case i have encountered. It was a Zend 1.12 framework project, started on 2007 year. It has about 300k customers and about 100 managers, and about 500 sellers. Rights were done in big XML file (about 15 mb). And once per 3-4 month they have issues with database, and they have to recover the users from dump. And about 10% users has lost their rights, because their id was changed (there was different delta id, because they used replication, and one server issued odd ids (2,4,6,....) and second - even (1,2,3,4)... So, the main thing i want to warn everybody, that ACL permissions have to be stored in users account in primary database or in object in collections in primary database, and it have to be done in simply recoverable way. thats all

So, we have to set up the ACL in model, with input parameters of current document and current user.

So, tests will be like this

//owner can edit documents if(document.ownerId === user.id){ callback(null, true); }

— Reply to this email directly or view it on GitHub.

vodolaz095 commented 10 years ago

i'll post the confluence page, when i'll finish this approach, i hope to show something working, and compatible with current project tomorrow

vodolaz095 commented 10 years ago

https://oselot.atlassian.net/wiki/display/ACR/ACR+role+model