{"action":"created","issue":{"url":"https://api.github.com/repos/reactioncommerce/reaction/issues/372","labels_url":"https://api.github.com/repos/reactioncommerce/reaction/issues/372/labels{/name}","comments_url":"https://api.github.com/repos/reactioncommerce/reaction/issues/372/comments","events_url":"https://api.github.com/repos/reactioncommerce/reaction/issues/372/events","html_url":"https://github.com/reactioncommerce/reaction/issues/372","id":71413618,"number":372,"title":"Role and permissions for multi vendor","user":{"login":"boboci9","id":9323474,"avatar_url":"https://avatars.githubusercontent.com/u/9323474?v=3","gravatar_id":"","url":"https://api.github.com/users/boboci9","html_url":"https://github.com/boboci9","followers_url":"https://api.github.com/users/boboci9/followers","following_url":"https://api.github.com/users/boboci9/following{/other_user}","gists_url":"https://api.github.com/users/boboci9/gists{/gist_id}","starred_url":"https://api.github.com/users/boboci9/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/boboci9/subscriptions","organizations_url":"https://api.github.com/users/boboci9/orgs","repos_url":"https://api.github.com/users/boboci9/repos","events_url":"https://api.github.com/users/boboci9/events{/privacy}","received_events_url":"https://api.github.com/users/boboci9/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/reactioncommerce/reaction/labels/discussion","name":"discussion","color":"e86bc4"},{"url":"https://api.github.com/repos/reactioncommerce/reaction/labels/ready","name":"ready","color":"ededed"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/reactioncommerce/reaction/milestones/25","html_url":"https://github.com/reactioncommerce/reaction/milestones/Marketplace","labels_url":"https://api.github.com/repos/reactioncommerce/reaction/milestones/25/labels","id":1091589,"number":25,"title":"Marketplace","description":"Multi-vendor and marketplace functionality.","creator":{"login":"aaronjudd","id":439959,"avatar_url":"https://avatars.githubusercontent.com/u/439959?v=3","gravatar_id":"","url":"https://api.github.com/users/aaronjudd","html_url":"https://github.com/aaronjudd","followers_url":"https://api.github.com/users/aaronjudd/followers","following_url":"https://api.github.com/users/aaronjudd/following{/other_user}","gists_url":"https://api.github.com/users/aaronjudd/gists{/gist_id}","starred_url":"https://api.github.com/users/aaronjudd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aaronjudd/subscriptions","organizations_url":"https://api.github.com/users/aaronjudd/orgs","repos_url":"https://api.github.com/users/aaronjudd/repos","events_url":"https://api.github.com/users/aaronjudd/events{/privacy}","received_events_url":"https://api.github.com/users/aaronjudd/received_events","type":"User","site_admin":false},"open_issues":2,"closed_issues":0,"state":"open","created_at":"2015-04-30T19:26:25Z","updated_at":"2015-04-30T19:27:34Z","due_on":null,"closed_at":null},"comments":6,"created_at":"2015-04-27T21:55:29Z","updated_at":"2015-05-05T03:16:30Z","closed_at":null,"body":"Hi Aaron,\r\n\r\nAs I mentioned on gitter I am working on a PR to help the current version of package permissions work better with the multi vendor solution (it would be a continuation of the PR #128) based on your ideas from #357 but I wanted to clear some of your ideas on the matter before I pull anything. I will list my suggestions please let me know what do you think.\r\n\r\n1. In the Packages publication section we have\r\n\r\n\t\tif Roles.userIsInRohle(this.userId, ['dashboard','owner','admin'])\r\n\t\t      return Packages.find shopId: shop._id\r\n\r\n\tbut what happens when we have multiple shops and the user is the owner of a completely different shop than the shop._id.\r\n\r\n\tI can think of several possibilities to handle this issue so I wanted to see your point of view on which to include in the PR\r\n\r\n\t The suggestion would be using the group concept form the meteor-roles package this would work even if we don’t overwrite the whole code at once. This would mean that the shopId would be the name of the group and it would look like the following in the DB:\r\n\t  \r\n\t\tuser1.roles = {\r\n\t\t    'shopId1': ['dashboard','admin']}\r\n\t\tuser2.roles = {\r\n\t\t    'shopId2': ['owner']}\r\n\t\t    \r\n\tand we could use Roles.userIsInRole(userId1, ['dashboard','admin']) -> true (this would still work)\r\n\tor Roles.userIsInRole(userId1, ['dashboard','admin'], shopId2) -> false\r\n\r\n2. Also here in the Package publications I think we should include a registry check based on the permissions so if the user is not admin we check if he’s a member and check for the userPermissions  something like this\r\n\r\n\t        Shops.find().forEach (shop) ->\r\n\t\t        member = _.find shop.members, (member) ->\r\n\t\t          currentUser is member.userId #this.userId is not defined here\r\n\t\t        if member\r\n\t\t          Packages.find { shopId: shop._id, 'registry.route' : {$in:member.permissions}}\r\n\t\t      return Packages.find { shopId: shop._id},\r\n\t\t      \r\n\tWe would of course have to recheck this on the client side as well because we would have packages returned with several registries but the user might not have access to all so I would check this in the reactionApp helper.\r\n\r\n\tBut there is still an open question for public packages there are some packages that should be present no matter the user permissions, how should we handle these?\r\n\r\n3. Regarding the ReactionCore class properties like userPermissions, in a multi vendor environment should these be calculated by the shop the current user is a member of an not the current shop? \r\n\r\n\tSomething like this in the app.coffee init function\r\n\r\n\t\tShops.find().forEach (shop) ->\r\n\t\t              member = _.find shop.members, (member) ->\r\n\t\t                    member.userId is Meteor.userId()\r\n\t\t          if member\r\n\t\t            self.isMember = true\r\n\t\t            self.isAdmin = member.isAdmin\r\n\t\t            self.userPermissions = member.permissions\r\n\r\nThanks for your help in advance."},"comment":{"url":"https://api.github.com/repos/reactioncommerce/reaction/issues/comments/98921253","html_url":"https://github.com/reactioncommerce/reaction/issues/372#issuecomment-98921253","issue_url":"https://api.github.com/repos/reactioncommerce/reaction/issues/372","id":98921253,"user":{"login":"aaronjudd","id":439959,"avatar_url":"https://avatars.githubusercontent.com/u/439959?v=3","gravatar_id":"","url":"https://api.github.com/users/aaronjudd","html_url":"https://github.com/aaronjudd","followers_url":"https://api.github.com/users/aaronjudd/followers","following_url":"https://api.github.com/users/aaronjudd/following{/other_user}","gists_url":"https://api.github.com/users/aaronjudd/gists{/gist_id}","starred_url":"https://api.github.com/users/aaronjudd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aaronjudd/subscriptions","organizations_url":"https://api.github.com/users/aaronjudd/orgs","repos_url":"https://api.github.com/users/aaronjudd/repos","events_url":"https://api.github.com/users/aaronjudd/events{/privacy}","received_events_url":"https://api.github.com/users/aaronjudd/received_events","type":"User","site_admin":false},"created_at":"2015-05-05T03:16:30Z","updated_at":"2015-05-05T03:16:30Z","body":"After really digging into the existing roles, I felt this this functionality was probably written before there was `groups` support, and just in general was lagging behind since the most recent package / registry updates.  I had merely kept it running the existing permissions process when I refactored the package registry, and thankfully, it's much easier to manage permissions now using the registry.\r\n\r\nI'm not sure why we had the `Shops.members` functionality,  but it's now removed in favor of the roles package methods.\r\n\r\nI've refactored to get the current admin working properly just using roles and groups from `alanning:roles`. The previous implementation wasn't using groups at all, just permissions, so now the permission sets are unique to each group(shop).\r\n\r\nWe should be able to deprecate `packages.permissions`, `ReactionCore.permissions` and `shop.members` now by reusing the packages.registry routes to establish permissions/roles.\r\n\r\nWith this approach, you do not need to do anything special to setup permissions for packages, **by default we'll use the package.registry.routes to create required permissions**.\r\n\r\n# registry permissions (roles)\r\n*server/registry.coffee with optional permission definitions*\r\n\r\n\t registry: [\r\n\t    {\r\n\t      route: \"dashboard\"\r\n\t      provides: 'dashboard'\r\n\t      label: 'Core'\r\n\t      description: 'Reaction Commerce Core'\r\n\t      icon: 'fa fa-th'\r\n\t      cycle: 1\r\n\t      container: \"dashboard\"\r\n\t    }\r\n\t  ]\r\n\r\n\r\n>*TODO* `registry.route` and `registry.label` define the permission and the label.  Allow `packages.registry.permissions` as optional/override.\r\n\r\n\t      \tpermissions: [\r\n\t\t    {\r\n\t\t      label: \"Customers\" # use to override a label for a registry label\r\n\t\t      permission: \"dashboard/customers\" # registry route\r\n\t\t    }\r\n\t\t  ] \r\n\r\n![](https://www.dropbox.com/s/f8r58czacvs0pvo/Screenshot%202015-05-04%2019.20.26.png?dl=0)\r\n\r\n# group (by shop)\r\nNote:  using **shopId** as a **group**, we may need to ensure:\r\n\r\n\tGroup names can not start with '$' or numbers. Periods in names '.' are automatically converted to underscores. \r\n\r\nI've updated the packages permissions to be used like this:\r\n\r\n\tRoles.addUsersToRoles([user1, user2], ['dashboard/customers', 'dashboard/orders'], shopId)\r\n\tRoles.addUsersToRoles(userId, 'admin', Roles.GLOBAL_GROUP)\r\n\r\nSince groups are used, we can update the permissions in general publications like:\r\n\r\n\tRoles.userIsInRole(userId, ['admin', currentRoute], shopId))\r\n\tRoles.userIsInRole(userId, ['admin'], shopId)\r\n\r\n\r\nTo add a new permission (**client**)\r\n\r\n\tMeteor.call(\"addUserPermissions\",'khzqH84zMetraqkJ6','dashboard/settings/account',ReactionCore.getShopId())\r\n\r\nnow a role is assigned to the user, specifically for this shop:\r\n\r\n\tRoles.getRolesForUser(\"khzqH84zMetraqkJ6\",ReactionCore.getShopId());\r\n\t> [\"dashboard/settings/account\"]\r\n\r\nwithout a shop:\r\n\r\n\tRoles.getRolesForUser(\"khzqH84zMetraqkJ6\")\r\n\t[]\r\n\t\r\nwhich is represented in the `user` document  as\r\n\r\n    \"roles\" : {\r\n        \"WvrKDomkYth3THbDD\" : [ \r\n            \"dashboard/settings/account\"\r\n        ]\r\n    }\r\n\r\n\r\nIn templates, we can use the `isInRole` helper introduced by the roles package:\r\n\r\n\t{{#if isInRole 'editor,user' 'group1'}}\r\n\t{{/if}}\r\n\r\nI've retained the previous ReactionCore methods and Template helpers, although I'm not sure they are really needed.\r\n\r\n\t  hasOwnerAccess: ->\r\n\t    return Roles.userIsInRole Meteor.userId(), 'owner', @shopId\r\n\r\n\t  # dashboard access\r\n\t  hasDashboardAccess: ->\r\n\t    return Roles.userIsInRole Meteor.userId(), 'admin', @shopId\r\n\r\n\t  # permission check\r\n\t  hasPermission: (permissions) ->\r\n\t    return Roles.userIsInRole Meteor.userId(), permissions, @shopId\r\n\r\n#default roles\r\nnot defined in the registry, default system roles\r\n\r\n- view\r\n- manager\r\n- admin\r\n- owner\r\n\r\nI'll further document the default roles - as currently really only `admin` is used, but I think there should be a small limited number of roles that are used system wide (and not package dependent)\r\n\r\n# public\r\n>There is an ongoing discussion in our team about what a public package is referring to? I was under the impression that provides=userAccountDropdown packages for example are public packages?\r\n\r\n        # exposes public settings for packages\r\n        for pkg in enabledPackages\r\n          if pkg?.settings?.public\r\n            for setting, value of pkg.settings.public\r\n              ReactionCore[setting] = value\r\n\r\nI'm not even sure. Maybe your interpretation is true - there are \"public\" packages for the userAccountsDropdown after all.  But confusingly - I adopted `public` in reference to \"public settings\"  as well - the part of the registry that exposes public client variables.  We probably just need to clean up references / docs here?\r\n"}}