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.
This commit is contained in:
parent
205db66864
commit
821bb1e8cb
|
@ -590,7 +590,7 @@ export default Controller.extend(CanCheckEmails, {
|
|||
|
||||
deleteSSORecord() {
|
||||
return bootbox.confirm(
|
||||
I18n.t("admin.user.sso.confirm_delete"),
|
||||
I18n.t("admin.user.discourse_connect.confirm_delete"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
(confirmed) => {
|
||||
|
|
|
@ -70,8 +70,8 @@
|
|||
{{/if}}
|
||||
</div>
|
||||
<div class="controls">
|
||||
{{#if siteSettings.sso_overrides_email}}
|
||||
{{i18n "user.email.sso_override_instructions"}}
|
||||
{{#if siteSettings.auth_overrides_email}}
|
||||
{{i18n "user.email.auth_override_instructions"}}
|
||||
{{else if model.email}}
|
||||
{{html-safe (i18n "admin.user.visit_profile" url=preferencesPath)}}
|
||||
{{/if}}
|
||||
|
@ -105,8 +105,8 @@
|
|||
<div class="controls">
|
||||
{{#if model.email}}
|
||||
{{#if model.secondary_emails}}
|
||||
{{#if siteSettings.sso_overrides_email}}
|
||||
{{i18n "user.email.sso_override_instructions"}}
|
||||
{{#if siteSettings.auth_overrides_email}}
|
||||
{{i18n "user.email.auth_override_instructions"}}
|
||||
{{else}}
|
||||
{{html-safe (i18n "admin.user.visit_profile" url=preferencesPath)}}
|
||||
{{/if}}
|
||||
|
@ -646,11 +646,11 @@
|
|||
|
||||
{{#if model.single_sign_on_record}}
|
||||
<section class="details">
|
||||
<h1>{{i18n "admin.user.sso.title"}}</h1>
|
||||
<h1>{{i18n "admin.user.discourse_connect.title"}}</h1>
|
||||
|
||||
{{#with model.single_sign_on_record as |sso|}}
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_id"}}</div>
|
||||
<div class="field">{{i18n "admin.user.discourse_connect.external_id"}}</div>
|
||||
<div class="value">{{sso.external_id}}</div>
|
||||
{{#if model.can_delete_sso_record}}
|
||||
<div class="controls">
|
||||
|
@ -658,22 +658,22 @@
|
|||
class="btn-danger"
|
||||
action=(action "deleteSSORecord")
|
||||
icon="far-trash-alt"
|
||||
label="admin.user.sso.delete_sso_record"
|
||||
label="admin.user.discourse_connect.delete_sso_record"
|
||||
}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_username"}}</div>
|
||||
<div class="field">{{i18n "admin.user.discourse_connect.external_username"}}</div>
|
||||
<div class="value">{{sso.external_username}}</div>
|
||||
</div>
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_name"}}</div>
|
||||
<div class="field">{{i18n "admin.user.discourse_connect.external_name"}}</div>
|
||||
<div class="value">{{sso.external_name}}</div>
|
||||
</div>
|
||||
{{#if canAdminCheckEmails}}
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_email"}}</div>
|
||||
<div class="field">{{i18n "admin.user.discourse_connect.external_email"}}</div>
|
||||
{{#if ssoExternalEmail}}
|
||||
<div class="value">{{ssoExternalEmail}}</div>
|
||||
{{else}}
|
||||
|
@ -687,12 +687,12 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.external_avatar_url"}}</div>
|
||||
<div class="field">{{i18n "admin.user.discourse_connect.external_avatar_url"}}</div>
|
||||
<div class="value">{{sso.external_avatar_url}}</div>
|
||||
</div>
|
||||
{{#if sso.last_payload}}
|
||||
<div class="display-row">
|
||||
<div class="field">{{i18n "admin.user.sso.last_payload"}}</div>
|
||||
<div class="field">{{i18n "admin.user.discourse_connect.last_payload"}}</div>
|
||||
<div class="value">
|
||||
{{#each ssoPayload as |line|}}
|
||||
{{line}}<br>
|
||||
|
|
|
@ -221,7 +221,7 @@ export default Component.extend({
|
|||
) {
|
||||
if (!canInviteViaEmail) {
|
||||
// can't invite via email, only existing users
|
||||
return I18n.t("topic.invite_reply.sso_enabled");
|
||||
return I18n.t("topic.invite_reply.discourse_connect_enabled");
|
||||
} else if (isPM) {
|
||||
// inviting to a message
|
||||
return I18n.t("topic.invite_private.email_or_username");
|
||||
|
|
|
@ -13,7 +13,7 @@ export default Controller.extend({
|
|||
return (
|
||||
!this.siteSettings.invite_only &&
|
||||
this.siteSettings.allow_new_registrations &&
|
||||
!this.siteSettings.enable_sso
|
||||
!this.siteSettings.enable_discourse_connect
|
||||
);
|
||||
},
|
||||
|
||||
|
|
|
@ -392,7 +392,7 @@ export default Controller.extend(ModalFunctionality, {
|
|||
}
|
||||
|
||||
const skipConfirmation =
|
||||
options && this.siteSettings.external_auth_skip_create_confirm;
|
||||
options && this.siteSettings.auth_skip_create_confirm;
|
||||
|
||||
const createAccountController = this.createAccount;
|
||||
createAccountController.setProperties({
|
||||
|
|
|
@ -71,7 +71,8 @@ export default Controller.extend(CanCheckEmails, {
|
|||
return false;
|
||||
} else {
|
||||
return (
|
||||
!this.siteSettings.enable_sso && this.siteSettings.enable_local_logins
|
||||
!this.siteSettings.enable_discourse_connect &&
|
||||
this.siteSettings.enable_local_logins
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -755,7 +755,7 @@ const User = RestModel.extend({
|
|||
|
||||
@discourseComputed("can_delete_account")
|
||||
canDeleteAccount(canDeleteAccount) {
|
||||
return !this.siteSettings.enable_sso && canDeleteAccount;
|
||||
return !this.siteSettings.enable_discourse_connect && canDeleteAccount;
|
||||
},
|
||||
|
||||
delete: function () {
|
||||
|
|
|
@ -243,7 +243,7 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, {
|
|||
},
|
||||
|
||||
handleShowLogin() {
|
||||
if (this.siteSettings.enable_sso) {
|
||||
if (this.siteSettings.enable_discourse_connect) {
|
||||
const returnPath = encodeURIComponent(window.location.pathname);
|
||||
window.location = getURL("/session/sso?return_path=" + returnPath);
|
||||
} else {
|
||||
|
@ -254,7 +254,7 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, {
|
|||
},
|
||||
|
||||
handleShowCreateAccount() {
|
||||
if (this.siteSettings.enable_sso) {
|
||||
if (this.siteSettings.enable_discourse_connect) {
|
||||
const returnPath = encodeURIComponent(window.location.pathname);
|
||||
window.location = getURL("/session/sso?return_path=" + returnPath);
|
||||
} else {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#unless siteSettings.sso_overrides_avatar}}
|
||||
{{#unless siteSettings.discourse_connect_overrides_avatar}}
|
||||
<div class="control-group pref-avatar">
|
||||
<label class="control-label" id="profile-picture">{{i18n "user.avatar.title"}}</label>
|
||||
<div class="controls">
|
||||
|
@ -94,8 +94,8 @@
|
|||
{{/if}}
|
||||
|
||||
<div class="instructions">
|
||||
{{#if siteSettings.sso_overrides_email}}
|
||||
{{i18n "user.email.sso_override_instructions"}}
|
||||
{{#if siteSettings.auth_overrides_email}}
|
||||
{{i18n "user.email.auth_override_instructions"}}
|
||||
{{/if}}
|
||||
{{i18n "user.email.instructions"}}
|
||||
</div>
|
||||
|
|
|
@ -32,7 +32,7 @@ acceptance("Create Account - external auth", function (needs) {
|
|||
});
|
||||
|
||||
test("when skip is enabled", async function (assert) {
|
||||
this.siteSettings.external_auth_skip_create_confirm = true;
|
||||
this.siteSettings.auth_skip_create_confirm = true;
|
||||
await visit("/");
|
||||
|
||||
assert.ok(
|
||||
|
|
|
@ -29,7 +29,7 @@ const ORIGINAL_SETTINGS = {
|
|||
enable_twitter_logins: true,
|
||||
enable_facebook_logins: true,
|
||||
enable_github_logins: true,
|
||||
enable_sso: false,
|
||||
enable_discourse_connect: false,
|
||||
min_username_length: 3,
|
||||
max_username_length: 20,
|
||||
min_password_length: 8,
|
||||
|
|
|
@ -439,12 +439,12 @@ class Admin::UsersController < Admin::AdminController
|
|||
end
|
||||
|
||||
def sync_sso
|
||||
return render body: nil, status: 404 unless SiteSetting.enable_sso
|
||||
return render body: nil, status: 404 unless SiteSetting.enable_discourse_connect
|
||||
|
||||
begin
|
||||
sso = DiscourseSingleSignOn.parse("sso=#{params[:sso]}&sig=#{params[:sig]}")
|
||||
rescue DiscourseSingleSignOn::ParseError => e
|
||||
return render json: failed_json.merge(message: I18n.t("sso.login_error")), status: 422
|
||||
return render json: failed_json.merge(message: I18n.t("discourse_connect.login_error")), status: 422
|
||||
end
|
||||
|
||||
begin
|
||||
|
@ -453,7 +453,7 @@ class Admin::UsersController < Admin::AdminController
|
|||
rescue ActiveRecord::RecordInvalid => ex
|
||||
render json: failed_json.merge(message: ex.message), status: 403
|
||||
rescue DiscourseSingleSignOn::BlankExternalId => ex
|
||||
render json: failed_json.merge(message: I18n.t('sso.blank_id_error')), status: 422
|
||||
render json: failed_json.merge(message: I18n.t('discourse_connect.blank_id_error')), status: 422
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -739,11 +739,11 @@ class ApplicationController < ActionController::Base
|
|||
def redirect_to_login
|
||||
dont_cache_page
|
||||
|
||||
if SiteSetting.external_auth_immediately && SiteSetting.enable_sso?
|
||||
if SiteSetting.auth_immediately && SiteSetting.enable_discourse_connect?
|
||||
# save original URL in a session so we can redirect after login
|
||||
session[:destination_url] = destination_url
|
||||
redirect_to path('/session/sso')
|
||||
elsif SiteSetting.external_auth_immediately && !SiteSetting.enable_local_logins && Discourse.enabled_authenticators.length == 1 && !cookies[:authentication_data]
|
||||
elsif SiteSetting.auth_immediately && !SiteSetting.enable_local_logins && Discourse.enabled_authenticators.length == 1 && !cookies[:authentication_data]
|
||||
# Only one authentication provider, direct straight to it.
|
||||
# If authentication_data is present, then we are halfway though registration. Don't redirect offsite
|
||||
cookies[:destination_url] = destination_url
|
||||
|
|
|
@ -338,7 +338,7 @@ class GroupsController < ApplicationController
|
|||
|
||||
if emails.any?
|
||||
if SiteSetting.enable_sso?
|
||||
raise Discourse::InvalidParameters.new(I18n.t("no_invites_with_sso"))
|
||||
raise Discourse::InvalidParameters.new(I18n.t("no_invites_with_discourse_connect"))
|
||||
elsif !SiteSetting.enable_local_logins?
|
||||
raise Discourse::InvalidParameters.new(I18n.t("no_invites_without_local_logins"))
|
||||
end
|
||||
|
|
|
@ -268,7 +268,7 @@ class InvitesController < ApplicationController
|
|||
|
||||
if user.has_password?
|
||||
send_activation_email(user) unless user.active
|
||||
elsif !SiteSetting.enable_sso && SiteSetting.enable_local_logins
|
||||
elsif !SiteSetting.enable_discourse_connect && SiteSetting.enable_local_logins
|
||||
Jobs.enqueue(:invite_password_instructions_email, username: user.username)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,19 +24,19 @@ class SessionController < ApplicationController
|
|||
session.delete(:destination_url)
|
||||
cookies.delete(:destination_url)
|
||||
|
||||
if SiteSetting.enable_sso?
|
||||
if SiteSetting.enable_discourse_connect?
|
||||
sso = DiscourseSingleSignOn.generate_sso(return_path)
|
||||
if SiteSetting.verbose_sso_logging
|
||||
if SiteSetting.verbose_discourse_connect_logging
|
||||
Rails.logger.warn("Verbose SSO log: Started SSO process\n\n#{sso.diagnostics}")
|
||||
end
|
||||
redirect_to sso_url(sso)
|
||||
redirect_to discourse_connect_url(sso)
|
||||
else
|
||||
render body: nil, status: 404
|
||||
end
|
||||
end
|
||||
|
||||
def sso_provider(payload = nil)
|
||||
if SiteSetting.enable_sso_provider
|
||||
if SiteSetting.enable_discourse_connect_provider
|
||||
begin
|
||||
if !payload
|
||||
params.require(:sso)
|
||||
|
@ -44,15 +44,15 @@ class SessionController < ApplicationController
|
|||
end
|
||||
sso = SingleSignOnProvider.parse(payload)
|
||||
rescue SingleSignOnProvider::BlankSecret
|
||||
render plain: I18n.t("sso.missing_secret"), status: 400
|
||||
render plain: I18n.t("discourse_connect.missing_secret"), status: 400
|
||||
return
|
||||
rescue SingleSignOnProvider::ParseError => e
|
||||
if SiteSetting.verbose_sso_logging
|
||||
if SiteSetting.verbose_discourse_connect_logging
|
||||
Rails.logger.warn("Verbose SSO log: Signature parse error\n\n#{e.message}\n\n#{sso&.diagnostics}")
|
||||
end
|
||||
|
||||
# Do NOT pass the error text to the client, it would give them the correct signature
|
||||
render plain: I18n.t("sso.login_error"), status: 422
|
||||
render plain: I18n.t("discourse_connect.login_error"), status: 422
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -138,7 +138,7 @@ class SessionController < ApplicationController
|
|||
end
|
||||
|
||||
def sso_login
|
||||
raise Discourse::NotFound.new unless SiteSetting.enable_sso
|
||||
raise Discourse::NotFound.new unless SiteSetting.enable_discourse_connect
|
||||
|
||||
params.require(:sso)
|
||||
params.require(:sig)
|
||||
|
@ -146,26 +146,26 @@ class SessionController < ApplicationController
|
|||
begin
|
||||
sso = DiscourseSingleSignOn.parse(request.query_string)
|
||||
rescue DiscourseSingleSignOn::ParseError => e
|
||||
if SiteSetting.verbose_sso_logging
|
||||
if SiteSetting.verbose_discourse_connect_logging
|
||||
Rails.logger.warn("Verbose SSO log: Signature parse error\n\n#{e.message}\n\n#{sso&.diagnostics}")
|
||||
end
|
||||
|
||||
# Do NOT pass the error text to the client, it would give them the correct signature
|
||||
return render_sso_error(text: I18n.t("sso.login_error"), status: 422)
|
||||
return render_sso_error(text: I18n.t("discourse_connect.login_error"), status: 422)
|
||||
end
|
||||
|
||||
if !sso.nonce_valid?
|
||||
if SiteSetting.verbose_sso_logging
|
||||
if SiteSetting.verbose_discourse_connect_logging
|
||||
Rails.logger.warn("Verbose SSO log: Nonce has already expired\n\n#{sso.diagnostics}")
|
||||
end
|
||||
return render_sso_error(text: I18n.t("sso.timeout_expired"), status: 419)
|
||||
return render_sso_error(text: I18n.t("discourse_connect.timeout_expired"), status: 419)
|
||||
end
|
||||
|
||||
if ScreenedIpAddress.should_block?(request.remote_ip)
|
||||
if SiteSetting.verbose_sso_logging
|
||||
if SiteSetting.verbose_discourse_connect_logging
|
||||
Rails.logger.warn("Verbose SSO log: IP address is blocked #{request.remote_ip}\n\n#{sso.diagnostics}")
|
||||
end
|
||||
return render_sso_error(text: I18n.t("sso.unknown_error"), status: 500)
|
||||
return render_sso_error(text: I18n.t("discourse_connect.unknown_error"), status: 500)
|
||||
end
|
||||
|
||||
return_path = sso.return_path
|
||||
|
@ -180,10 +180,10 @@ class SessionController < ApplicationController
|
|||
end
|
||||
|
||||
if SiteSetting.must_approve_users? && !user.approved?
|
||||
if SiteSetting.sso_not_approved_url.present?
|
||||
redirect_to SiteSetting.sso_not_approved_url
|
||||
if SiteSetting.discourse_connect_not_approved_url.present?
|
||||
redirect_to SiteSetting.discourse_connect_not_approved_url
|
||||
else
|
||||
render_sso_error(text: I18n.t("sso.account_not_approved"), status: 403)
|
||||
render_sso_error(text: I18n.t("discourse_connect.account_not_approved"), status: 403)
|
||||
end
|
||||
return
|
||||
elsif !user.active?
|
||||
|
@ -192,7 +192,7 @@ class SessionController < ApplicationController
|
|||
session["user_created_message"] = activation.message
|
||||
redirect_to(users_account_created_path) && (return)
|
||||
else
|
||||
if SiteSetting.verbose_sso_logging
|
||||
if SiteSetting.verbose_discourse_connect_logging
|
||||
Rails.logger.warn("Verbose SSO log: User was logged on #{user.username}\n\n#{sso.diagnostics}")
|
||||
end
|
||||
if user.id != current_user&.id
|
||||
|
@ -206,7 +206,7 @@ class SessionController < ApplicationController
|
|||
uri = URI(return_path)
|
||||
if (uri.hostname == Discourse.current_hostname)
|
||||
return_path = uri.to_s
|
||||
elsif !SiteSetting.sso_allows_all_return_paths
|
||||
elsif !SiteSetting.discourse_connect_allows_all_return_paths
|
||||
return_path = path("/")
|
||||
end
|
||||
rescue
|
||||
|
@ -223,11 +223,11 @@ class SessionController < ApplicationController
|
|||
|
||||
redirect_to return_path
|
||||
else
|
||||
render_sso_error(text: I18n.t("sso.not_found"), status: 500)
|
||||
render_sso_error(text: I18n.t("discourse_connect.not_found"), status: 500)
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
|
||||
if SiteSetting.verbose_sso_logging
|
||||
if SiteSetting.verbose_discourse_connect_logging
|
||||
Rails.logger.warn(<<~EOF)
|
||||
Verbose SSO log: Record was invalid: #{e.record.class.name} #{e.record.id}
|
||||
#{e.record.errors.to_h}
|
||||
|
@ -245,17 +245,17 @@ class SessionController < ApplicationController
|
|||
# If there's a problem with the email we can explain that
|
||||
if (e.record.is_a?(User) && e.record.errors[:primary_email].present?)
|
||||
if e.record.email.blank?
|
||||
text = I18n.t("sso.no_email")
|
||||
text = I18n.t("discourse_connect.no_email")
|
||||
else
|
||||
text = I18n.t("sso.email_error", email: ERB::Util.html_escape(e.record.email))
|
||||
text = I18n.t("discourse_connect.email_error", email: ERB::Util.html_escape(e.record.email))
|
||||
end
|
||||
end
|
||||
|
||||
render_sso_error(text: text || I18n.t("sso.unknown_error"), status: 500)
|
||||
render_sso_error(text: text || I18n.t("discourse_connect.unknown_error"), status: 500)
|
||||
|
||||
rescue DiscourseSingleSignOn::BlankExternalId
|
||||
|
||||
render_sso_error(text: I18n.t("sso.blank_id_error"), status: 500)
|
||||
render_sso_error(text: I18n.t("discourse_connect.blank_id_error"), status: 500)
|
||||
|
||||
rescue => e
|
||||
message = +"Failed to create or lookup user: #{e}."
|
||||
|
@ -266,7 +266,7 @@ class SessionController < ApplicationController
|
|||
|
||||
Rails.logger.error(message)
|
||||
|
||||
render_sso_error(text: I18n.t("sso.unknown_error"), status: 500)
|
||||
render_sso_error(text: I18n.t("discourse_connect.unknown_error"), status: 500)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -445,7 +445,7 @@ class SessionController < ApplicationController
|
|||
def destroy
|
||||
redirect_url = params[:return_url].presence || SiteSetting.logout_redirect.presence
|
||||
|
||||
sso = SiteSetting.enable_sso
|
||||
sso = SiteSetting.enable_discourse_connect
|
||||
only_one_authenticator = !SiteSetting.enable_local_logins && Discourse.enabled_authenticators.length == 1
|
||||
if SiteSetting.login_required && (sso || only_one_authenticator)
|
||||
# In this situation visiting most URLs will start the auth process again
|
||||
|
@ -498,7 +498,7 @@ class SessionController < ApplicationController
|
|||
return if user&.admin?
|
||||
|
||||
if (check_login_via_email && !SiteSetting.enable_local_logins_via_email) ||
|
||||
SiteSetting.enable_sso ||
|
||||
SiteSetting.enable_discourse_connect ||
|
||||
!SiteSetting.enable_local_logins
|
||||
raise Discourse::InvalidAccess, "SSO takes over local login or the local login is disallowed."
|
||||
end
|
||||
|
|
|
@ -19,7 +19,7 @@ class UploadsController < ApplicationController
|
|||
# 50 characters ought to be enough for the upload type
|
||||
type = params.require(:type).parameterize(separator: "_")[0..50]
|
||||
|
||||
if type == "avatar" && !me.admin? && (SiteSetting.sso_overrides_avatar || !SiteSetting.allow_uploaded_avatars)
|
||||
if type == "avatar" && !me.admin? && (SiteSetting.discourse_connect_overrides_avatar || !SiteSetting.allow_uploaded_avatars)
|
||||
return render json: failed_json, status: 422
|
||||
end
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class UserApiKeysController < ApplicationController
|
|||
unless current_user
|
||||
cookies[:destination_url] = request.fullpath
|
||||
|
||||
if SiteSetting.enable_sso?
|
||||
if SiteSetting.enable_discourse_connect?
|
||||
redirect_to path('/session/sso')
|
||||
else
|
||||
redirect_to path('/login')
|
||||
|
@ -115,7 +115,7 @@ class UserApiKeysController < ApplicationController
|
|||
unless current_user
|
||||
cookies[:destination_url] = request.fullpath
|
||||
|
||||
if SiteSetting.enable_sso?
|
||||
if SiteSetting.enable_discourse_connect?
|
||||
redirect_to path('/session/sso')
|
||||
else
|
||||
redirect_to path('/login')
|
||||
|
|
|
@ -40,7 +40,7 @@ class Users::OmniauthCallbacksController < ApplicationController
|
|||
|
||||
preferred_origin = request.env['omniauth.origin']
|
||||
|
||||
if SiteSetting.enable_sso_provider && payload = cookies.delete(:sso_payload)
|
||||
if SiteSetting.enable_discourse_connect_provider && payload = cookies.delete(:sso_payload)
|
||||
preferred_origin = session_sso_provider_url + "?" + payload
|
||||
elsif cookies[:destination_url].present?
|
||||
preferred_origin = cookies[:destination_url]
|
||||
|
|
|
@ -179,7 +179,7 @@ class UsersController < ApplicationController
|
|||
end
|
||||
rescue Discourse::InvalidAccess
|
||||
if current_user&.staff?
|
||||
render_json_error(I18n.t('errors.messages.sso_overrides_username'))
|
||||
render_json_error(I18n.t('errors.messages.auth_overrides_username'))
|
||||
else
|
||||
render json: failed_json, status: 403
|
||||
end
|
||||
|
@ -412,8 +412,8 @@ class UsersController < ApplicationController
|
|||
))
|
||||
else
|
||||
if current_user&.staff?
|
||||
message = if SiteSetting.enable_sso
|
||||
I18n.t("invite.disabled_errors.sso_enabled")
|
||||
message = if SiteSetting.enable_discourse_connect
|
||||
I18n.t("invite.disabled_errors.discourse_connect_enabled")
|
||||
elsif !SiteSetting.enable_local_logins
|
||||
I18n.t("invite.disabled_errors.local_logins_disabled")
|
||||
end
|
||||
|
@ -436,8 +436,8 @@ class UsersController < ApplicationController
|
|||
render json: MultiJson.dump(invites: serialize_data(invites.to_a, InviteLinkSerializer), can_see_invite_details: guardian.can_see_invite_details?(inviter))
|
||||
else
|
||||
if current_user&.staff?
|
||||
message = if SiteSetting.enable_sso
|
||||
I18n.t("invite.disabled_errors.sso_enabled")
|
||||
message = if SiteSetting.enable_discourse_connect
|
||||
I18n.t("invite.disabled_errors.discourse_connect_enabled")
|
||||
elsif !SiteSetting.enable_local_logins
|
||||
I18n.t("invite.disabled_errors.local_logins_disabled")
|
||||
end
|
||||
|
@ -909,7 +909,7 @@ class UsersController < ApplicationController
|
|||
|
||||
def account_created
|
||||
if current_user.present?
|
||||
if SiteSetting.enable_sso_provider && payload = cookies.delete(:sso_payload)
|
||||
if SiteSetting.enable_discourse_connect_provider && payload = cookies.delete(:sso_payload)
|
||||
return redirect_to(session_sso_provider_url + "?" + payload)
|
||||
elsif destination_url = cookies.delete(:destination_url)
|
||||
return redirect_to(destination_url)
|
||||
|
@ -958,7 +958,7 @@ class UsersController < ApplicationController
|
|||
elsif destination_url = cookies[:destination_url]
|
||||
cookies[:destination_url] = nil
|
||||
return redirect_to(destination_url)
|
||||
elsif SiteSetting.enable_sso_provider && payload = cookies.delete(:sso_payload)
|
||||
elsif SiteSetting.enable_discourse_connect_provider && payload = cookies.delete(:sso_payload)
|
||||
return redirect_to(session_sso_provider_url + "?" + payload)
|
||||
end
|
||||
else
|
||||
|
@ -1095,7 +1095,7 @@ class UsersController < ApplicationController
|
|||
user = fetch_user_from_params
|
||||
guardian.ensure_can_edit!(user)
|
||||
|
||||
if SiteSetting.sso_overrides_avatar
|
||||
if SiteSetting.discourse_connect_overrides_avatar
|
||||
return render json: failed_json, status: 422
|
||||
end
|
||||
|
||||
|
@ -1276,7 +1276,7 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def list_second_factors
|
||||
raise Discourse::NotFound if SiteSetting.enable_sso || !SiteSetting.enable_local_logins
|
||||
raise Discourse::NotFound if SiteSetting.enable_discourse_connect || !SiteSetting.enable_local_logins
|
||||
|
||||
unless params[:password].empty?
|
||||
RateLimiter.new(nil, "login-hr-#{request.remote_ip}", SiteSetting.max_logins_per_ip_per_hour, 1.hour).performed!
|
||||
|
@ -1448,7 +1448,7 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def second_factor_check_confirmed_password
|
||||
raise Discourse::NotFound if SiteSetting.enable_sso || !SiteSetting.enable_local_logins
|
||||
raise Discourse::NotFound if SiteSetting.enable_discourse_connect || !SiteSetting.enable_local_logins
|
||||
|
||||
raise Discourse::InvalidAccess.new unless current_user && secure_session_confirmed?
|
||||
end
|
||||
|
|
|
@ -548,7 +548,7 @@ module ApplicationHelper
|
|||
def can_sign_up?
|
||||
SiteSetting.allow_new_registrations &&
|
||||
!SiteSetting.invite_only &&
|
||||
!SiteSetting.enable_sso
|
||||
!SiteSetting.enable_discourse_connect
|
||||
end
|
||||
|
||||
def rss_creator(user)
|
||||
|
|
|
@ -113,7 +113,7 @@ module Jobs
|
|||
condition = { trust_level: trust_level }
|
||||
end
|
||||
|
||||
if SiteSetting.enable_sso
|
||||
if SiteSetting.enable_discourse_connect
|
||||
# SSO enabled
|
||||
User.where(condition).includes(:user_profile, :user_stat, :user_emails, :single_sign_on_record, :groups).find_each do |user|
|
||||
user_info_array = get_base_user_array(user)
|
||||
|
@ -232,7 +232,7 @@ module Jobs
|
|||
def get_header(entity)
|
||||
if entity == 'user_list'
|
||||
header_array = HEADER_ATTRS_FOR['user_list'] + HEADER_ATTRS_FOR['user_stats'] + HEADER_ATTRS_FOR['user_profile']
|
||||
header_array.concat(HEADER_ATTRS_FOR['user_sso']) if SiteSetting.enable_sso
|
||||
header_array.concat(HEADER_ATTRS_FOR['user_sso']) if SiteSetting.enable_discourse_connect
|
||||
user_custom_fields = UserField.all
|
||||
if user_custom_fields.present?
|
||||
user_custom_fields.each do |custom_field|
|
||||
|
|
|
@ -384,7 +384,7 @@ module Jobs
|
|||
def get_header(entity)
|
||||
if entity == 'user_list'
|
||||
header_array = HEADER_ATTRS_FOR['user_list'] + HEADER_ATTRS_FOR['user_stats'] + HEADER_ATTRS_FOR['user_profile']
|
||||
header_array.concat(HEADER_ATTRS_FOR['user_sso']) if SiteSetting.enable_sso
|
||||
header_array.concat(HEADER_ATTRS_FOR['user_sso']) if SiteSetting.enable_discourse_connect
|
||||
user_custom_fields = UserField.all
|
||||
if user_custom_fields.present?
|
||||
user_custom_fields.each do |custom_field|
|
||||
|
|
|
@ -54,19 +54,19 @@ module SecondFactorManager
|
|||
end
|
||||
|
||||
def totp_enabled?
|
||||
!SiteSetting.enable_sso &&
|
||||
!SiteSetting.enable_discourse_connect &&
|
||||
SiteSetting.enable_local_logins &&
|
||||
self&.user_second_factors.totps.exists?
|
||||
end
|
||||
|
||||
def backup_codes_enabled?
|
||||
!SiteSetting.enable_sso &&
|
||||
!SiteSetting.enable_discourse_connect &&
|
||||
SiteSetting.enable_local_logins &&
|
||||
self&.user_second_factors.backup_codes.exists?
|
||||
end
|
||||
|
||||
def security_keys_enabled?
|
||||
!SiteSetting.enable_sso &&
|
||||
!SiteSetting.enable_discourse_connect &&
|
||||
SiteSetting.enable_local_logins &&
|
||||
self&.security_keys.where(factor_type: UserSecurityKey.factor_types[:second_factor], enabled: true).exists?
|
||||
end
|
||||
|
|
|
@ -6,11 +6,11 @@ class DiscourseSingleSignOn < SingleSignOn
|
|||
class BannedExternalId < StandardError; end
|
||||
|
||||
def self.sso_url
|
||||
SiteSetting.sso_url
|
||||
SiteSetting.discourse_connect_url
|
||||
end
|
||||
|
||||
def self.sso_secret
|
||||
SiteSetting.sso_secret
|
||||
SiteSetting.discourse_connect_secret
|
||||
end
|
||||
|
||||
def self.generate_sso(return_path = "/")
|
||||
|
@ -120,7 +120,7 @@ class DiscourseSingleSignOn < SingleSignOn
|
|||
# The user might require approval
|
||||
user.create_reviewable
|
||||
|
||||
if bio && (user.user_profile.bio_raw.blank? || SiteSetting.sso_overrides_bio)
|
||||
if bio && (user.user_profile.bio_raw.blank? || SiteSetting.discourse_connect_overrides_bio)
|
||||
user.user_profile.bio_raw = bio
|
||||
user.user_profile.save!
|
||||
end
|
||||
|
@ -170,7 +170,7 @@ class DiscourseSingleSignOn < SingleSignOn
|
|||
end
|
||||
|
||||
def apply_group_rules(user)
|
||||
if SiteSetting.sso_overrides_groups
|
||||
if SiteSetting.discourse_connect_overrides_groups
|
||||
synchronize_groups(user)
|
||||
return
|
||||
end
|
||||
|
@ -219,7 +219,7 @@ class DiscourseSingleSignOn < SingleSignOn
|
|||
|
||||
user = User.create!(user_params)
|
||||
|
||||
if SiteSetting.verbose_sso_logging
|
||||
if SiteSetting.verbose_discourse_connect_logging
|
||||
Rails.logger.warn("Verbose SSO log: New User (user_id: #{user.id}) Params: #{user_params} User Params: #{user.attributes} User Errors: #{user.errors.full_messages} Email: #{user.primary_email.attributes} Email Error: #{user.primary_email.errors.full_messages}")
|
||||
end
|
||||
end
|
||||
|
@ -233,7 +233,7 @@ class DiscourseSingleSignOn < SingleSignOn
|
|||
Jobs.enqueue(:download_avatar_from_url,
|
||||
url: avatar_url,
|
||||
user_id: user.id,
|
||||
override_gravatar: SiteSetting.sso_overrides_avatar
|
||||
override_gravatar: SiteSetting.discourse_connect_overrides_avatar
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -273,13 +273,13 @@ class DiscourseSingleSignOn < SingleSignOn
|
|||
def change_external_attributes_and_override(sso_record, user)
|
||||
@email_changed = false
|
||||
|
||||
if SiteSetting.sso_overrides_email && user.email != Email.downcase(email)
|
||||
if SiteSetting.auth_overrides_email && user.email != Email.downcase(email)
|
||||
user.email = email
|
||||
user.active = false if require_activation
|
||||
@email_changed = true
|
||||
end
|
||||
|
||||
if SiteSetting.sso_overrides_username? && username.present?
|
||||
if SiteSetting.auth_overrides_username? && username.present?
|
||||
if user.username.downcase == username.downcase
|
||||
user.username = username # there may be a change of case
|
||||
elsif user.username != username
|
||||
|
@ -287,7 +287,7 @@ class DiscourseSingleSignOn < SingleSignOn
|
|||
end
|
||||
end
|
||||
|
||||
if SiteSetting.sso_overrides_name && user.name != name && name.present?
|
||||
if SiteSetting.auth_overrides_name && user.name != name && name.present?
|
||||
user.name = name || User.suggest_name(username.blank? ? email : username)
|
||||
end
|
||||
|
||||
|
@ -297,18 +297,18 @@ class DiscourseSingleSignOn < SingleSignOn
|
|||
|
||||
avatar_missing = user.uploaded_avatar_id.nil? || !Upload.exists?(user.uploaded_avatar_id)
|
||||
|
||||
if (avatar_missing || avatar_force_update || SiteSetting.sso_overrides_avatar) && avatar_url.present?
|
||||
if (avatar_missing || avatar_force_update || SiteSetting.discourse_connect_overrides_avatar) && avatar_url.present?
|
||||
avatar_changed = sso_record.external_avatar_url != avatar_url
|
||||
|
||||
if avatar_force_update || avatar_changed || avatar_missing
|
||||
Jobs.enqueue(:download_avatar_from_url, url: avatar_url, user_id: user.id, override_gravatar: SiteSetting.sso_overrides_avatar)
|
||||
Jobs.enqueue(:download_avatar_from_url, url: avatar_url, user_id: user.id, override_gravatar: SiteSetting.discourse_connect_overrides_avatar)
|
||||
end
|
||||
end
|
||||
|
||||
if profile_background_url.present?
|
||||
profile_background_missing = user.user_profile.profile_background_upload.blank? || Upload.get_from_url(user.user_profile.profile_background_upload.url).blank?
|
||||
|
||||
if profile_background_missing || SiteSetting.sso_overrides_profile_background
|
||||
if profile_background_missing || SiteSetting.discourse_connect_overrides_profile_background
|
||||
profile_background_changed = sso_record.external_profile_background_url != profile_background_url
|
||||
if profile_background_changed || profile_background_missing
|
||||
Jobs.enqueue(:download_profile_background_from_url,
|
||||
|
@ -322,7 +322,7 @@ class DiscourseSingleSignOn < SingleSignOn
|
|||
|
||||
if card_background_url.present?
|
||||
card_background_missing = user.user_profile.card_background_upload.blank? || Upload.get_from_url(user.user_profile.card_background_upload.url).blank?
|
||||
if card_background_missing || SiteSetting.sso_overrides_profile_background
|
||||
if card_background_missing || SiteSetting.discourse_connect_overrides_profile_background
|
||||
card_background_changed = sso_record.external_card_background_url != card_background_url
|
||||
if card_background_changed || card_background_missing
|
||||
Jobs.enqueue(:download_profile_background_from_url,
|
||||
|
|
|
@ -361,7 +361,7 @@ class Invite < ActiveRecord::Base
|
|||
return if email.blank?
|
||||
|
||||
if SiteSetting.enable_sso?
|
||||
errors.add(:email, I18n.t("invite.disabled_errors.sso_enabled"))
|
||||
errors.add(:email, I18n.t("invite.disabled_errors.discourse_connect_enabled"))
|
||||
elsif !SiteSetting.enable_local_logins?
|
||||
errors.add(:email, I18n.t("invite.disabled_errors.local_logins_disabled"))
|
||||
end
|
||||
|
|
|
@ -106,7 +106,7 @@ class AdminUserListSerializer < BasicUserSerializer
|
|||
end
|
||||
|
||||
def include_second_factor_enabled?
|
||||
!SiteSetting.enable_sso &&
|
||||
!SiteSetting.enable_discourse_connect &&
|
||||
SiteSetting.enable_local_logins &&
|
||||
object.has_any_second_factor_methods_enabled?
|
||||
end
|
||||
|
|
|
@ -228,7 +228,7 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||
end
|
||||
|
||||
def include_external_id?
|
||||
SiteSetting.enable_sso
|
||||
SiteSetting.enable_discourse_connect
|
||||
end
|
||||
|
||||
def second_factor_enabled
|
||||
|
|
|
@ -44,7 +44,7 @@ class NotificationSerializer < ApplicationSerializer
|
|||
end
|
||||
|
||||
def include_external_id?
|
||||
SiteSetting.enable_sso
|
||||
SiteSetting.enable_discourse_connect
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -120,15 +120,15 @@ class UserSerializer < UserCardSerializer
|
|||
end
|
||||
|
||||
def can_change_bio
|
||||
!(SiteSetting.enable_sso && SiteSetting.sso_overrides_bio)
|
||||
!(SiteSetting.enable_discourse_connect && SiteSetting.discourse_connect_overrides_bio)
|
||||
end
|
||||
|
||||
def can_change_location
|
||||
!(SiteSetting.enable_sso && SiteSetting.sso_overrides_location)
|
||||
!(SiteSetting.enable_discourse_connect && SiteSetting.discourse_connect_overrides_location)
|
||||
end
|
||||
|
||||
def can_change_website
|
||||
!(SiteSetting.enable_sso && SiteSetting.sso_overrides_website)
|
||||
!(SiteSetting.enable_discourse_connect && SiteSetting.discourse_connect_overrides_website)
|
||||
end
|
||||
|
||||
def user_api_keys
|
||||
|
|
|
@ -67,15 +67,15 @@ class UserUpdater
|
|||
def update(attributes = {})
|
||||
user_profile = user.user_profile
|
||||
user_profile.dismissed_banner_key = attributes[:dismissed_banner_key] if attributes[:dismissed_banner_key].present?
|
||||
unless SiteSetting.enable_sso && SiteSetting.sso_overrides_bio
|
||||
unless SiteSetting.enable_discourse_connect && SiteSetting.discourse_connect_overrides_bio
|
||||
user_profile.bio_raw = attributes.fetch(:bio_raw) { user_profile.bio_raw }
|
||||
end
|
||||
|
||||
unless SiteSetting.enable_sso && SiteSetting.sso_overrides_location
|
||||
unless SiteSetting.enable_discourse_connect && SiteSetting.discourse_connect_overrides_location
|
||||
user_profile.location = attributes.fetch(:location) { user_profile.location }
|
||||
end
|
||||
|
||||
unless SiteSetting.enable_sso && SiteSetting.sso_overrides_website
|
||||
unless SiteSetting.enable_discourse_connect && SiteSetting.discourse_connect_overrides_website
|
||||
user_profile.website = format_url(attributes.fetch(:website) { user_profile.website })
|
||||
end
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<h1><%= t('sso.login_error') %></h1>
|
||||
<h1><%= t('discourse_connect.login_error') %></h1>
|
||||
|
||||
<br/>
|
||||
|
||||
|
|
|
@ -1263,7 +1263,7 @@ en:
|
|||
set_primary: "Set Primary Email"
|
||||
destroy: "Remove Email"
|
||||
add_email: "Add Alternate Email"
|
||||
sso_override_instructions: "Email can be updated from SSO provider."
|
||||
auth_override_instructions: "Email can be updated from authentication provider."
|
||||
no_secondary: "No secondary emails"
|
||||
instructions: "Never shown to the public."
|
||||
admin_note: "Note: An admin user changing another non-admin user's email indicates the user has lost access to their original email account, so a reset password email will be sent to their new address. The user's email will not change until they complete the reset password process."
|
||||
|
@ -2648,7 +2648,7 @@ en:
|
|||
action: "Send Invite"
|
||||
help: "invite others to this topic via email or notifications"
|
||||
to_forum: "We'll send a brief email allowing your friend to immediately join by clicking a link."
|
||||
sso_enabled: "Enter the username of the person you'd like to invite to this topic."
|
||||
discourse_connect_enabled: "Enter the username of the person you'd like to invite to this topic."
|
||||
to_topic_blank: "Enter the username or email address of the person you'd like to invite to this topic."
|
||||
to_topic_email: "You've entered an email address. We'll email an invitation that allows your friend to immediately reply to this topic."
|
||||
to_topic_username: "You've entered a username. We'll send a notification with a link inviting them to this topic."
|
||||
|
@ -3863,7 +3863,7 @@ en:
|
|||
wordpress: Necessary for the WordPress wp-discourse plugin to work.
|
||||
users:
|
||||
bookmarks: List user bookmarks. It returns bookmark reminders when using the ICS format.
|
||||
sync_sso: Synchronize a user using SSO.
|
||||
sync_sso: Synchronize a user using DiscourseConnect.
|
||||
show: Obtain information about an user.
|
||||
check_emails: List user emails.
|
||||
update: Update user profile information.
|
||||
|
@ -4853,8 +4853,8 @@ en:
|
|||
on_grace_period: "Currently in promotion grace period, will not be demoted."
|
||||
locked_will_not_be_promoted: "Trust level locked. Will never be promoted."
|
||||
locked_will_not_be_demoted: "Trust level locked. Will never be demoted."
|
||||
sso:
|
||||
title: "Single Sign On"
|
||||
discourse_connect:
|
||||
title: "DiscourseConnect Single Sign On"
|
||||
external_id: "External ID"
|
||||
external_username: "Username"
|
||||
external_name: "Name"
|
||||
|
@ -4862,7 +4862,7 @@ en:
|
|||
external_avatar_url: "Profile Picture URL"
|
||||
last_payload: "Last Payload"
|
||||
delete_sso_record: "Delete SSO Record"
|
||||
confirm_delete: "Are you sure you would like to delete this single sign on (SSO) record?"
|
||||
confirm_delete: "Are you sure you would like to delete this DiscourseConnect record?"
|
||||
|
||||
user_fields:
|
||||
title: "User Fields"
|
||||
|
|
|
@ -180,7 +180,7 @@ en:
|
|||
one: is the wrong length (should be %{count} character)
|
||||
other: is the wrong length (should be %{count} characters)
|
||||
other_than: "must be other than %{count}"
|
||||
sso_overrides_username: "Username needs to be updated on SSO provider side, since `sso_overrides_username` setting is enabled."
|
||||
auth_overrides_username: "Username needs to be updated on authentication provider side, since `auth_overrides_username` setting is enabled."
|
||||
template:
|
||||
body: ! "There were problems with the following fields:"
|
||||
header:
|
||||
|
@ -204,7 +204,7 @@ en:
|
|||
share_quote_facebook_requirements: "You must set a Facebook app id to enable quote sharing for Facebook."
|
||||
second_factor_cannot_enforce_with_socials: "You cannot enforce 2FA with social logins enabled. You must first disable login via: %{auth_provider_names}"
|
||||
second_factor_cannot_be_enforced_with_disabled_local_login: "You cannot enforce 2FA if local logins are disabled."
|
||||
second_factor_cannot_be_enforced_with_sso_enabled: "You cannot enforce 2FA if SSO is enabled."
|
||||
second_factor_cannot_be_enforced_with_discourse_connect_enabled: "You cannot enforce 2FA if DiscourseConnect is enabled."
|
||||
local_login_cannot_be_disabled_if_second_factor_enforced: "You cannot disable local login if 2FA is enforced. Disable enforced 2FA before disabling local logins."
|
||||
cannot_enable_s3_uploads_when_s3_enabled_globally: "You cannot enable S3 uploads because S3 uploads are already globally enabled, and enabling this site-level could cause critical issues with uploads"
|
||||
cors_origins_should_not_have_trailing_slash: "You should not add the trailing slash (/) to CORS origins."
|
||||
|
@ -239,7 +239,7 @@ en:
|
|||
confirm_email: "<p>You’re almost done! We sent an activation mail to your email address. Please follow the instructions in the mail to activate your account.</p><p>If it doesn’t arrive, check your spam folder.</p>"
|
||||
cant_invite_to_group: "You are not allowed to invite users to specified group(s). Make sure you are owner of the group(s) you are trying to invite to."
|
||||
disabled_errors:
|
||||
sso_enabled: "Invites are disabled because SSO is enabled."
|
||||
discourse_connect_enabled: "Invites are disabled because DiscourseConnect is enabled."
|
||||
local_logins_disabled: "Invites are disabled because the 'enable local logins' setting is disabled."
|
||||
invalid_access: "You are not permitted to view the requested resource."
|
||||
|
||||
|
@ -448,7 +448,7 @@ en:
|
|||
one: "Maximum %{count} user can be added at once"
|
||||
other: "Maximum %{count} users can be added at once"
|
||||
usernames_or_emails_required: "Usernames or emails must be present"
|
||||
no_invites_with_sso: "You can invite only registered users when SSO is enabled"
|
||||
no_invites_with_discourse_connect: "You can invite only registered users when DiscourseConnect is enabled"
|
||||
no_invites_without_local_logins: "You can invite only registered users when local logins are disabled"
|
||||
default_names:
|
||||
everyone: "everyone"
|
||||
|
@ -1532,7 +1532,7 @@ en:
|
|||
detailed_404: "Provides more details to users about why they can’t access a particular topic. Note: This is less secure because users will know if a URL links to a valid topic."
|
||||
enforce_second_factor: "Forces users to enable two-factor authentication. Select 'all' to enforce it to all users. Select 'staff' to enforce it to staff users only."
|
||||
force_https: "Force your site to use HTTPS only. WARNING: do NOT enable this until you verify HTTPS is fully set up and working absolutely everywhere! Did you check your CDN, all social logins, and any external logos / dependencies to make sure they are all HTTPS compatible, too?"
|
||||
same_site_cookies: "Use same site cookies, they eliminate all vectors Cross Site Request Forgery on supported browsers (Lax or Strict). Warning: Strict will only work on sites that force login and use SSO."
|
||||
same_site_cookies: "Use same site cookies, they eliminate all vectors Cross Site Request Forgery on supported browsers (Lax or Strict). Warning: Strict will only work on sites that force login and use an external auth method."
|
||||
summary_score_threshold: "The minimum score required for a post to be included in 'Summarize This Topic'"
|
||||
summary_posts_required: "Minimum posts in a topic before 'Summarize This Topic' is enabled. Changes to this setting will be applied retroactively within a week."
|
||||
summary_likes_required: "Minimum likes in a topic before 'Summarize This Topic' is enabled. Changes to this setting will be applied retroactively within a week."
|
||||
|
@ -1656,27 +1656,27 @@ en:
|
|||
password_unique_characters: "Minimum number of unique characters that a password must have."
|
||||
block_common_passwords: "Don't allow passwords that are in the 10,000 most common passwords."
|
||||
|
||||
external_auth_skip_create_confirm: When signing up via external auth, skip the create account popup. Best used alongside sso_overrides_email, sso_overrides_username and sso_overrides_name.
|
||||
external_auth_immediately: "Automatically redirect to the external login system without user interaction. This only takes effect when login_required is true, and there is only one external authentication method"
|
||||
auth_skip_create_confirm: When signing up via external auth, skip the create account popup. Best used alongside auth_overrides_email, auth_overrides_username and auth_overrides_name.
|
||||
auth_immediately: "Automatically redirect to the external login system without user interaction. This only takes effect when login_required is true, and there is only one external authentication method"
|
||||
|
||||
enable_sso: "Enable single sign on via an external site (WARNING: USERS' EMAIL ADDRESSES *MUST* BE VALIDATED BY THE EXTERNAL SITE!)"
|
||||
verbose_sso_logging: "Log verbose SSO related diagnostics to <a href='%{base_path}/logs' target='_blank'>/logs</a>"
|
||||
enable_sso_provider: "Implement Discourse SSO provider protocol at the /session/sso_provider endpoint, requires sso_provider_secrets to be set"
|
||||
sso_url: "URL of single sign on endpoint (must include http:// or https://)"
|
||||
sso_secret: "Secret string used to cryptographically authenticate SSO information, be sure it is 10 characters or longer"
|
||||
sso_provider_secrets: "A list of domain-secret pairs that are using Discourse as an SSO provider. Make sure SSO secret is 10 characters or longer. Wildcard symbol * can be used to match any domain or only a part of it (e.g. *.example.com)."
|
||||
sso_overrides_bio: "Overrides user bio in user profile and prevents user from changing it"
|
||||
sso_overrides_groups: "Synchronize all manual group membership with groups specified in the groups sso attribute (WARNING: if you do not specify groups all manual group membership will be cleared for user)"
|
||||
sso_overrides_email: "Overrides local email with external site email from SSO payload on every login, and prevent local changes. Applies to all authentication providers. (WARNING: discrepancies can occur due to normalization of local emails)"
|
||||
sso_overrides_username: "Overrides local username with external site username from SSO payload on every login, and prevent local changes. Applies to all authentication providers. (WARNING: discrepancies can occur due to differences in username length/requirements)"
|
||||
sso_overrides_name: "Overrides local full name with external site full name from SSO payload on every login, and prevent local changes. Applies to all authentication providers."
|
||||
sso_overrides_avatar: "Overrides user avatar with external site avatar from SSO payload. If enabled, users will not be allowed to upload avatars on Discourse."
|
||||
sso_overrides_location: "Overrides user location with external location from SSO payload and prevent local changes."
|
||||
sso_overrides_website: "Overrides user website with external location from SSO payload and prevent local changes."
|
||||
sso_overrides_profile_background: "Overrides user profile background with external site avatar from SSO payload."
|
||||
sso_overrides_card_background: "Overrides user card background with external site avatar from SSO payload."
|
||||
sso_not_approved_url: "Redirect unapproved SSO accounts to this URL"
|
||||
sso_allows_all_return_paths: "Do not restrict the domain for return_paths provided by SSO (by default return path must be on current site)"
|
||||
enable_discourse_connect: "Enable sign on via DiscourseConnect (formerly 'Discourse SSO') (WARNING: USERS' EMAIL ADDRESSES *MUST* BE VALIDATED BY THE EXTERNAL SITE!)"
|
||||
verbose_discourse_connect_logging: "Log verbose DiscourseConnect related diagnostics to <a href='%{base_path}/logs' target='_blank'>/logs</a>"
|
||||
enable_discourse_connect_provider: "Implement DiscourseConnect (formerly 'Discourse SSO') provider protocol at the /session/sso_provider endpoint, requires discourse_connect_provider_secrets to be set"
|
||||
discourse_connect_url: "URL of DiscourseConnect endpoint (must include http:// or https://)"
|
||||
discourse_connect_secret: "Secret string used to cryptographically authenticate DiscourseConnect information, be sure it is 10 characters or longer"
|
||||
discourse_connect_provider_secrets: "A list of domain-secret pairs that are using DiscourseConnect. Make sure DiscourseConnect secret is 10 characters or longer. Wildcard symbol * can be used to match any domain or only a part of it (e.g. *.example.com)."
|
||||
discourse_connect_overrides_bio: "Overrides user bio in user profile and prevents user from changing it"
|
||||
discourse_connect_overrides_groups: "Synchronize all manual group membership with groups specified in the groups attribute (WARNING: if you do not specify groups all manual group membership will be cleared for user)"
|
||||
auth_overrides_email: "Overrides local email with external site email on every login, and prevent local changes. Applies to all authentication providers. (WARNING: discrepancies can occur due to normalization of local emails)"
|
||||
auth_overrides_username: "Overrides local username with external site username on every login, and prevent local changes. Applies to all authentication providers. (WARNING: discrepancies can occur due to differences in username length/requirements)"
|
||||
auth_overrides_name: "Overrides local full name with external site full name on every login, and prevent local changes. Applies to all authentication providers."
|
||||
discourse_connect_overrides_avatar: "Overrides user avatar with external site avatar from DiscourseConnect payload. If enabled, users will not be allowed to upload avatars on Discourse."
|
||||
discourse_connect_overrides_location: "Overrides user location with external location from DiscourseConnect payload and prevent local changes."
|
||||
discourse_connect_overrides_website: "Overrides user website with external location from DiscourseConnect payload and prevent local changes."
|
||||
discourse_connect_overrides_profile_background: "Overrides user profile background with external site avatar from DiscourseConnect payload."
|
||||
discourse_connect_overrides_card_background: "Overrides user card background with external site avatar from DiscourseConnect payload."
|
||||
discourse_connect_not_approved_url: "Redirect unapproved DiscourseConnect accounts to this URL"
|
||||
discourse_connect_allows_all_return_paths: "Do not restrict the domain for return_paths provided by DiscourseConnect (by default return path must be on current site)"
|
||||
|
||||
enable_local_logins: "Enable local username and password login based accounts. This must be enabled for invites to work. WARNING: if disabled, you may be unable to log in if you have not previously configured at least one alternate login method."
|
||||
enable_local_logins_via_email: "Allow users to request a one-click login link to be sent to them via email."
|
||||
|
@ -2313,8 +2313,8 @@ en:
|
|||
email_editable_enabled: "You must disable 'email editable' before enabling this setting."
|
||||
staged_users_disabled: "You must first enable 'staged users' before enabling this setting."
|
||||
reply_by_email_disabled: "You must first enable 'reply by email' before enabling this setting."
|
||||
sso_url_is_empty: "You must set a 'sso url' before enabling this setting."
|
||||
sso_invite_only: "You cannot enable sso and invite only at the same time."
|
||||
discourse_connect_url_is_empty: "You must set a 'discourse connect url' before enabling this setting."
|
||||
discourse_connect_invite_only: "You cannot enable DiscourseConnect and invite only at the same time."
|
||||
enable_local_logins_disabled: "You must first enable 'enable local logins' before enabling this setting."
|
||||
min_username_length_exists: "You cannot set the minimum username length above the shortest username (%{username})."
|
||||
min_username_length_range: "You cannot set the minimum above the maximum."
|
||||
|
@ -2334,9 +2334,9 @@ en:
|
|||
list_value_count: "The list must contain exactly %{count} values."
|
||||
|
||||
placeholder:
|
||||
sso_provider_secrets:
|
||||
discourse_connect_provider_secrets:
|
||||
key: "www.example.com"
|
||||
value: "SSO secret"
|
||||
value: "DiscourseConnect secret"
|
||||
|
||||
search:
|
||||
extreme_load_error: "Site is under extreme load, search is disabled, try again later"
|
||||
|
@ -2349,7 +2349,7 @@ en:
|
|||
audio: "[audio]"
|
||||
video: "[video]"
|
||||
|
||||
sso:
|
||||
discourse_connect:
|
||||
login_error: "Login Error"
|
||||
not_found: "Your account couldn't be found. Please contact the site's administrator."
|
||||
account_not_approved: "Your account is pending approval. You will receive an email notification when you are approved."
|
||||
|
@ -2358,7 +2358,7 @@ en:
|
|||
no_email: "No email address was provided. Please contact the site's administrator."
|
||||
blank_id_error: "The `external_id` is required but was blank"
|
||||
email_error: "An account could not be registered with the email address <b>%{email}</b>. Please contact the site's administrator."
|
||||
missing_secret: "SSO authentication failed due to missing secret. Contact the site administrators to fix this problem."
|
||||
missing_secret: "Authentication failed due to missing secret. Contact the site administrators to fix this problem."
|
||||
|
||||
original_poster: "Original Poster"
|
||||
most_posts: "Most Posts"
|
||||
|
|
|
@ -423,31 +423,31 @@ login:
|
|||
default: ""
|
||||
type: list
|
||||
list_type: simple
|
||||
external_auth_skip_create_confirm:
|
||||
auth_skip_create_confirm:
|
||||
default: false
|
||||
client: true
|
||||
external_auth_immediately:
|
||||
auth_immediately:
|
||||
default: true
|
||||
enable_sso:
|
||||
enable_discourse_connect:
|
||||
client: true
|
||||
default: false
|
||||
validator: "EnableSsoValidator"
|
||||
sso_allows_all_return_paths: false
|
||||
enable_sso_provider: false
|
||||
verbose_sso_logging: false
|
||||
discourse_connect_allows_all_return_paths: false
|
||||
enable_discourse_connect_provider: false
|
||||
verbose_discourse_connect_logging: false
|
||||
verbose_auth_token_logging:
|
||||
hidden: true
|
||||
default: true
|
||||
max_suspicious_distance_km:
|
||||
hidden: true
|
||||
default: 500
|
||||
sso_url:
|
||||
discourse_connect_url:
|
||||
default: ""
|
||||
regex: '^https?:\/\/.+[^\/]$'
|
||||
sso_secret:
|
||||
discourse_connect_secret:
|
||||
default: ""
|
||||
secret: true
|
||||
sso_provider_secrets:
|
||||
discourse_connect_provider_secrets:
|
||||
default: ""
|
||||
type: list
|
||||
list_type: secret
|
||||
|
@ -455,22 +455,22 @@ login:
|
|||
placeholder:
|
||||
key: "sso_provider.key_placeholder"
|
||||
value: "sso_provider.value_placeholder"
|
||||
sso_overrides_groups: false
|
||||
sso_overrides_bio: false
|
||||
sso_overrides_email:
|
||||
discourse_connect_overrides_groups: false
|
||||
discourse_connect_overrides_bio: false
|
||||
auth_overrides_email:
|
||||
default: false
|
||||
validator: "SsoOverridesEmailValidator"
|
||||
client: true
|
||||
sso_overrides_username: false
|
||||
sso_overrides_name: false
|
||||
sso_overrides_avatar:
|
||||
auth_overrides_username: false
|
||||
auth_overrides_name: false
|
||||
discourse_connect_overrides_avatar:
|
||||
default: false
|
||||
client: true
|
||||
sso_overrides_profile_background: false
|
||||
sso_overrides_location: false
|
||||
sso_overrides_website: false
|
||||
sso_overrides_card_background: false
|
||||
sso_not_approved_url: ""
|
||||
discourse_connect_overrides_profile_background: false
|
||||
discourse_connect_overrides_location: false
|
||||
discourse_connect_overrides_website: false
|
||||
discourse_connect_overrides_card_background: false
|
||||
discourse_connect_not_approved_url: ""
|
||||
blocked_email_domains:
|
||||
default: "mailinator.com"
|
||||
type: list
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
class AddSsoProviderSecretsToSiteSettings < ActiveRecord::Migration[5.2]
|
||||
def up
|
||||
return unless SiteSetting.enable_sso_provider && SiteSetting.sso_secret.present?
|
||||
sso_secret = SiteSetting.sso_secret
|
||||
sso_secret_insert = ActiveRecord::Base.connection.quote("*|#{sso_secret}")
|
||||
|
||||
execute "INSERT INTO site_settings(name, data_type, value, created_at, updated_at)
|
||||
VALUES ('sso_provider_secrets', 8, #{sso_secret_insert}, now(), now())"
|
||||
execute <<~SQL
|
||||
INSERT INTO site_settings(name, data_type, value, created_at, updated_at)
|
||||
SELECT 'sso_provider_secrets', 8, '*|' || value, now(), now()
|
||||
FROM site_settings WHERE name = 'sso_secret'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM site_settings WHERE name = 'enable_sso_provider' AND value = 't'
|
||||
)
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RenameSsoSiteSettings < ActiveRecord::Migration[6.0]
|
||||
RENAME_SETTINGS = [
|
||||
['enable_sso', 'enable_discourse_connect'],
|
||||
['sso_allows_all_return_paths', 'discourse_connect_allows_all_return_paths'],
|
||||
['enable_sso_provider', 'enable_discourse_connect_provider'],
|
||||
['verbose_sso_logging', 'verbose_discourse_connect_logging'],
|
||||
['sso_url', 'discourse_connect_url'],
|
||||
['sso_secret', 'discourse_connect_secret'],
|
||||
['sso_provider_secrets', 'discourse_connect_provider_secrets'],
|
||||
['sso_overrides_groups', 'discourse_connect_overrides_groups'],
|
||||
['sso_overrides_bio', 'discourse_connect_overrides_bio'],
|
||||
['sso_overrides_email', 'auth_overrides_email'],
|
||||
['sso_overrides_username', 'auth_overrides_username'],
|
||||
['sso_overrides_name', 'auth_overrides_name'],
|
||||
['sso_overrides_avatar', 'discourse_connect_overrides_avatar'],
|
||||
['sso_overrides_profile_background', 'discourse_connect_overrides_profile_background'],
|
||||
['sso_overrides_location', 'discourse_connect_overrides_location'],
|
||||
['sso_overrides_website', 'discourse_connect_overrides_website'],
|
||||
['sso_overrides_card_background', 'discourse_connect_overrides_card_background'],
|
||||
['external_auth_skip_create_confirm', 'auth_skip_create_confirm'],
|
||||
['external_auth_immediately', 'auth_immediately']
|
||||
]
|
||||
|
||||
def up
|
||||
# Copying the rows so that things keep working during deploy
|
||||
# TODO: Add a post-deploy migration to drop the old rows
|
||||
|
||||
RENAME_SETTINGS.each do |old_name, new_name|
|
||||
execute <<~SQL
|
||||
INSERT INTO site_settings (name, data_type, value, created_at, updated_at)
|
||||
SELECT '#{new_name}', data_type, value, created_at, updated_at
|
||||
FROM site_settings
|
||||
WHERE name = '#{old_name}'
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
|
@ -70,17 +70,17 @@ class Auth::Result
|
|||
|
||||
def apply_user_attributes!
|
||||
change_made = false
|
||||
if SiteSetting.sso_overrides_username? && username.present? && username != user.username
|
||||
if SiteSetting.auth_overrides_username? && username.present? && username != user.username
|
||||
user.username = UserNameSuggester.suggest(username || name || email, user.username)
|
||||
change_made = true
|
||||
end
|
||||
|
||||
if SiteSetting.sso_overrides_email && email_valid && email.present? && user.email != Email.downcase(email)
|
||||
if SiteSetting.auth_overrides_email && email_valid && email.present? && user.email != Email.downcase(email)
|
||||
user.email = email
|
||||
change_made = true
|
||||
end
|
||||
|
||||
if SiteSetting.sso_overrides_name && name.present? && user.name != name
|
||||
if SiteSetting.auth_overrides_name && name.present? && user.name != name
|
||||
user.name = name
|
||||
change_made = true
|
||||
end
|
||||
|
@ -89,11 +89,11 @@ class Auth::Result
|
|||
end
|
||||
|
||||
def can_edit_name
|
||||
!SiteSetting.sso_overrides_name
|
||||
!SiteSetting.auth_overrides_name
|
||||
end
|
||||
|
||||
def can_edit_username
|
||||
!(SiteSetting.sso_overrides_username || omit_username)
|
||||
!(SiteSetting.auth_overrides_username || omit_username)
|
||||
end
|
||||
|
||||
def to_client_hash
|
||||
|
|
|
@ -78,7 +78,7 @@ class ComposerMessagesFinder
|
|||
# - "disable avatar education message" is enabled
|
||||
# - "sso overrides avatar" is enabled
|
||||
# - "allow uploaded avatars" is disabled
|
||||
return if SiteSetting.disable_avatar_education_message || SiteSetting.sso_overrides_avatar || !SiteSetting.allow_uploaded_avatars
|
||||
return if SiteSetting.disable_avatar_education_message || SiteSetting.discourse_connect_overrides_avatar || !SiteSetting.allow_uploaded_avatars
|
||||
|
||||
# If we got this far, log that we've nagged them about the avatar
|
||||
UserHistory.create!(action: UserHistory.actions[:notified_about_avatar], target_user_id: @user.id)
|
||||
|
|
|
@ -353,7 +353,7 @@ class Guardian
|
|||
def can_invite_to_forum?(groups = nil)
|
||||
authenticated? &&
|
||||
(SiteSetting.max_invites_per_day.to_i > 0 || is_staff?) &&
|
||||
!SiteSetting.enable_sso &&
|
||||
!SiteSetting.enable_discourse_connect &&
|
||||
SiteSetting.enable_local_logins &&
|
||||
(
|
||||
(!SiteSetting.must_approve_users? && @user.has_trust_level?(SiteSetting.min_trust_level_to_allow_invite.to_i)) ||
|
||||
|
@ -391,7 +391,7 @@ class Guardian
|
|||
|
||||
def can_invite_via_email?(object)
|
||||
return false unless can_invite_to?(object)
|
||||
!SiteSetting.enable_sso && SiteSetting.enable_local_logins && (!SiteSetting.must_approve_users? || is_staff?)
|
||||
!SiteSetting.enable_discourse_connect && SiteSetting.enable_local_logins && (!SiteSetting.must_approve_users? || is_staff?)
|
||||
end
|
||||
|
||||
def can_bulk_invite_to_forum?(user)
|
||||
|
|
|
@ -23,7 +23,7 @@ module UserGuardian
|
|||
end
|
||||
|
||||
def can_edit_username?(user)
|
||||
return false if SiteSetting.sso_overrides_username?
|
||||
return false if SiteSetting.auth_overrides_username?
|
||||
return true if is_staff?
|
||||
return false if SiteSetting.username_change_period <= 0
|
||||
return false if is_anonymous?
|
||||
|
@ -31,7 +31,7 @@ module UserGuardian
|
|||
end
|
||||
|
||||
def can_edit_email?(user)
|
||||
return false if SiteSetting.sso_overrides_email?
|
||||
return false if SiteSetting.auth_overrides_email?
|
||||
return false unless SiteSetting.email_editable?
|
||||
return true if is_staff?
|
||||
return false if is_anonymous?
|
||||
|
@ -40,7 +40,7 @@ module UserGuardian
|
|||
|
||||
def can_edit_name?(user)
|
||||
return false unless SiteSetting.enable_names?
|
||||
return false if SiteSetting.sso_overrides_name?
|
||||
return false if SiteSetting.auth_overrides_name?
|
||||
return true if is_staff?
|
||||
return false if is_anonymous?
|
||||
can_edit?(user)
|
||||
|
@ -61,7 +61,7 @@ module UserGuardian
|
|||
def can_delete_user?(user)
|
||||
return false if user.nil? || user.admin?
|
||||
if is_me?(user)
|
||||
!SiteSetting.enable_sso &&
|
||||
!SiteSetting.enable_discourse_connect &&
|
||||
!user.has_more_posts_than?(SiteSetting.delete_user_self_max_post_count)
|
||||
else
|
||||
is_staff? && (
|
||||
|
@ -173,6 +173,6 @@ module UserGuardian
|
|||
end
|
||||
|
||||
def can_delete_sso_record?(user)
|
||||
SiteSetting.enable_sso && user && is_admin?
|
||||
SiteSetting.enable_discourse_connect && user && is_admin?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ class SingleSignOnProvider < SingleSignOn
|
|||
set_return_sso_url(payload)
|
||||
if sso_secret.blank? && self.sso_secret.blank?
|
||||
host = URI.parse(@return_sso_url).host
|
||||
Rails.logger.warn("SSO failed; website #{host} is not in the `sso_provider_secrets` site settings")
|
||||
Rails.logger.warn("SSO failed; website #{host} is not in the `discourse_connect_provider_secrets` site settings")
|
||||
raise BlankSecret
|
||||
end
|
||||
|
||||
|
@ -24,9 +24,9 @@ class SingleSignOnProvider < SingleSignOn
|
|||
end
|
||||
|
||||
def self.sso_secret
|
||||
return nil unless @return_sso_url && SiteSetting.enable_sso_provider
|
||||
return nil unless @return_sso_url && SiteSetting.enable_discourse_connect_provider
|
||||
|
||||
provider_secrets = SiteSetting.sso_provider_secrets.split(/[|\n]/)
|
||||
provider_secrets = SiteSetting.discourse_connect_provider_secrets.split(/[|\n]/)
|
||||
provider_secrets_hash = Hash[*provider_secrets]
|
||||
return_url_host = URI.parse(@return_sso_url).host
|
||||
# moves wildcard domains to the end of hash
|
||||
|
|
|
@ -10,7 +10,27 @@ module SiteSettings::DeprecatedSettings
|
|||
['enable_category_group_review', 'enable_category_group_moderation', true, '2.7'],
|
||||
['newuser_max_images', 'newuser_max_embedded_media', true, '2.7'],
|
||||
['min_trust_to_post_images', 'min_trust_to_post_embedded_media', true, '2.7'],
|
||||
['moderators_create_categories', 'moderators_manage_categories_and_groups', '2.7']
|
||||
['moderators_create_categories', 'moderators_manage_categories_and_groups', '2.7'],
|
||||
|
||||
['enable_sso', 'enable_discourse_connect', true, '2.8'],
|
||||
['sso_allows_all_return_paths', 'discourse_connect_allows_all_return_paths', true, '2.8'],
|
||||
['enable_sso_provider', 'enable_discourse_connect_provider', true, '2.8'],
|
||||
['verbose_sso_logging', 'verbose_discourse_connect_logging', true, '2.8'],
|
||||
['sso_url', 'discourse_connect_url', true, '2.8'],
|
||||
['sso_secret', 'discourse_connect_secret', true, '2.8'],
|
||||
['sso_provider_secrets', 'discourse_connect_provider_secrets', true, '2.8'],
|
||||
['sso_overrides_groups', 'discourse_connect_overrides_groups', true, '2.8'],
|
||||
['sso_overrides_bio', 'discourse_connect_overrides_bio', true, '2.8'],
|
||||
['sso_overrides_email', 'auth_overrides_email', true, '2.8'],
|
||||
['sso_overrides_username', 'auth_overrides_username', true, '2.8'],
|
||||
['sso_overrides_name', 'auth_overrides_name', true, '2.8'],
|
||||
['sso_overrides_avatar', 'discourse_connect_overrides_avatar', true, '2.8'],
|
||||
['sso_overrides_profile_background', 'discourse_connect_overrides_profile_background', true, '2.8'],
|
||||
['sso_overrides_location', 'discourse_connect_overrides_location', true, '2.8'],
|
||||
['sso_overrides_website', 'discourse_connect_overrides_website', true, '2.8'],
|
||||
['sso_overrides_card_background', 'discourse_connect_overrides_card_background', true, '2.8'],
|
||||
['external_auth_skip_create_confirm', 'auth_skip_create_confirm', true, '2.8'],
|
||||
['external_auth_immediately', 'auth_immediately', true, '2.8'],
|
||||
]
|
||||
|
||||
def setup_deprecated_methods
|
||||
|
|
|
@ -177,8 +177,8 @@ module SiteSettings::Validations
|
|||
end
|
||||
|
||||
def validate_enforce_second_factor(new_val)
|
||||
if SiteSetting.enable_sso?
|
||||
return validate_error :second_factor_cannot_be_enforced_with_sso_enabled
|
||||
if SiteSetting.enable_discourse_connect?
|
||||
return validate_error :second_factor_cannot_be_enforced_with_discourse_connect_enabled
|
||||
end
|
||||
if new_val == "all" && Discourse.enabled_auth_providers.count > 0
|
||||
auth_provider_names = Discourse.enabled_auth_providers.map(&:name).join(", ")
|
||||
|
|
|
@ -7,10 +7,10 @@ class EnableInviteOnlyValidator
|
|||
|
||||
def valid_value?(val)
|
||||
return true if val == 'f'
|
||||
!SiteSetting.enable_sso?
|
||||
!SiteSetting.enable_discourse_connect?
|
||||
end
|
||||
|
||||
def error_message
|
||||
I18n.t('site_settings.errors.sso_invite_only')
|
||||
I18n.t('site_settings.errors.discourse_connect_invite_only')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,12 +7,12 @@ class EnableSsoValidator
|
|||
|
||||
def valid_value?(val)
|
||||
return true if val == 'f'
|
||||
return false if SiteSetting.sso_url.blank? || SiteSetting.invite_only?
|
||||
return false if SiteSetting.discourse_connect_url.blank? || SiteSetting.invite_only?
|
||||
true
|
||||
end
|
||||
|
||||
def error_message
|
||||
return I18n.t('site_settings.errors.sso_url_is_empty') if SiteSetting.sso_url.blank?
|
||||
return I18n.t('site_settings.errors.sso_invite_only') if SiteSetting.invite_only?
|
||||
return I18n.t('site_settings.errors.discourse_connect_url_is_empty') if SiteSetting.discourse_connect_url.blank?
|
||||
return I18n.t('site_settings.errors.discourse_connect_invite_only') if SiteSetting.invite_only?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ SiteSetting.refresh!
|
|||
tests = [
|
||||
["current cache", lambda do
|
||||
SiteSetting.title
|
||||
SiteSetting.enable_sso
|
||||
SiteSetting.enable_discourse_connect
|
||||
end
|
||||
],
|
||||
["change default locale with current cache refreshed", lambda do
|
||||
|
|
|
@ -13,7 +13,7 @@ require File.expand_path('../../../../config/environment', __FILE__)
|
|||
|
||||
# warming up
|
||||
SiteSetting.title
|
||||
SiteSetting.enable_sso
|
||||
SiteSetting.enable_discourse_connect
|
||||
SiteSetting.default_locale = SiteSetting.default_locale == 'en' ? 'zh_CN' : 'en'
|
||||
SiteSetting.title = SecureRandom.hex
|
||||
|
||||
|
@ -22,7 +22,7 @@ profile do
|
|||
end
|
||||
|
||||
profile do
|
||||
SiteSetting.enable_sso
|
||||
SiteSetting.enable_discourse_connect
|
||||
end
|
||||
|
||||
profile do
|
||||
|
|
|
@ -138,8 +138,8 @@ describe ComposerMessagesFinder do
|
|||
expect(finder.check_avatar_notification).to be_blank
|
||||
end
|
||||
|
||||
it "doesn't notify users if 'sso_overrides_avatar' setting is enabled" do
|
||||
SiteSetting.sso_overrides_avatar = true
|
||||
it "doesn't notify users if 'discourse_connect_overrides_avatar' setting is enabled" do
|
||||
SiteSetting.discourse_connect_overrides_avatar = true
|
||||
expect(finder.check_avatar_notification).to be_blank
|
||||
end
|
||||
|
||||
|
|
|
@ -111,8 +111,8 @@ RSpec.describe SecondFactorManager do
|
|||
|
||||
describe 'when SSO is enabled' do
|
||||
it 'should return false' do
|
||||
SiteSetting.sso_url = 'http://someurl.com'
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = 'http://someurl.com'
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
expect(user.totp_enabled?).to eq(false)
|
||||
end
|
||||
|
@ -437,8 +437,8 @@ RSpec.describe SecondFactorManager do
|
|||
|
||||
describe 'when SSO is enabled' do
|
||||
it 'should return false' do
|
||||
SiteSetting.sso_url = 'http://someurl.com'
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = 'http://someurl.com'
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
expect(user_backup.backup_codes_enabled?).to eq(false)
|
||||
end
|
||||
|
|
|
@ -237,8 +237,8 @@ describe UserGuardian do
|
|||
include_examples "can_delete_user examples"
|
||||
|
||||
it "isn't allowed when SSO is enabled" do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
expect(guardian.can_delete_user?(user)).to eq(false)
|
||||
end
|
||||
|
||||
|
|
|
@ -690,8 +690,8 @@ describe Guardian do
|
|||
end
|
||||
|
||||
it 'returns false for all users when sso is enabled' do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
expect(Guardian.new(trust_level_2).can_invite_via_email?(topic)).to be_falsey
|
||||
expect(Guardian.new(moderator).can_invite_via_email?(topic)).to be_falsey
|
||||
|
@ -2714,9 +2714,9 @@ describe Guardian do
|
|||
|
||||
context 'when SSO username override is active' do
|
||||
before do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.sso_overrides_username = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.auth_overrides_username = true
|
||||
end
|
||||
|
||||
it "is false for admins" do
|
||||
|
@ -2799,9 +2799,9 @@ describe Guardian do
|
|||
context 'when SSO email override is active' do
|
||||
before do
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
end
|
||||
|
||||
it "is false for admins" do
|
||||
|
@ -2878,8 +2878,8 @@ describe Guardian do
|
|||
|
||||
context 'when SSO is disabled' do
|
||||
before do
|
||||
SiteSetting.enable_sso = false
|
||||
SiteSetting.sso_overrides_name = false
|
||||
SiteSetting.enable_discourse_connect = false
|
||||
SiteSetting.auth_overrides_name = false
|
||||
end
|
||||
|
||||
it 'is true for admins' do
|
||||
|
@ -2897,13 +2897,13 @@ describe Guardian do
|
|||
|
||||
context 'when SSO is enabled' do
|
||||
before do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
end
|
||||
|
||||
context 'when SSO name override is active' do
|
||||
before do
|
||||
SiteSetting.sso_overrides_name = true
|
||||
SiteSetting.auth_overrides_name = true
|
||||
end
|
||||
|
||||
it 'is false for admins' do
|
||||
|
@ -2921,7 +2921,7 @@ describe Guardian do
|
|||
|
||||
context 'when SSO name override is not active' do
|
||||
before do
|
||||
SiteSetting.sso_overrides_name = false
|
||||
SiteSetting.auth_overrides_name = false
|
||||
end
|
||||
|
||||
it 'is true for admins' do
|
||||
|
|
|
@ -7,8 +7,8 @@ RSpec.describe EnableInviteOnlyValidator do
|
|||
|
||||
context "when sso is enabled" do
|
||||
before do
|
||||
SiteSetting.sso_url = "https://example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
end
|
||||
|
||||
it "is valid when false" do
|
||||
|
@ -18,7 +18,7 @@ RSpec.describe EnableInviteOnlyValidator do
|
|||
it "is isn't value for true" do
|
||||
expect(subject.valid_value?('t')).to eq(false)
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
'site_settings.errors.sso_invite_only'
|
||||
'site_settings.errors.discourse_connect_invite_only'
|
||||
))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe EnableSsoValidator do
|
|||
describe '#valid_value?' do
|
||||
describe "when 'sso url' is empty" do
|
||||
before do
|
||||
SiteSetting.sso_url = ""
|
||||
SiteSetting.discourse_connect_url = ""
|
||||
end
|
||||
|
||||
describe 'when val is false' do
|
||||
|
@ -22,7 +22,7 @@ RSpec.describe EnableSsoValidator do
|
|||
expect(subject.valid_value?('t')).to eq(false)
|
||||
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
'site_settings.errors.sso_url_is_empty'
|
||||
'site_settings.errors.discourse_connect_url_is_empty'
|
||||
))
|
||||
end
|
||||
end
|
||||
|
@ -31,7 +31,7 @@ RSpec.describe EnableSsoValidator do
|
|||
describe "when invite_only is set" do
|
||||
before do
|
||||
SiteSetting.invite_only = true
|
||||
SiteSetting.sso_url = 'https://example.com/sso'
|
||||
SiteSetting.discourse_connect_url = 'https://example.com/sso'
|
||||
end
|
||||
|
||||
it 'allows a false value' do
|
||||
|
@ -41,14 +41,14 @@ RSpec.describe EnableSsoValidator do
|
|||
it "doesn't allow true" do
|
||||
expect(subject.valid_value?('t')).to eq(false)
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
'site_settings.errors.sso_invite_only'
|
||||
'site_settings.errors.discourse_connect_invite_only'
|
||||
))
|
||||
end
|
||||
end
|
||||
|
||||
describe "when 'sso url' is present" do
|
||||
before do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
end
|
||||
|
||||
describe 'when value is false' do
|
||||
|
|
|
@ -8,8 +8,8 @@ RSpec.describe SsoOverridesEmailValidator do
|
|||
describe '#valid_value?' do
|
||||
describe "when 'email editable' is true" do
|
||||
before do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.email_editable = true
|
||||
end
|
||||
|
||||
|
@ -32,8 +32,8 @@ RSpec.describe SsoOverridesEmailValidator do
|
|||
|
||||
describe "when 'email editable' is false" do
|
||||
before do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.email_editable = false
|
||||
end
|
||||
|
||||
|
|
|
@ -210,8 +210,8 @@ describe Jobs::ExportCsvFile do
|
|||
end
|
||||
|
||||
it 'exports sso data' do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
user = Fabricate(:user)
|
||||
user.user_profile.update_column(:location, "La,La Land")
|
||||
user.create_single_sign_on_record(external_id: "123", last_payload: "xxx", external_email: 'test@test.com')
|
||||
|
|
|
@ -151,10 +151,10 @@ describe SiteSettings::Validations do
|
|||
end
|
||||
|
||||
context "when SSO is enabled" do
|
||||
let(:error_message) { I18n.t("errors.site_settings.second_factor_cannot_be_enforced_with_sso_enabled") }
|
||||
let(:error_message) { I18n.t("errors.site_settings.second_factor_cannot_be_enforced_with_discourse_connect_enabled") }
|
||||
before do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
end
|
||||
|
||||
it "should raise an error" do
|
||||
|
|
|
@ -4,12 +4,12 @@ require "rails_helper"
|
|||
|
||||
describe DiscourseSingleSignOn do
|
||||
before do
|
||||
@sso_url = "http://example.com/discourse_sso"
|
||||
@sso_secret = "shjkfdhsfkjh"
|
||||
@discourse_connect_url = "http://example.com/discourse_sso"
|
||||
@discourse_connect_secret = "shjkfdhsfkjh"
|
||||
|
||||
SiteSetting.sso_url = @sso_url
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.sso_secret = @sso_secret
|
||||
SiteSetting.discourse_connect_url = @discourse_connect_url
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.discourse_connect_secret = @discourse_connect_secret
|
||||
Jobs.run_immediately!
|
||||
end
|
||||
|
||||
|
@ -114,7 +114,7 @@ describe DiscourseSingleSignOn do
|
|||
end
|
||||
|
||||
it "unstaged users" do
|
||||
SiteSetting.sso_overrides_name = true
|
||||
SiteSetting.auth_overrides_name = true
|
||||
|
||||
email = "staged@user.com"
|
||||
Fabricate(:user, staged: true, email: email)
|
||||
|
@ -195,7 +195,7 @@ describe DiscourseSingleSignOn do
|
|||
sso.groups = "#{group2.name.capitalize},group4,badname,trust_level_4"
|
||||
sso.lookup_or_create_user(ip_address)
|
||||
|
||||
SiteSetting.sso_overrides_groups = true
|
||||
SiteSetting.discourse_connect_overrides_groups = true
|
||||
|
||||
group1.reload
|
||||
expect(group1.usernames).to eq("")
|
||||
|
@ -260,7 +260,7 @@ describe DiscourseSingleSignOn do
|
|||
end
|
||||
|
||||
it 'can override username properly when only the case changes' do
|
||||
SiteSetting.sso_overrides_username = true
|
||||
SiteSetting.auth_overrides_username = true
|
||||
|
||||
sso = DiscourseSingleSignOn.new
|
||||
sso.username = "testuser"
|
||||
|
@ -280,8 +280,8 @@ describe DiscourseSingleSignOn do
|
|||
expect(user.username).to eq "TestUser"
|
||||
end
|
||||
|
||||
it 'behaves properly when sso_overrides_username is set but username is missing or blank' do
|
||||
SiteSetting.sso_overrides_username = true
|
||||
it 'behaves properly when auth_overrides_username is set but username is missing or blank' do
|
||||
SiteSetting.auth_overrides_username = true
|
||||
|
||||
sso = DiscourseSingleSignOn.new
|
||||
sso.username = "testuser"
|
||||
|
@ -310,9 +310,9 @@ describe DiscourseSingleSignOn do
|
|||
admin = Fabricate(:admin)
|
||||
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_overrides_name = true
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.sso_overrides_username = true
|
||||
SiteSetting.auth_overrides_name = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
SiteSetting.auth_overrides_username = true
|
||||
|
||||
sso = DiscourseSingleSignOn.new
|
||||
sso.username = "bob%the$admin"
|
||||
|
@ -378,7 +378,7 @@ describe DiscourseSingleSignOn do
|
|||
|
||||
it "generates a correct sso url" do
|
||||
url, payload = DiscourseSingleSignOn.generate_url.split("?")
|
||||
expect(url).to eq @sso_url
|
||||
expect(url).to eq @discourse_connect_url
|
||||
|
||||
sso = DiscourseSingleSignOn.parse(payload)
|
||||
expect(sso.nonce).to_not be_nil
|
||||
|
@ -447,7 +447,7 @@ describe DiscourseSingleSignOn do
|
|||
|
||||
it 'does not deactivate user if email provided is capitalized' do
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
sso.require_activation = true
|
||||
|
||||
user = sso.lookup_or_create_user(ip_address)
|
||||
|
@ -465,7 +465,7 @@ describe DiscourseSingleSignOn do
|
|||
it 'deactivates accounts that have updated email address' do
|
||||
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
sso.require_activation = true
|
||||
|
||||
user = sso.lookup_or_create_user(ip_address)
|
||||
|
@ -567,7 +567,7 @@ describe DiscourseSingleSignOn do
|
|||
|
||||
# yes override if site setting
|
||||
sso.bio = "new profile 2"
|
||||
SiteSetting.sso_overrides_bio = true
|
||||
SiteSetting.discourse_connect_overrides_bio = true
|
||||
|
||||
user = sso.lookup_or_create_user(ip_address)
|
||||
expect(user.user_profile.bio_cooked).to match_html("<p>new profile 2</p")
|
||||
|
@ -575,7 +575,7 @@ describe DiscourseSingleSignOn do
|
|||
|
||||
end
|
||||
|
||||
context 'when sso_overrides_avatar is not enabled' do
|
||||
context 'when discourse_connect_overrides_avatar is not enabled' do
|
||||
|
||||
it "correctly handles provided avatar_urls" do
|
||||
sso = DiscourseSingleSignOn.new
|
||||
|
@ -635,7 +635,7 @@ describe DiscourseSingleSignOn do
|
|||
|
||||
end
|
||||
|
||||
context 'when sso_overrides_avatar is enabled' do
|
||||
context 'when discourse_connect_overrides_avatar is enabled' do
|
||||
fab!(:sso_record) { Fabricate(:single_sign_on_record, external_avatar_url: "http://example.com/an_image.png") }
|
||||
|
||||
let!(:sso) {
|
||||
|
@ -650,7 +650,7 @@ describe DiscourseSingleSignOn do
|
|||
let(:logo) { file_from_fixtures("logo.png") }
|
||||
|
||||
before do
|
||||
SiteSetting.sso_overrides_avatar = true
|
||||
SiteSetting.discourse_connect_overrides_avatar = true
|
||||
end
|
||||
|
||||
it "deal with no avatar url passed for an existing user with an avatar" do
|
||||
|
@ -683,7 +683,7 @@ describe DiscourseSingleSignOn do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when sso_overrides_profile_background is not enabled' do
|
||||
context 'when discourse_connect_overrides_profile_background is not enabled' do
|
||||
|
||||
it "correctly handles provided profile_background_urls" do
|
||||
sso = DiscourseSingleSignOn.new
|
||||
|
@ -715,7 +715,7 @@ describe DiscourseSingleSignOn do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when sso_overrides_profile_background is enabled' do
|
||||
context 'when discourse_connect_overrides_profile_background is enabled' do
|
||||
fab!(:sso_record) { Fabricate(:single_sign_on_record, external_profile_background_url: "http://example.com/an_image.png") }
|
||||
|
||||
let!(:sso) {
|
||||
|
@ -730,7 +730,7 @@ describe DiscourseSingleSignOn do
|
|||
let(:logo) { file_from_fixtures("logo.png") }
|
||||
|
||||
before do
|
||||
SiteSetting.sso_overrides_profile_background = true
|
||||
SiteSetting.discourse_connect_overrides_profile_background = true
|
||||
end
|
||||
|
||||
it "deal with no profile_background_url passed for an existing user with a profile_background" do
|
||||
|
@ -755,7 +755,7 @@ describe DiscourseSingleSignOn do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when sso_overrides_card_background is not enabled' do
|
||||
context 'when discourse_connect_overrides_card_background is not enabled' do
|
||||
|
||||
it "correctly handles provided card_background_urls" do
|
||||
sso = DiscourseSingleSignOn.new
|
||||
|
@ -787,7 +787,7 @@ describe DiscourseSingleSignOn do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when sso_overrides_card_background is enabled' do
|
||||
context 'when discourse_connect_overrides_card_background is enabled' do
|
||||
fab!(:sso_record) { Fabricate(:single_sign_on_record, external_card_background_url: "http://example.com/an_image.png") }
|
||||
|
||||
let!(:sso) {
|
||||
|
@ -802,7 +802,7 @@ describe DiscourseSingleSignOn do
|
|||
let(:logo) { file_from_fixtures("logo.png") }
|
||||
|
||||
before do
|
||||
SiteSetting.sso_overrides_card_background = true
|
||||
SiteSetting.discourse_connect_overrides_card_background = true
|
||||
end
|
||||
|
||||
it "deal with no card_background_url passed for an existing user with a card_background" do
|
||||
|
|
|
@ -57,7 +57,7 @@ describe Invite do
|
|||
|
||||
invite = Fabricate.build(:invite, email: "test@mail.com")
|
||||
expect(invite).not_to be_valid
|
||||
expect(invite.errors.details[:email].first[:error]).to eq(I18n.t("invite.disabled_errors.sso_enabled"))
|
||||
expect(invite.errors.details[:email].first[:error]).to eq(I18n.t("invite.disabled_errors.discourse_connect_enabled"))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -862,12 +862,12 @@ RSpec.describe Admin::UsersController do
|
|||
|
||||
before do
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.sso_overrides_name = true
|
||||
SiteSetting.sso_overrides_username = true
|
||||
SiteSetting.sso_secret = sso_secret
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
SiteSetting.auth_overrides_name = true
|
||||
SiteSetting.auth_overrides_username = true
|
||||
SiteSetting.discourse_connect_secret = sso_secret
|
||||
sso.sso_secret = sso_secret
|
||||
end
|
||||
|
||||
|
@ -924,7 +924,7 @@ RSpec.describe Admin::UsersController do
|
|||
correct_payload = Rack::Utils.parse_query(sso.payload)
|
||||
post "/admin/users/sync_sso.json", params: correct_payload.merge(sig: "someincorrectsignature")
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.parsed_body["message"]).to include(I18n.t('sso.login_error'))
|
||||
expect(response.parsed_body["message"]).to include(I18n.t('discourse_connect.login_error'))
|
||||
expect(response.parsed_body["message"]).not_to include(correct_payload["sig"])
|
||||
end
|
||||
|
||||
|
@ -935,7 +935,7 @@ RSpec.describe Admin::UsersController do
|
|||
sso.external_id = ""
|
||||
post "/admin/users/sync_sso.json", params: Rack::Utils.parse_query(sso.payload)
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.parsed_body["message"]).to include(I18n.t('sso.blank_id_error'))
|
||||
expect(response.parsed_body["message"]).to include(I18n.t('discourse_connect.blank_id_error'))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1094,8 +1094,8 @@ RSpec.describe Admin::UsersController do
|
|||
fab!(:sso_record) { SingleSignOnRecord.create!(user_id: user.id, external_id: '12345', external_email: user.email, last_payload: '') }
|
||||
|
||||
it "deletes the record" do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
delete "/admin/users/#{user.id}/sso_record.json"
|
||||
expect(response.status).to eq(200)
|
||||
|
|
|
@ -96,8 +96,8 @@ describe 'users' do
|
|||
let(:external_id) { '1' }
|
||||
|
||||
before do
|
||||
SiteSetting.sso_url = 'http://someurl.com'
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = 'http://someurl.com'
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
user.create_single_sign_on_record(external_id: '1', last_payload: '')
|
||||
end
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ RSpec.describe ApplicationController do
|
|||
end
|
||||
|
||||
it "should redirect to SSO if enabled" do
|
||||
SiteSetting.sso_url = 'http://someurl.com'
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = 'http://someurl.com'
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
get "/"
|
||||
expect(response).to redirect_to("/session/sso")
|
||||
end
|
||||
|
@ -45,17 +45,17 @@ RSpec.describe ApplicationController do
|
|||
expect(response).to redirect_to("/login")
|
||||
end
|
||||
|
||||
it "should not redirect to SSO when external_auth_immediately is disabled" do
|
||||
SiteSetting.external_auth_immediately = false
|
||||
SiteSetting.sso_url = 'http://someurl.com'
|
||||
SiteSetting.enable_sso = true
|
||||
it "should not redirect to SSO when auth_immediately is disabled" do
|
||||
SiteSetting.auth_immediately = false
|
||||
SiteSetting.discourse_connect_url = 'http://someurl.com'
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
get "/"
|
||||
expect(response).to redirect_to("/login")
|
||||
end
|
||||
|
||||
it "should not redirect to authenticator when external_auth_immediately is disabled" do
|
||||
SiteSetting.external_auth_immediately = false
|
||||
it "should not redirect to authenticator when auth_immediately is disabled" do
|
||||
SiteSetting.auth_immediately = false
|
||||
SiteSetting.enable_google_oauth2_logins = true
|
||||
SiteSetting.enable_local_logins = false
|
||||
|
||||
|
|
|
@ -444,8 +444,8 @@ describe InvitesController do
|
|||
|
||||
it "does not send password reset email if sso is enabled" do
|
||||
invite # create the invite before enabling SSO
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
put "/invites/show/#{invite.invite_key}.json"
|
||||
expect(response.status).to eq(200)
|
||||
|
||||
|
|
|
@ -351,9 +351,9 @@ RSpec.describe Users::OmniauthCallbacksController do
|
|||
|
||||
it "should update name/username/email when sso_overrides is enabled" do
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.sso_overrides_name = true
|
||||
SiteSetting.sso_overrides_username = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
SiteSetting.auth_overrides_name = true
|
||||
SiteSetting.auth_overrides_username = true
|
||||
|
||||
UserAssociatedAccount.create!(provider_name: "google_oauth2", user_id: user.id, provider_uid: '123545')
|
||||
|
||||
|
@ -371,7 +371,7 @@ RSpec.describe Users::OmniauthCallbacksController do
|
|||
|
||||
it "will not update email if not verified" do
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
|
||||
OmniAuth.config.mock_auth[:google_oauth2][:extra][:raw_info][:email_verified] = false
|
||||
|
||||
|
@ -387,9 +387,9 @@ RSpec.describe Users::OmniauthCallbacksController do
|
|||
expect(user.email).to eq('email@example.com')
|
||||
end
|
||||
|
||||
it "shows error when sso_overrides_email causes a validation error" do
|
||||
it "shows error when auth_overrides_email causes a validation error" do
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
|
||||
UserAssociatedAccount.create!(provider_name: "google_oauth2", user_id: user.id, provider_uid: '123545')
|
||||
|
||||
|
@ -454,12 +454,12 @@ RSpec.describe Users::OmniauthCallbacksController do
|
|||
|
||||
context 'when sso_payload cookie exist' do
|
||||
before do
|
||||
SiteSetting.enable_sso_provider = true
|
||||
SiteSetting.sso_secret = "topsecret"
|
||||
SiteSetting.enable_discourse_connect_provider = true
|
||||
SiteSetting.discourse_connect_secret = "topsecret"
|
||||
|
||||
@sso = SingleSignOn.new
|
||||
@sso.nonce = "mynonce"
|
||||
@sso.sso_secret = SiteSetting.sso_secret
|
||||
@sso.sso_secret = SiteSetting.discourse_connect_secret
|
||||
@sso.return_sso_url = "http://somewhere.over.rainbow/sso"
|
||||
cookies[:sso_payload] = @sso.payload
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@ RSpec.describe SessionController do
|
|||
|
||||
context "when SSO enabled" do
|
||||
before do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
end
|
||||
|
||||
it "only works for admins" do
|
||||
|
@ -508,9 +508,9 @@ RSpec.describe SessionController do
|
|||
@sso_url = "http://example.com/discourse_sso"
|
||||
@sso_secret = "shjkfdhsfkjh"
|
||||
|
||||
SiteSetting.sso_url = @sso_url
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.sso_secret = @sso_secret
|
||||
SiteSetting.discourse_connect_url = @sso_url
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.discourse_connect_secret = @sso_secret
|
||||
|
||||
Fabricate(:admin)
|
||||
end
|
||||
|
@ -577,7 +577,7 @@ RSpec.describe SessionController do
|
|||
|
||||
expect(messages.length).to eq(0)
|
||||
expect(response.status).to eq(500)
|
||||
expect(response.body).to include(I18n.t('sso.blank_id_error'))
|
||||
expect(response.body).to include(I18n.t('discourse_connect.blank_id_error'))
|
||||
end
|
||||
|
||||
it 'can handle invalid sso email validation errors' do
|
||||
|
@ -593,7 +593,7 @@ RSpec.describe SessionController do
|
|||
|
||||
expect(messages.length).to eq(0)
|
||||
expect(response.status).to eq(500)
|
||||
expect(response.body).to include(I18n.t("sso.email_error", email: ERB::Util.html_escape("test@test.com")))
|
||||
expect(response.body).to include(I18n.t("discourse_connect.email_error", email: ERB::Util.html_escape("test@test.com")))
|
||||
end
|
||||
|
||||
it 'can handle invalid sso external ids due to banned word' do
|
||||
|
@ -628,7 +628,7 @@ RSpec.describe SessionController do
|
|||
sign_out
|
||||
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
|
||||
group = Fabricate(:group, name: :bob, automatic_membership_email_domains: 'jane.com')
|
||||
sso = get_sso("/")
|
||||
|
@ -731,7 +731,7 @@ RSpec.describe SessionController do
|
|||
end
|
||||
|
||||
it 'redirects to random url if it is allowed' do
|
||||
SiteSetting.sso_allows_all_return_paths = true
|
||||
SiteSetting.discourse_connect_allows_all_return_paths = true
|
||||
|
||||
sso = get_sso('https://gusundtrout.com')
|
||||
sso.external_id = '666' # the number of the beast
|
||||
|
@ -879,8 +879,8 @@ RSpec.describe SessionController do
|
|||
|
||||
context "when sso provider is enabled" do
|
||||
before do
|
||||
SiteSetting.enable_sso_provider = true
|
||||
SiteSetting.sso_provider_secrets = [
|
||||
SiteSetting.enable_discourse_connect_provider = true
|
||||
SiteSetting.discourse_connect_provider_secrets = [
|
||||
"*|secret,forAll",
|
||||
"*.rainbow|wrongSecretForOverRainbow",
|
||||
"www.random.site|secretForRandomSite",
|
||||
|
@ -932,9 +932,9 @@ RSpec.describe SessionController do
|
|||
describe 'local attribute override from SSO payload' do
|
||||
before do
|
||||
SiteSetting.email_editable = false
|
||||
SiteSetting.sso_overrides_email = true
|
||||
SiteSetting.sso_overrides_username = true
|
||||
SiteSetting.sso_overrides_name = true
|
||||
SiteSetting.auth_overrides_email = true
|
||||
SiteSetting.auth_overrides_username = true
|
||||
SiteSetting.auth_overrides_name = true
|
||||
|
||||
@user = Fabricate(:user)
|
||||
|
||||
|
@ -994,10 +994,10 @@ RSpec.describe SessionController do
|
|||
body: lambda { |request| file_from_fixtures("logo.png") }
|
||||
)
|
||||
|
||||
SiteSetting.enable_sso_provider = true
|
||||
SiteSetting.enable_sso = false
|
||||
SiteSetting.enable_discourse_connect_provider = true
|
||||
SiteSetting.enable_discourse_connect = false
|
||||
SiteSetting.enable_local_logins = true
|
||||
SiteSetting.sso_provider_secrets = [
|
||||
SiteSetting.discourse_connect_provider_secrets = [
|
||||
"*|secret,forAll",
|
||||
"*.rainbow|wrongSecretForOverRainbow",
|
||||
"www.random.site|secretForRandomSite",
|
||||
|
@ -1062,17 +1062,17 @@ RSpec.describe SessionController do
|
|||
end
|
||||
|
||||
it "fails with a nice error message if secret is blank" do
|
||||
SiteSetting.sso_provider_secrets = ""
|
||||
SiteSetting.discourse_connect_provider_secrets = ""
|
||||
sso = SingleSignOnProvider.new
|
||||
sso.nonce = "mynonce"
|
||||
sso.return_sso_url = "http://website.without.secret.com/sso"
|
||||
get "/session/sso_provider", params: Rack::Utils.parse_query(sso.payload("aasdasdasd"))
|
||||
expect(response.status).to eq(400)
|
||||
expect(response.body).to eq(I18n.t("sso.missing_secret"))
|
||||
expect(response.body).to eq(I18n.t("discourse_connect.missing_secret"))
|
||||
end
|
||||
|
||||
it "returns a 422 if no return_sso_url" do
|
||||
SiteSetting.sso_provider_secrets = "abcdefghij"
|
||||
SiteSetting.discourse_connect_provider_secrets = "abcdefghij"
|
||||
sso = SingleSignOnProvider.new
|
||||
get "/session/sso_provider?sso=asdf&sig=abcdefghij"
|
||||
expect(response.status).to eq(422)
|
||||
|
@ -1206,8 +1206,8 @@ RSpec.describe SessionController do
|
|||
|
||||
context 'SSO is enabled' do
|
||||
before do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
post "/session.json", params: {
|
||||
login: user.username, password: 'myawesomepassword'
|
||||
|
@ -1810,8 +1810,8 @@ RSpec.describe SessionController do
|
|||
end
|
||||
|
||||
it 'redirects to /login when SSO and login_required' do
|
||||
SiteSetting.sso_url = "https://example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
user = sign_in(Fabricate(:user))
|
||||
delete "/session/#{user.username}.json", xhr: true
|
||||
|
@ -1987,8 +1987,8 @@ RSpec.describe SessionController do
|
|||
|
||||
context 'SSO is enabled' do
|
||||
before do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
post "/session.json", params: {
|
||||
login: user.username, password: 'myawesomepassword'
|
||||
|
|
|
@ -127,8 +127,8 @@ describe UploadsController do
|
|||
expect(response.status).to eq(422)
|
||||
end
|
||||
|
||||
it 'ensures sso_overrides_avatar is not enabled when uploading an avatar' do
|
||||
SiteSetting.sso_overrides_avatar = true
|
||||
it 'ensures discourse_connect_overrides_avatar is not enabled when uploading an avatar' do
|
||||
SiteSetting.discourse_connect_overrides_avatar = true
|
||||
post "/uploads.json", params: { file: logo, type: "avatar" }
|
||||
expect(response.status).to eq(422)
|
||||
end
|
||||
|
|
|
@ -1071,8 +1071,8 @@ describe UsersController do
|
|||
end
|
||||
|
||||
it "doesn't use provided username/name if sso_overrides is enabled" do
|
||||
SiteSetting.sso_overrides_username = true
|
||||
SiteSetting.sso_overrides_name = true
|
||||
SiteSetting.auth_overrides_username = true
|
||||
SiteSetting.auth_overrides_name = true
|
||||
post "/u.json", params: {
|
||||
username: "attemptednewname",
|
||||
name: "Attempt At New Name",
|
||||
|
@ -1463,17 +1463,17 @@ describe UsersController do
|
|||
expect(response.parsed_body['username']).to eq(new_username)
|
||||
end
|
||||
|
||||
it 'should respond with proper error message if sso_overrides_username is enabled' do
|
||||
SiteSetting.sso_url = 'http://someurl.com'
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.sso_overrides_username = true
|
||||
it 'should respond with proper error message if auth_overrides_username is enabled' do
|
||||
SiteSetting.discourse_connect_url = 'http://someurl.com'
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.auth_overrides_username = true
|
||||
acting_user = Fabricate(:admin)
|
||||
sign_in(acting_user)
|
||||
|
||||
put "/u/#{user.username}/preferences/username.json", params: { new_username: new_username }
|
||||
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.parsed_body['errors'].first).to include(I18n.t('errors.messages.sso_overrides_username'))
|
||||
expect(response.parsed_body['errors'].first).to include(I18n.t('errors.messages.auth_overrides_username'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -2343,8 +2343,8 @@ describe UsersController do
|
|||
expect(response).to be_forbidden
|
||||
end
|
||||
|
||||
it "raises an error when sso_overrides_avatar is disabled" do
|
||||
SiteSetting.sso_overrides_avatar = true
|
||||
it "raises an error when discourse_connect_overrides_avatar is disabled" do
|
||||
SiteSetting.discourse_connect_overrides_avatar = true
|
||||
put "/u/#{user.username}/preferences/avatar/pick.json", params: {
|
||||
upload_id: upload.id, type: "custom"
|
||||
}
|
||||
|
@ -3972,8 +3972,8 @@ describe UsersController do
|
|||
|
||||
describe 'when SSO is enabled' do
|
||||
it 'should return the right response' do
|
||||
SiteSetting.sso_url = 'http://someurl.com'
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = 'http://someurl.com'
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
post "/users/create_second_factor_totp.json"
|
||||
|
||||
|
@ -4204,8 +4204,8 @@ describe UsersController do
|
|||
|
||||
describe 'when SSO is enabled' do
|
||||
it 'should return the right response' do
|
||||
SiteSetting.sso_url = 'http://someurl.com'
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = 'http://someurl.com'
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
|
||||
put "/users/second_factors_backup.json"
|
||||
|
||||
|
@ -4479,8 +4479,8 @@ describe UsersController do
|
|||
|
||||
context 'when SSO is enabled' do
|
||||
before do
|
||||
SiteSetting.sso_url = 'https://discourse.test/sso'
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = 'https://discourse.test/sso'
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
end
|
||||
|
||||
it 'does not allow access' do
|
||||
|
@ -4503,7 +4503,7 @@ describe UsersController do
|
|||
context 'when the site settings allow second factors' do
|
||||
before do
|
||||
SiteSetting.enable_local_logins = true
|
||||
SiteSetting.enable_sso = false
|
||||
SiteSetting.enable_discourse_connect = false
|
||||
end
|
||||
|
||||
context 'when the password parameter is not provided' do
|
||||
|
|
|
@ -27,9 +27,9 @@ RSpec.describe CurrentUserSerializer do
|
|||
end
|
||||
|
||||
it "should include the external_id" do
|
||||
SiteSetting.sso_url = "http://example.com/discourse_sso"
|
||||
SiteSetting.sso_secret = "12345678910"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "http://example.com/discourse_sso"
|
||||
SiteSetting.discourse_connect_secret = "12345678910"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
payload = serializer.as_json
|
||||
expect(payload[:external_id]).to eq("12345")
|
||||
end
|
||||
|
|
|
@ -29,9 +29,9 @@ describe NotificationSerializer do
|
|||
let(:json) { serializer.as_json }
|
||||
|
||||
it "should include the external_id" do
|
||||
SiteSetting.sso_url = "http://example.com/discourse_sso"
|
||||
SiteSetting.sso_secret = "12345678910"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = "http://example.com/discourse_sso"
|
||||
SiteSetting.discourse_connect_secret = "12345678910"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
expect(json[:notification][:external_id]).to eq("12345")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,13 +11,13 @@ describe SiteSettingsTask do
|
|||
describe 'export' do
|
||||
it 'creates a hash of all site settings' do
|
||||
sso_url = "https://somewhere.over.com"
|
||||
SiteSetting.sso_url = sso_url
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.discourse_connect_url = sso_url
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
hash = SiteSettingsTask.export_to_hash
|
||||
|
||||
expect(hash).to eq(
|
||||
"enable_sso" => "true",
|
||||
"sso_url" => sso_url
|
||||
"enable_discourse_connect" => "true",
|
||||
"discourse_connect_url" => sso_url
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -267,9 +267,9 @@ describe UserUpdater do
|
|||
|
||||
context 'when sso overrides bio' do
|
||||
it 'does not change bio' do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.sso_overrides_bio = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.discourse_connect_overrides_bio = true
|
||||
|
||||
user = Fabricate(:user)
|
||||
updater = UserUpdater.new(acting_user, user)
|
||||
|
@ -283,9 +283,9 @@ describe UserUpdater do
|
|||
|
||||
context 'when sso overrides location' do
|
||||
it 'does not change location' do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.sso_overrides_location = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.discourse_connect_overrides_location = true
|
||||
|
||||
user = Fabricate(:user)
|
||||
updater = UserUpdater.new(acting_user, user)
|
||||
|
@ -299,9 +299,9 @@ describe UserUpdater do
|
|||
|
||||
context 'when sso overrides website' do
|
||||
it 'does not change website' do
|
||||
SiteSetting.sso_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_sso = true
|
||||
SiteSetting.sso_overrides_website = true
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.discourse_connect_overrides_website = true
|
||||
|
||||
user = Fabricate(:user)
|
||||
updater = UserUpdater.new(acting_user, user)
|
||||
|
|
Loading…
Reference in New Issue