diff --git a/app/assets/javascripts/discourse/controllers/preferences.js.es6 b/app/assets/javascripts/discourse/controllers/preferences.js.es6 index c16c62492..98e0b05f7 100644 --- a/app/assets/javascripts/discourse/controllers/preferences.js.es6 +++ b/app/assets/javascripts/discourse/controllers/preferences.js.es6 @@ -48,6 +48,12 @@ export default Ember.Controller.extend(CanCheckEmails, { return this.siteSettings.enable_badges && hasTitleBadges; }, + @computed("model.can_change_bio") + canChangeBio(canChangeBio) + { + return canChangeBio; + }, + @computed() canChangePassword() { return !this.siteSettings.enable_sso && this.siteSettings.enable_local_logins; diff --git a/app/assets/javascripts/discourse/templates/user/preferences.hbs b/app/assets/javascripts/discourse/templates/user/preferences.hbs index 75c3bc10f..660f74c50 100644 --- a/app/assets/javascripts/discourse/templates/user/preferences.hbs +++ b/app/assets/javascripts/discourse/templates/user/preferences.hbs @@ -130,12 +130,14 @@ {{/if}} + {{#if canChangeBio}}
{{d-editor value=model.bio_raw}}
+ {{/if}} {{#each userFields as |uf|}} {{user-field field=uf.field value=uf.value}} diff --git a/app/models/discourse_single_sign_on.rb b/app/models/discourse_single_sign_on.rb index 2eef92afe..8de332750 100644 --- a/app/models/discourse_single_sign_on.rb +++ b/app/models/discourse_single_sign_on.rb @@ -82,6 +82,11 @@ class DiscourseSingleSignOn < SingleSignOn # optionally save the user and sso_record if they have changed user.save! + if bio && (user.user_profile.bio_raw.blank? || SiteSetting.sso_overrides_bio) + user.user_profile.bio_raw = bio + user.user_profile.save! + end + unless admin.nil? && moderator.nil? Group.refresh_automatic_groups!(:admins, :moderators, :staff) end diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb index b9be71f4d..673266f58 100644 --- a/app/serializers/user_serializer.rb +++ b/app/serializers/user_serializer.rb @@ -101,7 +101,8 @@ class UserSerializer < BasicUserSerializer :card_image_badge, :card_image_badge_id, :muted_usernames, - :mailing_list_posts_per_day + :mailing_list_posts_per_day, + :can_change_bio untrusted_attributes :bio_raw, :bio_cooked, @@ -132,6 +133,10 @@ class UserSerializer < BasicUserSerializer object.id && object.id == scope.user.try(:id) end + def can_change_bio + !(SiteSetting.enable_sso && SiteSetting.sso_overrides_bio) + end + def card_badge object.user_profile.card_image_badge end diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb index 859526012..ad25b23fa 100644 --- a/app/services/user_updater.rb +++ b/app/services/user_updater.rb @@ -45,7 +45,9 @@ class UserUpdater user_profile.location = attributes.fetch(:location) { user_profile.location } user_profile.dismissed_banner_key = attributes[:dismissed_banner_key] if attributes[:dismissed_banner_key].present? user_profile.website = format_url(attributes.fetch(:website) { user_profile.website }) - user_profile.bio_raw = attributes.fetch(:bio_raw) { user_profile.bio_raw } + unless SiteSetting.enable_sso && SiteSetting.sso_overrides_bio + user_profile.bio_raw = attributes.fetch(:bio_raw) { user_profile.bio_raw } + end user_profile.profile_background = attributes.fetch(:profile_background) { user_profile.profile_background } user_profile.card_background = attributes.fetch(:card_background) { user_profile.card_background } diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index ef9de6281..01ad1d329 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -977,6 +977,7 @@ en: enable_sso_provider: "Implement Discourse SSO provider protocol at the /session/sso_provider endpoint, requires sso_secret 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_overrides_bio: "Overrides user bio in user profile and prevents user from changing it" sso_overrides_email: "Overrides local email with external site email from SSO payload on every login, and prevent local changes. (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. (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." diff --git a/config/site_settings.yml b/config/site_settings.yml index c18801713..36eaf7c47 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -288,6 +288,7 @@ login: default: '' regex: '^https?:\/\/.+[^\/]$' sso_secret: '' + sso_overrides_bio: false sso_overrides_email: false sso_overrides_username: false sso_overrides_name: false diff --git a/lib/single_sign_on.rb b/lib/single_sign_on.rb index 525d02932..64d4e909a 100644 --- a/lib/single_sign_on.rb +++ b/lib/single_sign_on.rb @@ -1,6 +1,6 @@ class SingleSignOn ACCESSORS = [:nonce, :name, :username, :email, :avatar_url, :avatar_force_update, :require_activation, - :about_me, :external_id, :return_sso_url, :admin, :moderator, :suppress_welcome_message] + :bio, :external_id, :return_sso_url, :admin, :moderator, :suppress_welcome_message] FIXNUMS = [] BOOLS = [:avatar_force_update, :admin, :moderator, :require_activation, :suppress_welcome_message] NONCE_EXPIRY_TIME = 10.minutes diff --git a/spec/models/discourse_single_sign_on_spec.rb b/spec/models/discourse_single_sign_on_spec.rb index e70b7ce4e..2e4c61967 100644 --- a/spec/models/discourse_single_sign_on_spec.rb +++ b/spec/models/discourse_single_sign_on_spec.rb @@ -222,6 +222,47 @@ describe DiscourseSingleSignOn do end end + context 'setting bio for a user' do + let(:sso) { + sso = DiscourseSingleSignOn.new + sso.username = "test" + sso.name = "test" + sso.email = "test@test.com" + sso.external_id = "100" + sso.bio = "This **is** the bio" + sso + } + + it 'can set bio if supplied on new users or users with empty bio' do + # new account + user = sso.lookup_or_create_user(ip_address) + expect(user.user_profile.bio_cooked).to match_html("

This is the bio

") + + + # no override by default + sso.bio = "new profile" + user = sso.lookup_or_create_user(ip_address) + + expect(user.user_profile.bio_cooked).to match_html("

This is the bio

") + + # yes override for blank + user.user_profile.bio_raw = " " + user.user_profile.save! + + user = sso.lookup_or_create_user(ip_address) + expect(user.user_profile.bio_cooked).to match_html("

new profile

") + + + # yes override if site setting + sso.bio = "new profile 2" + SiteSetting.sso_overrides_bio = true + + user = sso.lookup_or_create_user(ip_address) + expect(user.user_profile.bio_cooked).to match_html("

new profile 2

") + end + + end + context 'when sso_overrides_avatar is enabled' do let!(:sso_record) { Fabricate(:single_sign_on_record, external_avatar_url: "http://example.com/an_image.png") } let!(:sso) { diff --git a/spec/services/user_updater_spec.rb b/spec/services/user_updater_spec.rb index 8cfeb9ec8..7a7de4234 100644 --- a/spec/services/user_updater_spec.rb +++ b/spec/services/user_updater_spec.rb @@ -65,7 +65,7 @@ describe UserUpdater do user = Fabricate(:user) updater = UserUpdater.new(acting_user, user) - updater.update(bio_raw: 'my new bio', + val = updater.update(bio_raw: 'my new bio', email_always: 'true', mailing_list_mode: true, digest_after_minutes: "45", @@ -73,6 +73,8 @@ describe UserUpdater do auto_track_topics_after_msecs: 101, email_in_reply_to: false ) + expect(val).to be_truthy + user.reload expect(user.user_profile.bio_raw).to eq 'my new bio' @@ -84,12 +86,18 @@ describe UserUpdater do expect(user.user_option.email_in_reply_to).to eq false end - context 'when update succeeds' do - it 'returns true' do + context 'when sso overrides bio' do + it 'does not change bio' do + SiteSetting.enable_sso = true + SiteSetting.sso_overrides_bio = true + user = Fabricate(:user) updater = UserUpdater.new(acting_user, user) - expect(updater.update).to be_truthy + expect(updater.update(bio_raw: "new bio")).to be_truthy + + user.reload + expect(user.user_profile.bio_raw).not_to eq 'new bio' end end