-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add user roles #349
Add user roles #349
Conversation
Rolify lets us add “global” and resource-specific roles to our User model. Issue #299
This commit begins the process of adding roles to the User model by: - Generating the role boilerplate and migrations - Configuring Rolify (specifically, enabling dynamic shortcuts so we can do queries like `user.is_admin?` or `user.is_insights_user?`) - Adding Role fixtures It also moves the Devise stuff in the User model up next to Rolify, with the idea that this sort of model-inheritance stuff should come before the model-definition stuff. Issue #299
This is a consequential commit. Previously, we were defining admins by the presence of a `super_admin` attribute on the `User` model. Now, we’re using Rolify with an `admin` role. Consequently, this commit: - Adds a (reversible) migration which finds all users with the `super_admin` attribute and adds the `:admin` role to them - Updates the seeds file to create the admin user - Removes the `User#super_admin?` method and converts all use of it to the `User#is_admin?` dynamic method created by Rolify - Updates the `User` fixtures and tests - Updates the `ARCHITECTURE.md` user model documentation Issue #299
This commit adds the `new_user` and `insights_user` roles to users that we create from applicants. It doesn’t do this to all new users using an `after_create` callback on the `User` model, as suggested by the Rolify docs, because we want more control over when we assign these roles. Issue #299
The `new_user` role distinguishes users who haven’t been through setup yet from those who have. This commit removes that role during account creation. Issue #299
Prior to the existence of our roles and the `new_user` role, we were using `user.sign_in_count` as a proxy for whether a user was already setup, and thus whether we could send them setup instructions. Now, we use the existence of the `new_user` role instead, as it’s more explicitly intended for this. Issue #299
333f161
to
ae85c53
Compare
This PR is tripping up Rubocop with two offenses:
I'd like to create the following two exceptions: Rails/HasAndBelongsToMany:
Enabled: true
Exclude:
# Rolify uses HABTM. Despite a decade of the community attempting to implement
# `has_many: through`, it still struggles mightily with it. Let's make an exception.
- app/models/role.rb Rolify uses HABTM and, judging by the literal decade of issues and PRs attempting to implement We should either ditch Rolify over this, or make an exception for this case. # Join tables don't really need timestamps
Rails/CreateTableWithTimestamps:
Exclude:
- db/migrate/20220919194501_rolify_create_roles.rb This one's pretty straightforward. We could create timestamps, but as that preexisting comment says, a true dumb join table doesn't really need them. |
Running tests gives me two errors (below):
|
Do it, sounds good to me! |
Now that we have roles, we can target users more specifically for specific tests. We also don’t need some of the duplicate test fixtures. Issue #299
Since adding Rolify, we are triggering two significant Rubocop offenses: - `has_and_belongs_to_many` is frowned upon in favor of `has_many :through`, but Rolify still uses the former. There have been many attempts to resolve this (see the Rolify issues and PRs) over the past decade, but none have fully landed. It’s beyond us to try and wrestle this into existence, so we’re going to make an exception and move on. - The HABTM join table has no timestamps, which is also frowned upon. We genuinely don’t care, however, and so are making an exception. Issue #299
ae85c53
to
d3a4f3e
Compare
😱 You're right! I'm not sure how I missed this, apologies. Didn't fully complete the references to the new users fixtures. Fixed and force-pushed!
Done! This checks clean now. Could I get a re-review @cguess? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One little question, but otherwise you're good to go.
This commit addresses some excellent @cguess feedback in PR #349: - Disable the Rolify `config.remove_role_if_empty`, which would purge unused roles automatically once the last resource used them. We don’t want this until we know that we do. - Seeds the database with the actual known/defined roles. - Updates the documentation about our architecture with the roles. Issue #299
This PR adds the concept of user roles to the site, and converts our determination of "what is an admin?" to use it.
It adds the Rolify gem (as determined in #282), which lets us add roles ad-hoc both "globally" (applies to the user everywhere) and per-resource (e.g. "user can moderate this particular archive item"), although we're only using the global roles. Roles are non-exclusive; a user can have multiple roles at once.
We currently have four roles:
new_user
is assigned duringUser
creation, and it semantically means "this user has not yet completed their setup process". This role is removed when the user follows the link in their email and chooses their password.insights_user
is also assigned duringUser
creation, and it semantically means "this user is approved to use the Insights site". This is a little bit unnecessary since all users can use the site, but I think it's good to be explicit and look to a future where this might not be the case (e.g., Vault-only users).media_vault_user
are users who have the right to use Media Vaultadmin
are users who are administrators of the siteThe only role that is currently used for any gatekeeping is
admin
, which replaces thesuper_admin
attribute on theUser
model. Rolify provides dynamic methods (defined during app boot and during new role creation, not through "method missing") for each role, e.g.is_admin?
oris_new_user?
, and we make use of those.Testing:
bundle install
rails db:reset
← you really should do a full reset if possible, to get all the new seedsrails t
of course[email protected]
and[email protected]
Closes #299