Authorization decides what a signed-in user is allowed to do. This lesson covers modeling roles and permissions with Consul and assignable_values.
Important
Work on this lesson in
advisormode.
Learning goals
- You can explain what authorization is, how it differs from authentication, and the shapes it usually takes: roles, ownership, per-record permissions.
- You can define what each role may do in one declarative place (we use Consul powers) and enforce it in controllers.
- You can restrict the values a field may take per user, e.g. with
assignable_values, and let that drive both form options and validation. - You can show or hide UI elements according to a user's permissions without duplicating the rules that the controller enforces.
- You can trace an authorization decision in an unfamiliar app from the view back to the code that grants or denies access.
- You can test authorization without duplicating every feature spec for every role.
- You can discuss the structural choices: one controller with conditions or separate ones per role, and where authorization specs live.
Resources
Read what's new to you, skim what's familiar, skip what you already master. Stop when you can meet the learning goals.
Your agent can also generate an overview, a tutorial or an explanation for anything here, tailored to what you already know. Just ask.
- 📄 Consul README Show archive.org snapshot — declarative "powers": one place that says what a user may see and do, usable in controllers, views and tests
- 📄 assignable_values README Show archive.org snapshot — restrict an attribute to the values a user may pick, and validate it
- 📄 Solving bizarre authorization requirements with Rails — slides of our talk on modelling authorization with scopes and powers
- ▶️ Autorisierung mit RBAC, ABAC, ReBAC, PBAC – What the Heck? Show archive.org snapshot — INNOQ, German; the authorization models beyond plain roles, and which problems each solves
Exercises
Read code
- In Cards, users can be given deck-specific read/write access. Play around in the cards UI to see that functionality.
- How does the application decide whether or not to render the "Edit card" button?
- See if you can follow the code from the view that renders the button back to the code that is responsible for granting or denying access.
Role-based authorization
Use Consul and assignable_values to implement role-based authorization in MovieDB:
- Add a
User#rolefield to MovieDB. The field can be switched betweenreader/writer/adminvalues. - A reader is allowed to view all movies. A reader is not allowed to create a new movie or edit or delete an existing movie.
- A writer is like a reader, but is also allowed to create new movies. A writer can edit and delete the movies she created herself, but not movies created by other users.
- An admin is allowed to create, view and edit and delete all movies.
- The admin may change the author of any movie by picking a user option from a
<select>in the movie form. However, non-admins should only see their own user as an option in the same<select>.
Remember to add tests for your authorization code.
Tip
If you have existing dropdowns that accept a restrict list of values (e.g. genre), you can simplify their implementation with assignable_values Show archive.org snapshot .
Discuss with your mentor
Discuss with your mentor:
- We don't want to duplicate our integration tests for every screen and user role. Why?
- Where to put authorization scenarios? In an
authorization.featureor under each resource folder, like the other scenarios. - If one role has, for a given resource, more permission than another role, should we have separate controllers and views?