mirror of
https://github.com/we-promise/sure.git
synced 2026-04-25 06:54:07 +00:00
* Fix OIDC household invitation (issue #900) - Auto-add existing user when inviting by email (no invite email sent) - Accept page: choose 'Create account' or 'Sign in' (supports OIDC) - Store invitation token in session on sign-in; accept after login (password, OIDC, OIDC link, OIDC JIT, MFA) - Invitation#accept_for!(user): add user to household and mark accepted - Defensive guards: nil/blank user, token normalization, accept_for! return check * Address PR review: rename accept_for! to accept_for, i18n OIDC notice, test fixes, stub Rails.application.config * Fix flaky system test: assert only configure step, not flash message Co-authored-by: Cursor <cursoragent@cursor.com> --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: mkdev11 <jaysmth689+github@users.noreply.github.com> Co-authored-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -18,6 +18,28 @@ class ApplicationController < ActionController::Base
|
||||
helper_method :demo_config, :demo_host_match?, :show_demo_warning?
|
||||
|
||||
private
|
||||
def accept_pending_invitation_for(user)
|
||||
return false if user.blank?
|
||||
|
||||
token = session[:pending_invitation_token]
|
||||
return false if token.blank?
|
||||
|
||||
invitation = Invitation.pending.find_by(token: token.to_s)
|
||||
return false unless invitation
|
||||
return false unless invitation.accept_for(user)
|
||||
|
||||
session.delete(:pending_invitation_token)
|
||||
true
|
||||
end
|
||||
|
||||
def store_pending_invitation_if_valid
|
||||
token = params[:invitation].to_s.presence
|
||||
return if token.blank?
|
||||
|
||||
invitation = Invitation.pending.find_by(token: token)
|
||||
session[:pending_invitation_token] = token if invitation
|
||||
end
|
||||
|
||||
def detect_os
|
||||
user_agent = request.user_agent
|
||||
@os = case user_agent
|
||||
|
||||
@@ -15,8 +15,16 @@ class InvitationsController < ApplicationController
|
||||
@invitation.inviter = Current.user
|
||||
|
||||
if @invitation.save
|
||||
InvitationMailer.invite_email(@invitation).deliver_later unless self_hosted?
|
||||
flash[:notice] = t(".success")
|
||||
normalized_email = @invitation.email.to_s.strip.downcase
|
||||
existing_user = User.find_by(email: normalized_email)
|
||||
if existing_user && @invitation.accept_for(existing_user)
|
||||
flash[:notice] = t(".existing_user_added")
|
||||
elsif existing_user
|
||||
flash[:alert] = t(".failure")
|
||||
else
|
||||
InvitationMailer.invite_email(@invitation).deliver_later unless self_hosted?
|
||||
flash[:notice] = t(".success")
|
||||
end
|
||||
else
|
||||
flash[:alert] = t(".failure")
|
||||
end
|
||||
@@ -28,7 +36,7 @@ class InvitationsController < ApplicationController
|
||||
@invitation = Invitation.find_by!(token: params[:id])
|
||||
|
||||
if @invitation.pending?
|
||||
redirect_to new_registration_path(invitation: @invitation.token)
|
||||
render :accept_choice, layout: "auth"
|
||||
else
|
||||
raise ActiveRecord::RecordNotFound
|
||||
end
|
||||
|
||||
@@ -32,6 +32,7 @@ class MfaController < ApplicationController
|
||||
if @user&.verify_otp?(params[:code])
|
||||
session.delete(:mfa_user_id)
|
||||
@session = create_session_for(@user)
|
||||
flash[:notice] = t("invitations.accept_choice.joined_household") if accept_pending_invitation_for(@user)
|
||||
redirect_to root_path
|
||||
else
|
||||
flash.now[:alert] = t(".invalid_code")
|
||||
|
||||
@@ -47,13 +47,17 @@ class OidcAccountsController < ApplicationController
|
||||
# Clear pending auth from session
|
||||
session.delete(:pending_oidc_auth)
|
||||
|
||||
# Check if user has MFA enabled
|
||||
if user.otp_required?
|
||||
session[:mfa_user_id] = user.id
|
||||
redirect_to verify_mfa_path
|
||||
else
|
||||
@session = create_session_for(user)
|
||||
redirect_to root_path, notice: "Account successfully linked to #{@pending_auth['provider']}"
|
||||
notice = if accept_pending_invitation_for(user)
|
||||
t("invitations.accept_choice.joined_household")
|
||||
else
|
||||
t("sessions.openid_connect.account_linked", provider: @pending_auth["provider"])
|
||||
end
|
||||
redirect_to root_path, notice: notice
|
||||
end
|
||||
else
|
||||
@email = params[:email]
|
||||
@@ -139,9 +143,9 @@ class OidcAccountsController < ApplicationController
|
||||
# Clear pending auth from session
|
||||
session.delete(:pending_oidc_auth)
|
||||
|
||||
# Create session and log them in
|
||||
@session = create_session_for(@user)
|
||||
redirect_to root_path, notice: "Welcome! Your account has been created."
|
||||
notice = accept_pending_invitation_for(@user) ? t("invitations.accept_choice.joined_household") : "Welcome! Your account has been created."
|
||||
redirect_to root_path, notice: notice
|
||||
else
|
||||
render :new_user, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
@@ -10,6 +10,7 @@ class SessionsController < ApplicationController
|
||||
end
|
||||
|
||||
def new
|
||||
store_pending_invitation_if_valid
|
||||
# Clear any stale mobile SSO session flag from an abandoned mobile flow
|
||||
session.delete(:mobile_sso)
|
||||
|
||||
@@ -64,6 +65,7 @@ class SessionsController < ApplicationController
|
||||
else
|
||||
log_super_admin_override_login(user)
|
||||
@session = create_session_for(user)
|
||||
flash[:notice] = t("invitations.accept_choice.joined_household") if accept_pending_invitation_for(user)
|
||||
redirect_to root_path
|
||||
end
|
||||
else
|
||||
@@ -180,6 +182,7 @@ class SessionsController < ApplicationController
|
||||
redirect_to verify_mfa_path
|
||||
else
|
||||
@session = create_session_for(user)
|
||||
flash[:notice] = t("invitations.accept_choice.joined_household") if accept_pending_invitation_for(user)
|
||||
redirect_to root_path
|
||||
end
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user