strongloop-community / loopback-acl-route

LoopBack route based ACL
Other
7 stars 2 forks source link

Role.isInRole && ACL.isMappedToRole do not work #3

Open mike-aungsan opened 8 years ago

mike-aungsan commented 8 years ago

I finally found this repo. Basically copy the code from this file https://github.com/strongloop/loopback/blob/9a33602458712afecedd25062f02bd8b5c4e01a5/test/role.test.js

Those two functions does not work. isInRole should be true

User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) {

  console.log('Created user ', user)
  console.log('')

  Role.create({"name": "userRole", "ownerId": ObjectID(user.id)}, function(err, role) {

    console.log('Created role ', role)
    console.log(err)
    console.log('')

    role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, function(err, p) {

      if (err) {
        console.log(err)
        throw err
      }

      console.log('Created principals')
      console.log(p)
      console.log('')

      Role.isInRole('userRole', {principalType: RoleMapping.USER, principalId: user.id}, function(err, isInRole) {
        console.log('Role.isInRole userRole')
        console.log(isInRole)
        console.log('')
      })

    })

  })

})

Mongodb

db.user.find() { "_id" : ObjectId("56340e2d8e142283754e0b84"), "password" : "$2a$10$9I6OAzexu4SCZo1GmbLO3eUaA6KJhhdd1hJAjbE3OVEM53V2LTQ/m", "email" : "x@y.com", "name" : "Raymond" }

db.role.find() { "_id" : ObjectId("56340e2d8e142283754e0b85"), "name" : "userRole", "ownerId" : ObjectId("56340e2d8e142283754e0b84"), "lastupdated" : ISODate("2015-10-31T00:41:17.257Z"), "created" : ISODate("2015-10-31T00:41:17.257Z"), "modified" : ISODate("2015-10-31T00:41:17.257Z") }

db.RoleMapping.find({}) { "_id" : ObjectId("56340e2d8e142283754e0b86"), "principalType" : "USER", "principalId" : "56340e2d8e142283754e0b84", "roleId" : ObjectId("56340e2d8e142283754e0b85") }

Need Help.

Many Thanks

superkhau commented 8 years ago

@mike-aungsan Did you try running the test in the LoopBack repo? Does it pass?

mike-aungsan commented 8 years ago

Some of them passed. Some does not. I am also going to look into detail. Here is the log. I use mongodb

test@test:~/loopback/loopback/test$ mocha role.test.js

role model ✓ should define role/role relations ✓ should define role/user relations ✓ should automatically generate role id ✓ should support getRoles() and isInRole() ✓ should support owner role resolver isMappedToRole 1) "before each" hook listByPrincipalType 2) "before each" hook for "should resolve user by id"

5 passing (3s) 2 failing

1) role model isMappedToRole "before each" hook for "should resolve user by id": Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test. at done (/home/test/loopback/loopback/node_modules/async/lib/async.js:132:19) at /home/test/loopback/loopback/node_modules/async/lib/async.js:32:16 at /home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/relation-definition.js:1814:13 at /home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:320:19 at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:116:5) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at ModelConstructor. (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:319:23) at ModelConstructor.next (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/hooks.js:75:12) at ModelConstructor. (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:307:26) at ModelConstructor.next (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/hooks.js:75:12) at /home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:306:22 at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:116:5) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at createCallback (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:296:17) at /home/test/loopback/loopback/node_modules/loopback-connector-mongodb/lib/mongodb.js:272:7 at process. (/home/test/loopback/loopback/node_modules/continuation-local-storage/node_modules/async-listener/index.js:19:15)

2) role model isMappedToRole "before each" hook for "should resolve user by id": Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test. at done (/home/test/loopback/loopback/node_modules/async/lib/async.js:132:19) at /home/test/loopback/loopback/node_modules/async/lib/async.js:32:16 at /home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/relation-definition.js:1814:13 at /home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:320:19 at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:116:5) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at ModelConstructor. (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:319:23) at ModelConstructor.next (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/hooks.js:75:12) at ModelConstructor. (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:307:26) at ModelConstructor.next (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/hooks.js:75:12) at /home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:306:22 at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at doNotify (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:93:49) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:116:5) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at Function.ObserverMixin._notifyBaseObservers (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:114:15) at Function.ObserverMixin.notifyObserversOf (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/observer.js:91:8) at createCallback (/home/test/loopback/loopback/node_modules/loopback-datasource-juggler/lib/dao.js:296:17) at /home/test/loopback/loopback/node_modules/loopback-connector-mongodb/lib/mongodb.js:272:7 at process. (/home/test/loopback/loopback/node_modules/continuation-local-storage/node_modules/async-listener/index.js:19:15)

mike-aungsan commented 8 years ago

Can I extend RoleMapping? If so, these two functions does not work.

