Role-based tab visibility, route enforcement, and audit trail #107
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Feature
Lineage
Parent of #115 (Keycloak login — DONE). Scoped during multi-user planning session (2026-06-04), rewritten 2026-06-07 after #115 shipped.
Repo
ldraney/landscaping-assistantUser Story
As a business owner
I want each user to see only the tabs and actions their role allows
So that crew members can't accidentally edit property data and I can see who changed what
Context
Keycloak login is live (#115, PR #134). Users can log in via OmniAuth Authorization Code + PKCE and their session stores
username,email, androles(fromrealm_access.rolesin the ID token). Five realm roles exist:admin,lead,member,client,super_admin.What's missing: the app doesn't use those roles yet. Every route is open, every tab is visible, and changes aren't tracked by user. This ticket wires up role-based access control.
Five roles, escalating access:
client— Person icon only (My Property / My Profile)member— + Today tablead— Today + Properties tabsadmin— Today + Week + Properties + Crew tabssuper_admin— same as admin + Platform view under Person iconNav layout (5 slots, Person always centered in slot 3):
Audit trail: PaperTrail gem tracks every create/update/destroy on all models with
whodunnitset fromcurrent_user[:username].Auth enforcement:
authenticate_user!(already in ApplicationController) applied as abefore_actionon controllers that require login. Role checks viacurrent_user_has_role?(already in ApplicationController).File Targets
Files to create:
config/initializers/paper_trail.rb— whodunnit config from sessiondb/migrate/*_add_paper_trail.rb— versions table migrationapp/controllers/crew_controller.rb— Crew tab (admin only), stub for nowapp/views/crew/index.html.erb— Crew tab placeholderFiles to modify:
Gemfile— addpaper_trailapp/views/layouts/application.html.erb— role-based bottom nav (5 slots, conditional tabs)app/controllers/application_controller.rb— addbefore_action :authenticate_user!globally, addrequire_rolehelper, set PaperTrail whodunnitapp/controllers/properties_controller.rb—require_role(:lead, :admin, :super_admin)app/controllers/work_queue_items_controller.rb—require_role(:member, :lead, :admin, :super_admin)app/controllers/weeks_controller.rb—require_role(:admin, :super_admin)app/controllers/uploads_controller.rb— role check for upload actionsapp/models/property.rb—has_paper_trailapp/models/work_queue_item.rb—has_paper_trailapp/models/upload.rb—has_paper_trailapp/models/service.rb—has_paper_trailapp/assets/stylesheets/application.css— nav adjustments for role-based tab visibilityconfig/routes.rb— add crew routesFiles NOT to touch:
app/models/user.rb— does not exist, should not be created. Keycloak is the user store.config/initializers/omniauth.rb— already configured, don't changeapp/controllers/sessions_controller.rb— already working, don't changeAcceptance Criteria
authenticate_user!enforced globally — unauthenticated requests redirect to Keycloak loginsuper_adminrole sees same as admin (Platform view is a separate ticket)require_rolehelper rejects users without the required role (403 or redirect)whodunnitrecords the Keycloak usernamekeycloak_configured?is false)Test Expectations
bundle exec rspecConstraints
current_userreturns{username:, email:, roles:}hash from session — use itkeycloak_configured?)Checklist
Related
docs/user-stories-auth.md— role definitions and nav layoutdocs/app-architecture.md— architecture and data modellandscaping-assistant— projectldraney referenced this issue2026-06-05 04:06:45 +00:00
ldraney referenced this issue2026-06-05 11:25:04 +00:00
ldraney referenced this issue2026-06-06 20:55:37 +00:00
Keycloak auth with direct grant, roles, and audit trailto Role-based tab visibility, route enforcement, and audit trail