identity-vault/config/routes.rb
nora 9998147a4e
epic: overhaul program management experience (#188)
* temp commit

* lemme do it

* nope

* let them do it too

* collab invite model

* better visuals on progman

* waow

* danger will robinson

* show apps on backend & link user

* first pass on app auditability!

* no lastnaming admins

* async frame that shit!

* waugh

* can't add yourself

* fix reinvite

* sidebar badging

* lint...

* gotta be on the app!

* let that get rescued by applcon

* already in revoke_all_authorizations

* woag

* the routes you grew up with no longer exist

* what would the UI for that even be?

* sorch

* much better!

* frickin validations
2026-03-02 22:15:13 -05:00

430 lines
32 KiB
Ruby

# == Route Map
#
# Prefix Verb URI Pattern Controller#Action
# native_oauth_authorization GET /oauth/authorize/native(.:format) doorkeeper/authorizations#show
# oauth_authorization GET /oauth/authorize(.:format) doorkeeper/authorizations#new
# DELETE /oauth/authorize(.:format) doorkeeper/authorizations#destroy
# POST /oauth/authorize(.:format) doorkeeper/authorizations#create
# oauth_token POST /oauth/token(.:format) doorkeeper/tokens#create
# oauth_revoke POST /oauth/revoke(.:format) doorkeeper/tokens#revoke
# oauth_introspect POST /oauth/introspect(.:format) doorkeeper/tokens#introspect
# oauth_applications GET /oauth/applications(.:format) doorkeeper/applications#index
# POST /oauth/applications(.:format) doorkeeper/applications#create
# new_oauth_application GET /oauth/applications/new(.:format) doorkeeper/applications#new
# edit_oauth_application GET /oauth/applications/:id/edit(.:format) doorkeeper/applications#edit
# oauth_application GET /oauth/applications/:id(.:format) doorkeeper/applications#show
# PATCH /oauth/applications/:id(.:format) doorkeeper/applications#update
# PUT /oauth/applications/:id(.:format) doorkeeper/applications#update
# DELETE /oauth/applications/:id(.:format) doorkeeper/applications#destroy
# oauth_authorized_applications GET /oauth/authorized_applications(.:format) doorkeeper/authorized_applications#index
# oauth_authorized_application DELETE /oauth/authorized_applications/:id(.:format) doorkeeper/authorized_applications#destroy
# oauth_token_info GET /oauth/token/info(.:format) doorkeeper/token_info#show
# letter_opener_web /letter_opener LetterOpenerWeb::Engine
# active_storage_encryption /encrypted_blobs ActiveStorageEncryption::Engine
# static_pages_index GET /static_pages/index(.:format) static_pages#index
# credentials_enroll_window GET /credentials/enroll_window(.:format) credentials#enroll_window
# credentials_enroll GET /credentials/enroll(.:format) credentials#enroll
# backend_identities_index GET /backend/identities/index(.:format) backend/identities#index
# backend_identities_show GET /backend/identities/show(.:format) backend/identities#show
# backend_good_job /backend/good_job GoodJob::Engine
# backend_audit_logs GET /backend/audit_logs(.:format) backend/audit_logs#index
# backend_root GET /backend(.:format) backend/static_pages#index
# backend_login GET /backend/login(.:format) backend/static_pages#login
# backend_slack_auth GET /backend/auth/slack(.:format) backend/sessions#new
# backend_auth_slack_callback GET /backend/auth/slack/callback(.:format) backend/sessions#create
# backend_fake_slack_callback_for_dev POST /backend/auth/slack/fake(.:format) backend/sessions#fake_slack_callback_for_dev
# deactivate_backend_user POST /backend/users/:id/deactivate(.:format) backend/users#deactivate
# activate_backend_user POST /backend/users/:id/activate(.:format) backend/users#activate
# backend_users GET /backend/users(.:format) backend/users#index
# POST /backend/users(.:format) backend/users#create
# new_backend_user GET /backend/users/new(.:format) backend/users#new
# edit_backend_user GET /backend/users/:id/edit(.:format) backend/users#edit
# backend_user GET /backend/users/:id(.:format) backend/users#show
# PATCH /backend/users/:id(.:format) backend/users#update
# PUT /backend/users/:id(.:format) backend/users#update
# DELETE /backend/users/:id(.:format) backend/users#destroy
# pending_backend_verifications GET /backend/verifications/pending(.:format) backend/verifications#pending
# approve_backend_verification PATCH /backend/verifications/:id/approve(.:format) backend/verifications#approve
# reject_backend_verification PATCH /backend/verifications/:id/reject(.:format) backend/verifications#reject
# backend_verifications GET /backend/verifications(.:format) backend/verifications#index
# backend_verification GET /backend/verifications/:id(.:format) backend/verifications#show
# backend_identities GET /backend/identities(.:format) backend/identities#index
# backend_identity GET /backend/identities/:id(.:format) backend/identities#show
# backend_programs GET /backend/programs(.:format) backend/programs#index
# POST /backend/programs(.:format) backend/programs#create
# new_backend_program GET /backend/programs/new(.:format) backend/programs#new
# edit_backend_program GET /backend/programs/:id/edit(.:format) backend/programs#edit
# backend_program GET /backend/programs/:id(.:format) backend/programs#show
# PATCH /backend/programs/:id(.:format) backend/programs#update
# PUT /backend/programs/:id(.:format) backend/programs#update
# DELETE /backend/programs/:id(.:format) backend/programs#destroy
# backend_break_glass POST /backend/break_glass(.:format) backend/break_glass#create
# root GET / static_pages#index
# check_your_email_sessions GET /sessions/check_your_email(.:format) sessions#check_your_email
# verify_sessions GET /sessions/verify(.:format) sessions#verify
# confirm_sessions POST /sessions/confirm(.:format) sessions#confirm
# new_sessions GET /sessions/new(.:format) sessions#new
# sessions DELETE /sessions(.:format) sessions#destroy
# POST /sessions(.:format) sessions#create
# welcome_onboarding GET /onboarding/welcome(.:format) onboardings#welcome
# signin_onboarding GET /onboarding/signin(.:format) onboardings#signin
# basic_info_onboarding GET /onboarding/basic_info(.:format) onboardings#basic_info
# POST /onboarding/basic_info(.:format) onboardings#create_basic_info
# document_onboarding GET /onboarding/document(.:format) onboardings#document
# POST /onboarding/document(.:format) onboardings#create_document
# submitted_onboarding GET /onboarding/submitted(.:format) onboardings#submitted
# continue_onboarding GET /onboarding/continue(.:format) onboardings#continue
# onboarding GET /onboarding(.:format) onboardings#show
# addresses GET /addresses(.:format) addresses#index
# POST /addresses(.:format) addresses#create
# new_address GET /addresses/new(.:format) addresses#new
# edit_address GET /addresses/:id/edit(.:format) addresses#edit
# address GET /addresses/:id(.:format) addresses#show
# PATCH /addresses/:id(.:format) addresses#update
# PUT /addresses/:id(.:format) addresses#update
# DELETE /addresses/:id(.:format) addresses#destroy
# api_v1_identities GET /api/v1/identities(.:format) api/v1/identities#index
# api_v1_identity GET /api/v1/identities/:id(.:format) api/v1/identities#show
# api_v1_me GET /api/v1/me(.:format) api/v1/identities#me
# api_v1_hcb GET /api/v1/hcb(.:format) api/v1/hcb#show
# link_slack_account GET /slack/link(.:format) slack_accounts#new
# slack_account_callback GET /slack/callback(.:format) slack_accounts#create
# rails_health_check GET /up(.:format) rails/health#show
# rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create
# rails_relay_inbound_emails POST /rails/action_mailbox/relay/inbound_emails(.:format) action_mailbox/ingresses/relay/inbound_emails#create
# rails_sendgrid_inbound_emails POST /rails/action_mailbox/sendgrid/inbound_emails(.:format) action_mailbox/ingresses/sendgrid/inbound_emails#create
# rails_mandrill_inbound_health_check GET /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#health_check
# rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create
# rails_mailgun_inbound_emails POST /rails/action_mailbox/mailgun/inbound_emails/mime(.:format) action_mailbox/ingresses/mailgun/inbound_emails#create
# rails_conductor_inbound_emails GET /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#index
# POST /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#create
# new_rails_conductor_inbound_email GET /rails/conductor/action_mailbox/inbound_emails/new(.:format) rails/conductor/action_mailbox/inbound_emails#new
# rails_conductor_inbound_email GET /rails/conductor/action_mailbox/inbound_emails/:id(.:format) rails/conductor/action_mailbox/inbound_emails#show
# new_rails_conductor_inbound_email_source GET /rails/conductor/action_mailbox/inbound_emails/sources/new(.:format) rails/conductor/action_mailbox/inbound_emails/sources#new
# rails_conductor_inbound_email_sources POST /rails/conductor/action_mailbox/inbound_emails/sources(.:format) rails/conductor/action_mailbox/inbound_emails/sources#create
# rails_conductor_inbound_email_reroute POST /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format) rails/conductor/action_mailbox/reroutes#create
# rails_conductor_inbound_email_incinerate POST /rails/conductor/action_mailbox/:inbound_email_id/incinerate(.:format) rails/conductor/action_mailbox/incinerates#create
# rails_service_blob GET /rails/active_storage/blobs/redirect/:signed_id/*filename(.:format) active_storage/blobs/redirect#show
# rails_service_blob_proxy GET /rails/active_storage/blobs/proxy/:signed_id/*filename(.:format) active_storage/blobs/proxy#show
# GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs/redirect#show
# rails_blob_representation GET /rails/active_storage/representations/redirect/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations/redirect#show
# rails_blob_representation_proxy GET /rails/active_storage/representations/proxy/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations/proxy#show
# GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations/redirect#show
# rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
# update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
# rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
#
# Routes for LetterOpenerWeb::Engine:
# letters GET / letter_opener_web/letters#index
# clear_letters POST /clear(.:format) letter_opener_web/letters#clear
# letter GET /:id(/:style)(.:format) letter_opener_web/letters#show
# delete_letter POST /:id/delete(.:format) letter_opener_web/letters#destroy
# GET /:id/attachments/:file(.:format) letter_opener_web/letters#attachment {file: /[^\/]+/}
#
# Routes for ActiveStorageEncryption::Engine:
# encrypted_blob_put PUT /blob/:token(.:format) active_storage_encryption/encrypted_blobs#update
# create_encrypted_blob_direct_upload POST /blob/direct-uploads(.:format) active_storage_encryption/encrypted_blobs#create_direct_upload
# encrypted_blob_streaming_get GET /blob/:token/*filename(.:format) active_storage_encryption/encrypted_blob_proxy#show
#
# Routes for GoodJob::Engine:
# root GET / good_job/jobs#redirect_to_index
# mass_update_jobs GET /jobs/mass_update(.:format) redirect(301, path: jobs)
# PUT /jobs/mass_update(.:format) good_job/jobs#mass_update
# discard_job PUT /jobs/:id/discard(.:format) good_job/jobs#discard
# force_discard_job PUT /jobs/:id/force_discard(.:format) good_job/jobs#force_discard
# reschedule_job PUT /jobs/:id/reschedule(.:format) good_job/jobs#reschedule
# retry_job PUT /jobs/:id/retry(.:format) good_job/jobs#retry
# jobs GET /jobs(.:format) good_job/jobs#index
# job GET /jobs/:id(.:format) good_job/jobs#show
# DELETE /jobs/:id(.:format) good_job/jobs#destroy
# metrics_primary_nav GET /jobs/metrics/primary_nav(.:format) good_job/metrics#primary_nav
# metrics_job_status GET /jobs/metrics/job_status(.:format) good_job/metrics#job_status
# retry_batch PUT /batches/:id/retry(.:format) good_job/batches#retry
# batches GET /batches(.:format) good_job/batches#index
# batch GET /batches/:id(.:format) good_job/batches#show
# enqueue_cron_entry POST /cron_entries/:cron_key/enqueue(.:format) good_job/cron_entries#enqueue
# enable_cron_entry PUT /cron_entries/:cron_key/enable(.:format) good_job/cron_entries#enable
# disable_cron_entry PUT /cron_entries/:cron_key/disable(.:format) good_job/cron_entries#disable
# cron_entries GET /cron_entries(.:format) good_job/cron_entries#index
# cron_entry GET /cron_entries/:cron_key(.:format) good_job/cron_entries#show
# processes GET /processes(.:format) good_job/processes#index
# performance_index GET /performance(.:format) good_job/performance#index
# performance GET /performance/:id(.:format) good_job/performance#show
# pauses POST /pauses(.:format) good_job/pauses#create
# DELETE /pauses(.:format) good_job/pauses#destroy
# GET /pauses(.:format) good_job/pauses#index
# cleaner_index GET /cleaner(.:format) good_job/cleaner#index
# frontend_module GET /frontend/modules/:version/:id(.:format) good_job/frontends#module {version: "4-10-2", format: "js"}
# frontend_static GET /frontend/static/:version/:id(.:format) good_job/frontends#static {version: "4-10-2"}
class SuperAdminConstraint
def self.matches?(request)
session_token = request.cookie_jar.encrypted[:session_token]
return false unless session_token
session = IdentitySession.not_expired.find_by(session_token: session_token)
return false unless session&.identity
session.identity.backend_user&.super_admin?
end
end
Rails.application.routes.draw do
use_doorkeeper_openid_connect
use_doorkeeper
mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development?
mount ActiveStorageEncryption::Engine, at: "/encrypted_blobs"
# Image conversion routes
get "static_pages/index"
namespace :backend do
get "identities/index"
get "identities/show"
constraints SuperAdminConstraint do
mount GoodJob::Engine => "good_job"
mount Audits1984::Engine => "/console_audit"
mount Flipper::UI.app(Flipper) => "/flipper", as: :flipper
end
resources :audit_logs, only: [ :index ]
get "dashboard", to: "dashboard#show", as: :dashboard
get "analytics", to: "analytics#show", as: :analytics
root "static_pages#index", as: :root
get "login", to: "static_pages#login", as: :login
get "session_dump", to: "static_pages#session_dump", as: :session_dump unless Rails.env.production?
get "kbar/search", to: "kbar#search", as: :kbar_search
get "identity_picker/search", to: "identity_picker#search", as: :identity_picker_search
post "hints/mark_seen", to: "hints#mark_seen", as: :hints_mark_seen
resources :users do
member do
post :deactivate
post :activate
end
end
resources :verifications, only: [ :index, :show ] do
collection do
get :pending
end
member do
patch :approve
patch :reject
patch :ignore
end
end
resources :identities do
member do
post :clear_slack_id
post :reprovision_slack
get :new_vouch
post :create_vouch
post :promote_to_full_user
end
end
# Programs management moved to DeveloperAppsController (unified UI)
post "/break_glass", to: "break_glass#create"
scope :json do
defaults format: :json do
end
end
end
root "static_pages#home"
get "/welcome", to: "static_pages#welcome", as: :welcome
get "/slack-id", to: "static_pages#slack_id", as: :slack_id
get "/oauth/welcome", to: "static_pages#oauth_welcome", as: :oauth_welcome
get "/security", to: "static_pages#security", as: :security
get "/activity", to: "audit_logs#index", as: :audit_logs
# Login system routes
resource :sessions, only: [ :new, :create, :destroy ] do
collection do
get :check_your_email
get :verify
post :confirm
end
end
resource :identity, only: [ :edit, :update ] do
collection do
post :toggle_2fa
get :confirm_disable_2fa
end
end
resources :email_changes, only: [ :new, :create, :show ] do
member do
get :cancel, action: :cancel_confirmation
post :cancel
end
collection do
get "verify/old", to: "email_changes#verify_old", as: :verify_old
post "verify/old", to: "email_changes#confirm_verify_old", as: :confirm_verify_old
get "verify/new", to: "email_changes#verify_new", as: :verify_new
post "verify/new", to: "email_changes#confirm_verify_new", as: :confirm_verify_new
end
end
get "/signup", to: "identities#new", defaults: { route_context: "signup" }, as: :signup
post "/signup", to: "identities#create", defaults: { route_context: "signup" }
get "/migrate", to: "identities#new", defaults: { route_context: "migrate" }, as: :migrate
post "/migrate", to: "identities#create", defaults: { route_context: "migrate" }
get "/join/:slug", to: "identities#new", defaults: { route_context: "join" }, as: :join
post "/join/:slug", to: "identities#create", defaults: { route_context: "join" }
get "/slack", to: "identities#new", defaults: { route_context: "join", slug: "slack" }, as: :slack_join
post "/slack", to: "identities#create", defaults: { route_context: "join", slug: "slack" }
get "/login", to: "logins#new", as: :login
post "/login", to: "logins#create"
get "/login/:id", to: "logins#show", as: :login_attempt
post "/login/:id/verify", to: "logins#verify", as: :verify_login_attempt
post "/login/:id/resend", to: "logins#resend", as: :resend_login_attempt
get "/login/:id/totp", to: "logins#totp", as: :totp_login_attempt
post "/login/:id/totp", to: "logins#verify_totp", as: :verify_totp_login_attempt
get "/login/:id/backup_code", to: "logins#backup_code", as: :backup_code_login_attempt
post "/login/:id/backup_code", to: "logins#verify_backup_code", as: :verify_backup_code_login_attempt
get "/login/:id/webauthn", to: "logins#webauthn", as: :webauthn_login_attempt
post "/login/:id/webauthn/options", to: "logins#webauthn_options", as: :webauthn_options_login_attempt
post "/login/:id/webauthn/verify", to: "logins#verify_webauthn", as: :verify_webauthn_login_attempt
post "/login/:id/webauthn/skip", to: "logins#skip_webauthn", as: :skip_webauthn_login_attempt
delete "/logout", to: "sessions#logout", as: :logout
get "/verifications/new", to: "verifications#new", as: :new_verifications
get "/verifications/status", to: "verifications#status", as: :verification_status
get "/verifications/:id", to: "verifications#show", as: :verification_step
put "/verifications/:id", to: "verifications#update", as: :update_verification_step
resources :addresses do
collection do
get :program_create_address
end
member do
patch :make_primary
end
end
namespace :portal do
get "verify", to: "verifications#start"
get "verify/document", to: "verifications#portal", as: :verify_document
post "verify/document", to: "verifications#create"
delete "verify", to: "verifications#cancel"
get "address", to: "addresses#portal"
post "address", to: "addresses#create"
get "address/done", to: "addresses#done", as: :address_done
end
resources :identity_sessions, only: [ :index, :destroy ] do
collection do
delete :destroy_all
end
end
resources :identity_totps, only: [ :index, :new, :destroy ] do
member do
post :verify
end
end
resources :identity_webauthn_credentials, path: "passkeys", only: [ :index, :new, :create, :destroy ] do
collection do
post :options
end
end
# Step-up authentication flow
get "/step_up", to: "step_up#new", as: :new_step_up
post "/step_up/verify", to: "step_up#verify", as: :verify_step_up
post "/step_up/send_email_code", to: "step_up#send_email_code", as: :send_step_up_email_code
post "/step_up/resend_email", to: "step_up#resend_email", as: :resend_step_up_email
post "/step_up/webauthn/options", to: "step_up#webauthn_options", as: :step_up_webauthn_options
post "/step_up/webauthn/verify", to: "step_up#verify_webauthn", as: :verify_step_up_webauthn
resources :identity_backup_codes, only: [ :index, :create ] do
patch :confirm, on: :collection
end
resources :authorized_applications, only: [ :index, :destroy ]
resources :developer_apps, path: "developer/apps" do
member do
post :rotate_credentials
post :revoke_all_authorizations
get :activity_log
end
resources :collaborators, only: [ :create, :destroy ],
controller: "developer_app_collaborators"
resources :collaborator_invites, only: [], controller: "developer_app_collaborator_invitations" do
member do
post :accept
post :decline
post :cancel
end
end
end
namespace :api do
namespace :v1 do
resources :identities, only: [ :show, :index ] do
member do
post :set_slack_id
end
end
get "/me", to: "identities#me"
get "/hcb", to: "hcb#show"
get "/health_check", to: "health_check#show"
end
namespace :external do
get "/check", to: "identities#check"
options "/check", to: "identities#options"
end
end
get "/api/external", to: "static_pages#external_api_docs"
get "/slack_staging", to: "static_pages#slack_staging" if Rails.env.staging?
# Documentation routes
get "/docs", to: "docs#index", as: :docs
get "/docs/:slug", to: "docs#show", as: :doc
# Slack interactivity routes
namespace :slack do
post "/interactivity", to: "interactivity#create"
end
scope :saml do
get "/metadata", to: "saml#metadata"
get "/welcome", to: "saml#welcome", as: :saml_welcome
post "/idp_initiated/:slug", to: "saml#idp_initiated", as: :idp_initiated_saml
get "/auth", to: "saml#sp_initiated_get"
end
# Error pages
match "/404", to: "errors#not_found", via: :all
match "/422", to: "errors#unprocessable_entity", via: :all
match "/500", to: "errors#internal_server_error", via: :all
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
# Can be used by load balancers and uptime monitors to verify that the app is live.
get "up" => "rails/health#show", as: :rails_health_check
# Render dynamic PWA files from app/views/pwa/* (remember to link manifest in application.html.erb)
# get "manifest" => "rails/pwa#manifest", as: :pwa_manifest
# get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker
# Defines the root path route ("/")
# root "posts#index"
end