RoleMapping.find(function(err, mappings) {
    console.log('RoleMapping.find')
    if (err)
        console.log(err)
    console.log(mappings)   //  empty if roleMapping is extended
    console.log('')

});

userRole.roles(function(err, roles) {
    console.log('userRole.roles')
    if (err)
        console.log(err)
    console.log(roles)
    console.log('')
});

role-mapping.json

{
  "name": "roleMapping",
  "base": "RoleMapping",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {},
  "validations": [],
  "relations": {},
  "acls": [

  ],
  "methods": {}
}

role-mapping.js

module.exports = function(RoleMapping) {

};

role.json

Here I cannot make admin Allow, acl 2nd rule, for everything. Any help?

{
  "name": "role",
  "base": "Role",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {

  },
  "indexes": {
    "name": {
      "keys": {"name": 1},
      "options": {"unique": true}
    },
    "ownerId": {
      "keys": {"ownerId": 1}
    }
  },
  "validations": [],
  "relations": {

  },
  "acls": [
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "DENY"
    },

    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "admin",
      "permission": "ALLOW",
      "property": "*"
    },

    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "lead",
      "permission": "ALLOW"
    },

    {
      "accessType": "READ",
      "principalType": "ROLE",
      "principalId": "$authenticated",
      "permission": "ALLOW"
    }

  ],
  "methods": {}
}
holisticode commented 8 years ago

Is this a confirmed bug? I am using Role.isInRole() and not getting expected results. Any workaround/fix in sight?

raymondfeng commented 8 years ago

Do you have a simple repo to reproduce the issue?

holisticode commented 8 years ago

Hmm I am afraid not. Commercial project I have been contracted for.

I just need to know if a user is an admin. With my registered admin user, which I set up using the recommended method in the docs, when I do Role.isInRole("admin",context, callback) I always get back false. Should be true for an admin...(context is loopback.getCurrentContext()).

The current workaround I have is cumbersome and not really nice, getting all RoleMapping and iterate until I found my admin user...

mike-tofi commented 8 years ago

Hi, I can make it work by putting properties for those extended models. Same as you, I have to clean up the code before I can push. I will try to put example today.

holisticode commented 8 years ago

@raymondfeng I published a simple repo to reproduce the problem.

It'a vanilla loopback, with just one TestModel. It has a create_admin.js script in server/boot, and an after save hook in common/models/testmodel.js. The Role.isInRole() call is in the model.

there is a simple test file in test/testmodels.js, which can be executed via the simple mocha call

Be sure to run npm install and npm install -g mocha

Also, I had to intervene in loopback-testing in order to be able to use a user which is logged in without always creating it (I don't know why loopback testing is doing it that way, it's counter-intuitive).

So you need to replace node_modules/loopback-testing/lib/helpers.js with the helpers.js in the root folder. It's just has some quick hacks in order for you to be able to reproduce this problem :)

So if you successfully can get the repo to run you would always get "false" for an admin user....

The repo is at https://github.com/fablife/loopback-playground

mike-tofi commented 8 years ago

This work.

user.json

{
  "name": "user",
  "base": "User",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
  },
  "validations": [],
  "relations": {
    "accessTokens": {
      "type": "hasMany",
      "model": "accessToken",
      "foreignKey": "userId",
      "options": {
        "disableInclude": true
      }
    },
    "identities": {
      "type": "hasMany",
      "model": "userIdentity",
      "foreignKey": "userId"
    },
    "credentials": {
      "type": "hasMany",
      "model": "userCredential",
      "foreignKey": "userId"
    }
  },
  "acls": [],
  "methods": {}
}

access-token.json

{
  "name": "accessToken",
  "base": "AccessToken",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {},
  "validations": [],
  "relations": {
    "user": {
      "type": "belongsTo",
      "model": "user",
      "foreignKey": "userId"
    }
  },
  "acls": [],
  "methods": {}
}

role.json

{
  "name": "role",
  "base": "Role",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {},
  "indexes": {},
  "validations": [],
  "relations": {
    "principals": {
      "type": "hasMany",
      "model": "roleMapping",
      "foreignKey": "roleId"
    },
    "user": {
      "type": "belongsTo",
      "model": "user",
      "foreignKey": "ownerId"
    }
  },
  "acls": [],
  "methods": {}
}

role-mapping.json

{
  "name": "roleMapping",
  "base": "RoleMapping",
  "description": "Map principals to roles",
  "idInjection": false,
  "options": {
    "validateUpsert": true
  },
  "properties": {},
  "validations": [],
  "relations": {
    "role": {
      "type": "belongsTo",
      "model": "role",
      "foreignKey": "roleId"
    },
    "user": {
      "type": "belongsTo",
      "model": "user",
      "foreignKey": "ownerId"
    }
  },
  "acls": [],
  "methods": {}
}