Authentication and Session Management#
Sure uses a cookie-based session authentication system built on Rails conventions. The three core pieces are: the Authentication controller concern (enforces auth on every request), the Current model (carries per-request context), and the ImpersonationSession model (supports admin impersonation with consent).
Request-Scoped Context: Current#
app/models/current.rb is a subclass of ActiveSupport::CurrentAttributes. It holds the active session, the user_agent, and the ip_address for each request.
The key accessors are :
| Method | Returns |
|---|---|
Current.user | The effective user — impersonated user if active, otherwise the session owner |
Current.true_user | Always the session owner, regardless of impersonation state |
Current.impersonated_user | Non-nil only during an active impersonation session |
Current.accessible_accounts / Current.accessible_entries | Scoped to the effective user's family |
Authentication Concern#
app/controllers/concerns/authentication.rb is included in ApplicationController and installs three before_action callbacks :
set_request_details— writesCurrent.user_agentandCurrent.ip_addressfrom the request .authenticate_user!— looks up aSessionrecord via a signed:session_tokencookie and assigns it toCurrent.session. Unauthenticated requests are redirected tonew_session_url(ornew_registration_urlon self-hosted first boot) .set_sentry_user— tags the Sentry scope with the current user whenSENTRY_DSNis set .
Controllers that don't need authentication call skip_authentication (e.g., the sessions and registrations controllers).
Session creation writes a permanent, httponly signed cookie :
cookies.signed.permanent[:session_token] = { value: session.id, httponly: true }
Session Model#
app/models/session.rb is an ActiveRecord model that belongs to a User and, optionally, an ImpersonationSession via the active_impersonator_session association. The presence of active_impersonator_session on the session record is what makes Current.impersonated_user non-nil .
Admin Impersonation#
Impersonation is consent-based and restricted to super_admin users. The flow:
super admin creates request → impersonated user approves → super admin joins → actions logged → complete/leave
Model: ImpersonationSession enforces three hard constraints at the model layer :
- Impersonator must be a
super_admin - Impersonated user cannot be a
super_admin - A user cannot impersonate themselves
Status lifecycle: pending → in_progress → complete (or rejected) .
Controller: ImpersonationSessionsController orchestrates the workflow :
create— super admin requests impersonation of a userjoin— super admin attaches the approvedImpersonationSessionto their ownCurrent.sessionleave— super admin detaches (setsactive_impersonator_session: nil)approve/reject— the impersonated user accepts or declinescomplete— either party ends the session
The Impersonatable concern (app/controllers/concerns/impersonatable.rb) auto-logs each request to ImpersonationSessionLog (app/models/impersonation_session_log.rb) whenever an active impersonation session exists, capturing controller, action, path, HTTP method, IP, and user agent.
User Roles and Fixtures#
The application has four roles: guest, member, admin, and super_admin. Support staff (impersonators) are provisioned as super_admin .
Test fixtures in test/fixtures/users.yml pre-hash passwords using BCrypt::Engine::MIN_COST to keep test sign-in fast . All fixture users share the same password returned by user_password_test .
Test Helpers#
Integration / unit tests (ActiveSupport::TestCase, ActionDispatch::IntegrationTest):
sign_in(user) posts credentials to sessions_path to establish a real cookie-based session :
post sessions_path, params: { email: user.email, password: user_password_test }
System tests (ApplicationSystemTestCase):
sign_in(user) drives the actual login form via Capybara and waits for "Welcome back, #{user.first_name}" before continuing . login_as(user) is an alias .
sign_out clicks through the user menu .
Key Files#
| File | Purpose |
|---|---|
app/models/current.rb | Request-scoped user context via CurrentAttributes |
app/controllers/concerns/authentication.rb | before_action auth guard and session wiring |
app/models/session.rb | Persistent session record; links user to impersonation state |
app/models/impersonation_session.rb | Consent-based admin impersonation model |
app/controllers/impersonation_sessions_controller.rb | Impersonation workflow actions |
app/controllers/concerns/impersonatable.rb | Audit-log concern for impersonation activity |
app/models/impersonation_session_log.rb | Per-action audit record during impersonation |
test/test_helper.rb | sign_in helper for integration tests |
test/application_system_test_case.rb | sign_in / sign_out helpers for system tests |
test/fixtures/users.yml | Pre-hashed test user fixtures |