Alanning:roles v3 released

Changes between 2.x and 3.0

Breaking changes

  • The roles a user has assigned are no longer stored in the collection users but have been moved to a separate collection called role-assignment , available at Meteor.roleAssignment. You might need to update your schema and places you access the collections directly.

  • The roles a user has are not published automatically anymore. If you want all the roles a user has to be published automatically you can use the following code:

    Meteor.publish(null, function () {
      if (this.userId) {
        return Meteor.roleAssignment.find({ 'user._id': this.userId });
      } else {
        this.ready()
      }
    })
    
  • The behavior of getRolesForUser() used with the option fullObjects has changed. If you need the old behavior, use the code of this change-set: Meteor-Community-Packages/meteor-roles/#41d2ed493852f21cf508b5b0b76e4f8a09ae8f5c

New options

  • removeUsersFromRoles() got the option anyScope to remove all the roles a user has.
  • getRolesForUser() got the new option onlyScoped to limiting the result to only scoped permissions

Details and reasoning can be found in #270 and #276

Migration to 3.0

If you are currently using this package in a version older than 2.x, please upgrade to 2.0 first by running the migration script: https://github.com/Meteor-Community-Packages/meteor-roles/tree/v2#migration-to-20

In meteor-roles 3.0, roles are stored differently in the database. To migrate the database to the new schema, run Meteor._forwardMigrate2() on the server. Please take a backup of the users collection before migrating.

meteor shell
> Package['alanning:roles'].Roles._forwardMigrate2()

In case something fails, there is also a script available for rolling back the changes. But be warned that a backward migration takes a magnitude longer than a forward migration. To migrate the database back to the old schema, run Meteor._backwardMigrate2() on the server:

meteor shell 
> Package['alanning:roles'].Roles._backwardMigrate2()

Future of 1.x and 2.x

If you want to keep using this package in version 1.x or 2.x, I’ll support them as good as I can and help you fixing bugs and keep them compatible with upcoming Meteor versions as I can, but all future development will be focussed on the latest major version.

Going forward

At first I want to give the credits and a big thanks to @alanning and @mitar for developing the package so far. Both mentioned in #270 that their time on developing this package got very limited, which is the reason why I picked it up after moving it into the Meteor Community Packages group.

I already have some plans for the next major version in mind which will focus on tree-shaking. In all our versions, roles have been stored in a collection accessible at Meteor.roles, but this collection could equally well be imported when you want it.

I would really appreciate if this package could be an example of collaboration and team effort. Every kind of help is appreciated and very welcome!

Thanks also to @storyteller for proofreading this :blush:

19 Likes

Good to read this is still actively developed and congrats for releasing a new version! :clap:

However…

The roles a user has are not published automatically anymore.

I wonder what the design decision is for this? Is there a scenario were you would use roles and don’t want to know them in the client?

2 Likes

What was the reason for moving roles to a separate collection? I imagine that will cause a performance hit as it will require more reads, which may be minor but could increase costs at a large scale

3 Likes

Also, moving it out of the users collection would prevent it being available in the MergeBox cache via msavin/userCache, which in my case eliminated a LOT of db lookups just to check a user’s roles.

Maybe Alanning:roles could check the MergeBox cache itself, since I imagine that in most cases developers will choose to autopublish a user’s roles.

4 Likes

In my case, we grant permissions on a per-document basis (think of a file-system where you grant access to files and folders). Storing all this in the user and shipping it to the client every time a user opens the application, was getting worse over time in our example. By this change here, I think I introduced a system which easily can scale in amount of users and assignment of roles.

You can find more details in the ticket #270 in the project repository.

1 Like

As of what I saw, the database calls didn’t increase and the objects received are often smaller than in v2. I added some considerations to the original pull request #276. If you see it getting worse or see some code which you think is in risk of decreasing the performance, I’d like to hear from you.

Well - technically they will be in the MergeBox, but they won’t be part of the users document which is why the extension wouldn’t take it.

But I would be grateful if if you could create a ticket in the repository for this feature. The better if you also have a way in mind of how this could be implemented - a PR would be awesome!

By necessity doesn’t it have to increase the calls? In v2 you would only query the users collection for a single user. In v3 you will query the users collection and the roles collection for a single user, unless I’m not understanding this correctly.

1 Like

