Check for pending invitations before creating new Family during SSO log in/sign up (#1171)

* Check for pending invitations before creating new Family during SSO account creation

When a user signs in via Google SSO and doesn't have an account yet, the
system now checks for pending invitations before creating a new Family.
If an invitation exists, the user joins the invited family instead.

- OidcAccountsController: check Invitation.pending in link/create_user
- API AuthController: check pending invitations in sso_create_account
- SessionsController: pass has_pending_invitation to mobile SSO callback
- Web view: show "Accept Invitation" button when invitation exists
- Flutter: show "Accept Invitation" tab/button when invitation pending

https://claude.ai/code/session_019Tr6edJa496V1ErGmsbqFU

* Fix external assistant tests: clear Settings cache to prevent test pollution

The tests relied solely on with_env_overrides to clear configuration, but
rails-settings-cached may retain stale Setting values across tests when
the cache isn't explicitly invalidated. Ensure both ENV vars AND Setting
values are cleared with Setting.clear_cache before assertions.

https://claude.ai/code/session_019Tr6edJa496V1ErGmsbqFU

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Juan José Mata
2026-03-10 13:38:42 +01:00
committed by GitHub
parent f6e7234ead
commit c09362b880
10 changed files with 93 additions and 24 deletions

View File

@@ -178,7 +178,10 @@ module Api
email = cached[:email]
unless cached[:allow_account_creation]
# Check for a pending invitation for this email
invitation = Invitation.pending.find_by(email: email)
unless invitation.present? || cached[:allow_account_creation]
render json: { error: "SSO account creation is disabled. Please contact an administrator." }, status: :forbidden
return
end
@@ -193,13 +196,22 @@ module Api
skip_password_validation: true
)
user.family = Family.new
if invitation.present?
# Accept the pending invitation: join the existing family
user.family_id = invitation.family_id
user.role = invitation.role
else
user.family = Family.new
provider_config = Rails.configuration.x.auth.sso_providers&.find { |p| p[:name] == cached[:provider] }
provider_default_role = provider_config&.dig(:settings, :default_role)
user.role = User.role_for_new_family_creator(fallback_role: provider_default_role || :admin)
provider_config = Rails.configuration.x.auth.sso_providers&.find { |p| p[:name] == cached[:provider] }
provider_default_role = provider_config&.dig(:settings, :default_role)
user.role = User.role_for_new_family_creator(fallback_role: provider_default_role || :admin)
end
if user.save
# Mark invitation as accepted if one was used
invitation&.update!(accepted_at: Time.current)
OidcIdentity.create_from_omniauth(build_omniauth_hash(cached), user)
SsoAuditLog.log_jit_account_created!(