Class: Bible270::SessionsController
- Inherits:
-
ApplicationController
- Object
- ApplicationController
- Bible270::SessionsController
- Defined in:
- app/controllers/bible270/sessions_controller.rb
Overview
Built-in OmniAuth sign-in.
The OmniAuth middleware (registered by the host app) handles the request and callback phases; by the time #create runs, request.env is populated and we just need to turn it into a Reader and remember them.
NOTE: OmniAuth 2.0+ only permits POST to its request-phase routes, so all sign-in controls in these views are forms/buttons rather than links.
Instance Method Summary collapse
- #create ⇒ Object
- #destroy ⇒ Object
-
#email_callback ⇒ Object
GET: the reader clicked the link.
-
#email_link ⇒ Object
POST: accept an address and send a one-time link.
- #failure ⇒ Object
- #new ⇒ Object
-
#refresh ⇒ Object
Refresh a resumed page's session and CSRF token without reloading its content.
Instance Method Details
#create ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'app/controllers/bible270/sessions_controller.rb', line 30 def create auth = request.env['omniauth.auth'] redirect_to(sign_in_path, alert: "Sign in didn't complete. Please try again.") and return unless auth if enrollment_closed? && !Reader.omniauth_reader_exists?(auth['provider'], auth['uid']) redirect_to(sign_in_path, alert: ) and return end reader = Reader.from_omniauth(auth) redirect_to(sign_in_path, alert: "We couldn't set up your reader profile.") and return unless reader&.persisted? destination = safe_origin(request.env['omniauth.origin']) || after_sign_in_path # Rotate the session id to avoid session fixation, then sign in. reset_session session[:bible270_reader_id] = reader.id remember_reader!(reader) @current_reader = reader # first_name is filled in for every route now, but a bridged host user may # still arrive without one. redirect_to destination, notice: "Welcome #{reader.first_name.presence || reader.display_name}." end |
#destroy ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'app/controllers/bible270/sessions_controller.rb', line 54 def destroy # Clear the long-lived cookie too, or the next request would sign them # straight back in. The stored token is left alone so their other devices # stay signed in; Reader#forget! is what revokes those. forget_reader! reset_session @current_reader = nil redirect_to(after_sign_out_path, notice: 'Signed out.') end |
#email_callback ⇒ Object
GET: the reader clicked the link.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'app/controllers/bible270/sessions_controller.rb', line 110 def email_callback token = SignInToken.claim!(params[:token]) if token.nil? redirect_to(sign_in_path, alert: 'That link has expired or was already used. Please request a new one.') and return end if enrollment_closed? && !Reader.email_reader_exists?(token.email) redirect_to(sign_in_path, alert: ) and return end reader = Reader.from_email(token.email, first_name: token.first_name, last_name: token.last_name, display_name: token.display_name) redirect_to(sign_in_path, alert: "We couldn't set up your reader profile.") and return unless reader&.persisted? destination = safe_origin(params[:origin]) || after_sign_in_path reset_session session[:bible270_reader_id] = reader.id remember_reader!(reader) @current_reader = reader if name_needed?(reader) redirect_to(profile_path, notice: 'Welcome. Please add your name, so others know who they are reading with.') return end redirect_to destination, notice: "Welcome #{reader.first_name}." end |
#email_link ⇒ Object
POST: accept an address and send a one-time link.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'app/controllers/bible270/sessions_controller.rb', line 72 def email_link unless Bible270.config.email_sign_in? redirect_to(sign_in_path, alert: "Email sign-in isn't enabled here.") and return end origin = safe_origin(params[:origin]) address = EmailSignIn.normalize_email(params[:email]) if address.nil? redirect_to(sign_in_path(origin: origin), alert: "That doesn't look like an email address — please check and try again.") and return end # Names are optional here. Requiring them only for unknown addresses would # make the response differ, which tells a stranger whether an address # already has an account. A new reader is asked for their name after they # click the link instead (see email_callback). names = Names.normalize(params[:first_name], params[:last_name]) _record, raw = SignInToken.issue!(address, first_name: names&.dig(:first_name), last_name: names&.dig(:last_name)) if raw && enrollment_closed? && !Reader.email_reader_exists?(address) Rails.logger.info("[bible270] enrolment closed; no link sent to #{address}") elsif raw deliver_sign_in_link(address, email_sign_in_url(token: raw, origin: origin)) else # Silent to the reader by design; say so in the log or this is undebuggable. Rails.logger.warn("[bible270] no sign-in link issued for #{address} " \ '(rate limited — see config.email_sign_in_max_per_window)') end # Deliberately identical whether or not a link was actually sent, so this # reveals neither who has an account nor that a limit was hit. redirect_to sign_in_path, notice: "Check your inbox — if that address is valid we've sent a sign-in link to #{address}." end |
#failure ⇒ Object
64 65 66 67 |
# File 'app/controllers/bible270/sessions_controller.rb', line 64 def failure = params[:message].presence || 'unknown error' redirect_to sign_in_path, alert: "Sign in failed (#{.to_s.tr('_', ' ')})." end |
#new ⇒ Object
13 14 15 16 17 18 |
# File 'app/controllers/bible270/sessions_controller.rb', line 13 def new redirect_to(after_sign_in_path, notice: "You're already signed in.") and return if signed_in? @providers = Bible270.config.omniauth_providers @origin = safe_origin(params[:origin]) end |
#refresh ⇒ Object
Refresh a resumed page's session and CSRF token without reloading its content. Calling current_reader first lets the long-lived remember cookie rebuild a browser session that the phone may have discarded while the tab was asleep.
23 24 25 26 27 28 |
# File 'app/controllers/bible270/sessions_controller.rb', line 23 def refresh current_reader response.headers['X-CSRF-Token'] = form_authenticity_token response.headers['Cache-Control'] = 'no-store' head :no_content end |