I will create a ticket for the MergeBox feature, however, I’ve just discovered a problem with the msavin:userCache approach (it’s not reactive so can only safely be used in Methods, not Publications). I’ve raised a bug on userCache here. Until we’ve (@msavin) found a work-around for that then I would steer clear of MergeBox…

Hi,

For routing purposes it is useful to know a users role, in order to prevent a user navigating to restricted pages.

I see that the new v3 behaviour does not automatically publish a user’s roles to the client.

The readme recommends publishing the user’s roles to the client like so

Meteor.publish(null, function () {
  if (this.userId) {
    return Meteor.roleAssignment.find({ 'user._id': this.userId });
  } else {
    this.ready()
  }
})

How do you rate-limit this ‘null’-named publication to protect it from abuse?

I rate-limit my publications like so:

    DDPRateLimiter.addRule(
      {
        name,
        'subscription',
        connectionId: () => true
      },
      5,
      10000
    );

Thanks

2 Likes

Well, in v2 you could give the full-fledged user-document to the function. In this case, most of the functions didn’t access the database at all - only if you gave it the users id as a string it would query the users database, for the document of the current user.

In v3, the system always queries a database called role-assignments. For backwards compatibility you can provide each function with the users document or his id. In any case, the system will query the database on the collection role-assignments, which only returns the data required - not all the other roles the user is assigned to.

If you want more, I want to encourage you to take a look at the source-code. It’s not very complicated :wink:

1 Like

Well, this is just a sample which I picked from the documentation of Meteor: Publish and subscribe | Meteor API Docs

You can, of course, take more control over this publication, which is why I added it as a sample. This is one way of doing it if you want to stay close to how v2 did it. In my application I have a more controlled way of publishing the role-assignments.

1 Like

Not a huge fan of the decision to move the roles out of the user document. I try to avoid unnecessary
publications as much as possible, as every publication means another load impact on the server.

5 Likes

I wonder if you could use a method call, with some periodic refreshes? Auto-publishing the roles set is one way to simulate how it used to work, but you might also be able to hit the database just once over a method (keeping in mind the data can go stale), and then use that somehow. I haven’t looked very closely at how we might do that, because I think the publication overhead for this in my app will be quite small. The convenience of an autopublished roles is worth the trade off for me, at least until I need more extreme scalability. Actually, it shouldn’t even be all that much more overhead than having it as part of the user document, which is also pub/sub if I understand correctly - seems more of a lateral move.

3 Likes

I’d like to elaborate a bit on this, because the separation of collections (in my eyes) does not increase the load on the server, since it’s the same amount of data processed - just now in two separate collections. In my case it even decreases.

I’m using the package redis-oplog where I can only listen to changes on a certain user on a certain scope. This way, the server doesn’t have to check for changes on roles in a different scope - as far as I know.

Another side-benefit is, that if you change a role, the value returned by Meteor.user() on the client triggers a rerun on a reactive context in v2, but not in v3.

1 Like

Has anyone had any issues running the migrate functions (either v2 or v3) on large user collections? I’ll definitely run a test first but was just curious.

I’ve been upgrading packages on a large app that is still on v1 and the idea of migrating and having extra publications has shied me away from upgrading. Especially since I don’t need the functionality or granularity.

@evolross

Well … there are some. The majority of those issues refers to installations using v1 of this package. The update mechanism for updating from v1 to v2 is not very smooth. E.g.

Another thing which could cause problems is the validation of the users document in your repository. The readme file of meteor-collection2 has a sample which should not be used together with >= v3 of the roles package.

Otherwise, please ping me if you run into any issues and I’ll see what I can do.

1 Like

We’re probably never going to migrate either, roles stored on user documents are too valuable for us.

I’m starting to think it would’ve been better to just create a new roles management package instead of bumping the existing one, since the 2 approaches are so radically different, and meet different needs.

Not a big deal to clone and maintain a v1 fork though!

4 Likes

As said, I’ll maintain them and keep them working as far as I am able to - but help is always highly appreciated.

You’re currently using v1 - what about a switch to v2? It is a bit different in the design of the individual documents, but it still stores the assignments of a role in the user-document.

1 Like

Yeah I guess we could, though quickly looking through the list of changes, there’s nothing we’re using that is improved/changed. It’s mostly renaming/deprecations, and role hierarchies, which we don’t need at the moment!

We are planning to use groups/scopes in the next months, so we might update just to stay consistent with the latest roles-management paradigm of Meteor :slight_smile: