Tito-backed magic-link auth, admin UI, and brand styling#4
Merged
Conversation
Port the ashevillagers auth flow: users enter their email, we check our DB first, fall back to Tito API, auto-create a user from their ticket, then email a 30-day magic link. No passwords. Single User model with three roles (attendee, volunteer, admin); admins are seeded in db/seeds.rb and never overwritten by Tito sync. Admin UI at /admin for user CRUD, bulk Tito sync, and DB-backed Configuration management for Tito credentials and email_from. Ruby bumped to 3.4.4 for Rails 8.1.3 compatibility.
Pull the template branch's navbar/footer/ridge-bg layout, logo, colfax font, and the blueridgeruby.com class-name system. Restyle all session views (new, callback, not_registered) and the dashboard to use the brand palette (navy text, red gradient CTAs, ridge background). Give the admin area a matching navy top bar and brand-consistent forms, tables, and role badges. Extend application.css with form/card/button/ alert/table/badge utilities on top of the template's base. Also add test/system/ scaffolding so bin/rails test:system runs cleanly and a brakeman.ignore entry for the admin-only role mass-assignment (guarded by require_admin! on every action).
…link-auth # Conflicts: # .ruby-version # app/assets/stylesheets/application.css # config/routes.rb # db/schema.rb
|
🚅 Deployed to the ruby-embassy-pr-4 environment in ruby-embassy
|
The Dockerfile has `# check=error=true`, which promotes BuildKit lint
warnings to hard errors. The shell-form CMD from the Railway setup
tripped JSONArgsRecommended and blocked the build.
Use JSON-form CMD with `sh -c` so `${PORT}` still expands at runtime,
and `exec` so SIGTERM is forwarded directly to the Rails process
instead of being swallowed by the shell. Defaults PORT to 3000 for
local `docker run`.
Railway deploys booted into a PG::UndefinedTable error: the app eager- loaded ApplicationMailer, which reads email_from from the configurations table at class-load time, but the table didn't exist yet because migrations had never run. The root cause was the CMD shape. bin/docker-entrypoint only runs db:prepare when the last two args are exactly `./bin/rails server`, and the previous `sh -c "..."` form hid those args behind the shell. Switch to the Rails 8 default `CMD ["./bin/thrust", "./bin/rails", "server"]`, which: - is JSON form, so the Dockerfile linter passes - matches the entrypoint pattern, so db:prepare runs before Rails boots - lets Thruster read Railway's $PORT natively (no shell expansion needed) - keeps signal forwarding correct (Thruster is PID 1)
Thruster 0.1.20 binds to $HTTP_PORT (default 80), but Railway routes traffic to whatever it set $PORT to. The deploy was healthy (migrations ran, Puma was up on 3000 as Thruster's upstream) but Railway's router got 502s because no one was listening on $PORT. Propagate PORT → HTTP_PORT in the server-startup branch of the entrypoint. Respects an explicit HTTP_PORT if the caller set one, and falls back to 80 (Thruster's default) otherwise — so local `docker run` still works without either var set.
Hardcode the mailer sender to hello@blueridgeruby.com and read tito_api_token / tito_account_slug / tito_event_slug from ENV instead of a DB-backed Configuration table. Deletes ~200 lines of metaprogramming (Configurable concern, CurrentAttributes loader, secret masking, admin CRUD, views) we were maintaining to manage four string values. Removes the production boot hazard: ApplicationMailer no longer queries the DB at class-load time, so eager loading succeeds on a fresh database before migrations have run. Keeps the per-user tito_account_slug / tito_event_slug columns and the memorialize_tito_config before_save callback. ENV holds the *current* event's slugs (used by Tito API calls); each user's row snapshots the slugs that were in force when their ticket was linked (used by admin_ticket_url). That preserves correct historical dashboard links across year-over-year redeploys. Railway needs: TITO_API_TOKEN, TITO_ACCOUNT_SLUG, TITO_EVENT_SLUG (plus the existing POSTMARK_API_TOKEN).
3f93c42 to
b12e27c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
blueridgeruby.com/#register./adminwith user CRUD, bulk Tito sync, and a DB-backedConfigurationstore for the Tito API token/slugs and sender address (admins edit live, no redeploys); Jeremy Smith is seeded as the sole admin andadminrole is never overwritten by syncs.application.csswith card/button/form/alert/table/badge utilities, navy + red-gradient palette throughout.letter_openerin development via the existingemail_fromconfig, and adds a justifiedconfig/brakeman.ignoreentry for the admin-gated role mass-assignment so CI is green.Test plan
/session/new, enterjeremy@blueridgeruby.com, click the magic link fromtmp/letter_opener, land on/dashboardwith the Admin badge/session/new→ see the "no ticket found" page with the Register CTA (requires Tito creds configured; otherwise "try again later" alert is expected)/admin/configurationsas admin, settito_api_token/tito_account_slug/tito_event_slug/email_from, then click "Sync from Tito" on/admin/usersand confirm attendees are imported/dashboardand/admin/*unauthenticated → redirected to/session/newbin/brakeman --no-pager && bin/bundler-audit && bin/importmap audit && bin/rubocop -f github && bin/rails db:test:prepare test test:system— all green