discourse/lib/auth/result.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

173 lines
3.9 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
class Auth::Result
ATTRIBUTES = [
:user,
:name,
:username,
:email,
:email_valid,
:extra_data,
:awaiting_activation,
:awaiting_approval,
:authenticated,
:authenticator_name,
:requires_invite,
:not_allowed_from_ip_address,
:admin_not_allowed_from_ip_address,
:omit_username, # Used by plugins to prevent username edits
:skip_email_validation,
:destination_url,
:omniauth_disallow_totp,
:failed,
:failed_reason,
:failed_code
]
attr_accessor *ATTRIBUTES
# These are stored in the session during
# account creation. The user cannot read or modify them
SESSION_ATTRIBUTES = [
:email,
:username,
:email_valid,
:omit_username,
:name,
:authenticator_name,
:extra_data,
:skip_email_validation
]
def [](key)
key = key.to_sym
public_send(key) if ATTRIBUTES.include?(key)
end
def initialize
@failed = false
end
def email
@email&.downcase
end
def email_valid=(val)
if !val.in? [true, false, nil]
raise ArgumentError, "email_valid should be boolean or nil"
end
@email_valid = !!val
end
def failed?
!!@failed
end
def session_data
SESSION_ATTRIBUTES.map { |att| [att, public_send(att)] }.to_h
end
def self.from_session_data(data, user:)
result = new
data = data.symbolize_keys
SESSION_ATTRIBUTES.each { |att| result.public_send("#{att}=", data[att]) }
result.user = user
result
end
def apply_user_attributes!
change_made = false
FEATURE: Rename 'Discourse SSO' to DiscourseConnect (#11978) The 'Discourse SSO' protocol is being rebranded to DiscourseConnect. This should help to reduce confusion when 'SSO' is used in the generic sense. This commit aims to: - Rename `sso_` site settings. DiscourseConnect specific ones are prefixed `discourse_connect_`. Generic settings are prefixed `auth_` - Add (server-side-only) backwards compatibility for the old setting names, with deprecation notices - Copy `site_settings` database records to the new names - Rename relevant translation keys - Update relevant translations This commit does **not** aim to: - Rename any Ruby classes or methods. This might be done in a future commit - Change any URLs. This would break existing integrations - Make any changes to the protocol. This would break existing integrations - Change any functionality. Further normalization across DiscourseConnect and other auth methods will be done separately The risks are: - There is no backwards compatibility for site settings on the client-side. Accessing auth-related site settings in Javascript is fairly rare, and an error on the client side would not be security-critical. - If a plugin is monkey-patching parts of the auth process, changes to locale keys could cause broken error messages. This should also be unlikely. The old site setting names remain functional, so security-related overrides will remain working. A follow-up commit will be made with a post-deploy migration to delete the old `site_settings` rows.
2021-02-08 18:04:33 +08:00
if SiteSetting.auth_overrides_username? && username.present? && username != user.username
user.username = UserNameSuggester.suggest(username_suggester_attributes, user.username)
change_made = true
end
FEATURE: Rename 'Discourse SSO' to DiscourseConnect (#11978) The 'Discourse SSO' protocol is being rebranded to DiscourseConnect. This should help to reduce confusion when 'SSO' is used in the generic sense. This commit aims to: - Rename `sso_` site settings. DiscourseConnect specific ones are prefixed `discourse_connect_`. Generic settings are prefixed `auth_` - Add (server-side-only) backwards compatibility for the old setting names, with deprecation notices - Copy `site_settings` database records to the new names - Rename relevant translation keys - Update relevant translations This commit does **not** aim to: - Rename any Ruby classes or methods. This might be done in a future commit - Change any URLs. This would break existing integrations - Make any changes to the protocol. This would break existing integrations - Change any functionality. Further normalization across DiscourseConnect and other auth methods will be done separately The risks are: - There is no backwards compatibility for site settings on the client-side. Accessing auth-related site settings in Javascript is fairly rare, and an error on the client side would not be security-critical. - If a plugin is monkey-patching parts of the auth process, changes to locale keys could cause broken error messages. This should also be unlikely. The old site setting names remain functional, so security-related overrides will remain working. A follow-up commit will be made with a post-deploy migration to delete the old `site_settings` rows.
2021-02-08 18:04:33 +08:00
if SiteSetting.auth_overrides_email && email_valid && email.present? && user.email != Email.downcase(email)
user.email = email
change_made = true
end
FEATURE: Rename 'Discourse SSO' to DiscourseConnect (#11978) The 'Discourse SSO' protocol is being rebranded to DiscourseConnect. This should help to reduce confusion when 'SSO' is used in the generic sense. This commit aims to: - Rename `sso_` site settings. DiscourseConnect specific ones are prefixed `discourse_connect_`. Generic settings are prefixed `auth_` - Add (server-side-only) backwards compatibility for the old setting names, with deprecation notices - Copy `site_settings` database records to the new names - Rename relevant translation keys - Update relevant translations This commit does **not** aim to: - Rename any Ruby classes or methods. This might be done in a future commit - Change any URLs. This would break existing integrations - Make any changes to the protocol. This would break existing integrations - Change any functionality. Further normalization across DiscourseConnect and other auth methods will be done separately The risks are: - There is no backwards compatibility for site settings on the client-side. Accessing auth-related site settings in Javascript is fairly rare, and an error on the client side would not be security-critical. - If a plugin is monkey-patching parts of the auth process, changes to locale keys could cause broken error messages. This should also be unlikely. The old site setting names remain functional, so security-related overrides will remain working. A follow-up commit will be made with a post-deploy migration to delete the old `site_settings` rows.
2021-02-08 18:04:33 +08:00
if SiteSetting.auth_overrides_name && name.present? && user.name != name
user.name = name
change_made = true
end
change_made
end
def can_edit_name
FEATURE: Rename 'Discourse SSO' to DiscourseConnect (#11978) The 'Discourse SSO' protocol is being rebranded to DiscourseConnect. This should help to reduce confusion when 'SSO' is used in the generic sense. This commit aims to: - Rename `sso_` site settings. DiscourseConnect specific ones are prefixed `discourse_connect_`. Generic settings are prefixed `auth_` - Add (server-side-only) backwards compatibility for the old setting names, with deprecation notices - Copy `site_settings` database records to the new names - Rename relevant translation keys - Update relevant translations This commit does **not** aim to: - Rename any Ruby classes or methods. This might be done in a future commit - Change any URLs. This would break existing integrations - Make any changes to the protocol. This would break existing integrations - Change any functionality. Further normalization across DiscourseConnect and other auth methods will be done separately The risks are: - There is no backwards compatibility for site settings on the client-side. Accessing auth-related site settings in Javascript is fairly rare, and an error on the client side would not be security-critical. - If a plugin is monkey-patching parts of the auth process, changes to locale keys could cause broken error messages. This should also be unlikely. The old site setting names remain functional, so security-related overrides will remain working. A follow-up commit will be made with a post-deploy migration to delete the old `site_settings` rows.
2021-02-08 18:04:33 +08:00
!SiteSetting.auth_overrides_name
end
def can_edit_username
FEATURE: Rename 'Discourse SSO' to DiscourseConnect (#11978) The 'Discourse SSO' protocol is being rebranded to DiscourseConnect. This should help to reduce confusion when 'SSO' is used in the generic sense. This commit aims to: - Rename `sso_` site settings. DiscourseConnect specific ones are prefixed `discourse_connect_`. Generic settings are prefixed `auth_` - Add (server-side-only) backwards compatibility for the old setting names, with deprecation notices - Copy `site_settings` database records to the new names - Rename relevant translation keys - Update relevant translations This commit does **not** aim to: - Rename any Ruby classes or methods. This might be done in a future commit - Change any URLs. This would break existing integrations - Make any changes to the protocol. This would break existing integrations - Change any functionality. Further normalization across DiscourseConnect and other auth methods will be done separately The risks are: - There is no backwards compatibility for site settings on the client-side. Accessing auth-related site settings in Javascript is fairly rare, and an error on the client side would not be security-critical. - If a plugin is monkey-patching parts of the auth process, changes to locale keys could cause broken error messages. This should also be unlikely. The old site setting names remain functional, so security-related overrides will remain working. A follow-up commit will be made with a post-deploy migration to delete the old `site_settings` rows.
2021-02-08 18:04:33 +08:00
!(SiteSetting.auth_overrides_username || omit_username)
end
def to_client_hash
if requires_invite
return { requires_invite: true }
end
if user&.suspended?
return {
suspended: true,
suspended_message: user.suspended_message
}
end
if omniauth_disallow_totp
return {
omniauth_disallow_totp: !!omniauth_disallow_totp,
email: email
}
end
if user
result = {
authenticated: !!authenticated,
awaiting_activation: !!awaiting_activation,
awaiting_approval: !!awaiting_approval,
not_allowed_from_ip_address: !!not_allowed_from_ip_address,
admin_not_allowed_from_ip_address: !!admin_not_allowed_from_ip_address
}
result[:destination_url] = destination_url if authenticated && destination_url.present?
return result
end
suggested_username = UserNameSuggester.suggest(username_suggester_attributes)
if email_valid && email.present?
if username.present? && User.username_available?(username, email)
suggested_username = username
elsif staged_user = User.where(staged: true).find_by_email(email)
suggested_username = staged_user.username
end
end
result = {
email: email,
username: suggested_username,
auth_provider: authenticator_name,
email_valid: !!email_valid,
can_edit_username: can_edit_username,
can_edit_name: can_edit_name
}
result[:destination_url] = destination_url if destination_url.present?
if SiteSetting.enable_names?
result[:name] = name.presence
result[:name] ||= User.suggest_name(username || email) if can_edit_name
end
result
end
private
def username_suggester_attributes
username || name || email
end
end