diff --git a/app/assets/javascripts/discourse/app/templates/preferences/interface.hbs b/app/assets/javascripts/discourse/app/templates/preferences/interface.hbs index e53cd172c2c..d51e6de26fc 100644 --- a/app/assets/javascripts/discourse/app/templates/preferences/interface.hbs +++ b/app/assets/javascripts/discourse/app/templates/preferences/interface.hbs @@ -135,7 +135,9 @@ {{#if siteSettings.automatically_unpin_topics}} {{preference-checkbox labelKey="user.automatically_unpin_topics" checked=model.user_option.automatically_unpin_topics class="pref-auto-unpin"}} {{/if}} - {{preference-checkbox labelKey="user.hide_profile_and_presence" checked=model.user_option.hide_profile_and_presence class="pref-hide-profile"}} + {{#if siteSettings.allow_users_to_hide_profile}} + {{preference-checkbox labelKey="user.hide_profile_and_presence" checked=model.user_option.hide_profile_and_presence class="pref-hide-profile"}} + {{/if}} {{#if isiPad}} {{preference-checkbox labelKey="user.enable_physical_keyboard" checked=disableSafariHacks class="pref-safari-hacks"}} {{/if}} diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 1cbf744a1bb..d885ac331ee 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -2029,6 +2029,7 @@ en: anonymous_account_duration_minutes: "To protect anonymity create a new anonymous account every N minutes for each user. Example: if set to 600, as soon as 600 minutes elapse from last post AND user switches to anon, a new anonymous account is created." hide_user_profiles_from_public: "Disable user cards, user profiles and user directory for anonymous users." + allow_users_to_hide_profile: "Allow users to hide their profile and presence" allow_featured_topic_on_user_profiles: "Allow users to feature a link to a topic on their user card and profile." diff --git a/config/site_settings.yml b/config/site_settings.yml index d78463c1254..f15a0577f90 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -601,6 +601,9 @@ users: anonymous_account_duration_minutes: default: 10080 max: 99000 + allow_users_to_hide_profile: + default: true + client: true hide_user_profiles_from_public: default: false client: true diff --git a/lib/guardian/user_guardian.rb b/lib/guardian/user_guardian.rb index 6e2ccdb03cd..a133e82f188 100644 --- a/lib/guardian/user_guardian.rb +++ b/lib/guardian/user_guardian.rb @@ -111,6 +111,7 @@ module UserGuardian def can_see_profile?(user) return false if user.blank? + return true if !SiteSetting.allow_users_to_hide_profile? # If a user has hidden their profile, restrict it to them and staff if user.user_option.try(:hide_profile_and_presence?) diff --git a/plugins/discourse-presence/assets/javascripts/discourse/lib/presence.js.es6 b/plugins/discourse-presence/assets/javascripts/discourse/lib/presence.js.es6 index da8b7ef97c5..aa070d68aba 100644 --- a/plugins/discourse-presence/assets/javascripts/discourse/lib/presence.js.es6 +++ b/plugins/discourse-presence/assets/javascripts/discourse/lib/presence.js.es6 @@ -102,7 +102,18 @@ const Presence = EmberObject.extend({ }, publish(state, whisper, postId, staffOnly) { - if (this.get("currentUser.hide_profile_and_presence")) { + // NOTE: `user_option` is the correct place to get this value from, but + // it may not have been set yet. It will always have been set directly + // on the currentUser, via the preloaded_json payload. + // TODO: Remove this when preloaded_json is refactored. + let hiddenProfile = this.get( + "currentUser.user_option.hide_profile_and_presence" + ); + if (hiddenProfile === undefined) { + hiddenProfile = this.get("currentUser.hide_profile_and_presence"); + } + + if (hiddenProfile && this.get("siteSettings.allow_users_to_hide_profile")) { return; } diff --git a/plugins/discourse-presence/plugin.rb b/plugins/discourse-presence/plugin.rb index de6a3e0fd9b..34eb3429860 100644 --- a/plugins/discourse-presence/plugin.rb +++ b/plugins/discourse-presence/plugin.rb @@ -155,7 +155,8 @@ after_initialize do def ensure_presence_enabled if !SiteSetting.presence_enabled || - current_user.user_option.hide_profile_and_presence? + (SiteSetting.allow_users_to_hide_profile && + current_user.user_option.hide_profile_and_presence?) raise Discourse::NotFound end diff --git a/plugins/discourse-presence/spec/requests/presence_controller_spec.rb b/plugins/discourse-presence/spec/requests/presence_controller_spec.rb index b18d731b9b8..8df3086aef8 100644 --- a/plugins/discourse-presence/spec/requests/presence_controller_spec.rb +++ b/plugins/discourse-presence/spec/requests/presence_controller_spec.rb @@ -45,6 +45,15 @@ describe ::Presence::PresencesController do expect(response.status).to eq(404) end + it 'returns the right response when user disables the presence feature and allow_users_to_hide_profile is disabled' do + user.user_option.update_column(:hide_profile_and_presence, true) + SiteSetting.allow_users_to_hide_profile = false + + post '/presence/publish.json', params: { topic_id: public_topic.id, state: 'replying' } + + expect(response.status).to eq(200) + end + it 'returns the right response when the presence site settings is disabled' do SiteSetting.presence_enabled = false diff --git a/spec/components/guardian/user_guardian_spec.rb b/spec/components/guardian/user_guardian_spec.rb index 04c34a18b0f..fc516cf70d6 100644 --- a/spec/components/guardian/user_guardian_spec.rb +++ b/spec/components/guardian/user_guardian_spec.rb @@ -143,6 +143,10 @@ describe UserGuardian do expect(Guardian.new(admin).can_see_profile?(hidden_user)).to eq(true) end + it "is true if hiding profiles is disabled" do + SiteSetting.allow_users_to_hide_profile = false + expect(Guardian.new(user).can_see_profile?(hidden_user)).to eq(true) + end end end diff --git a/spec/requests/list_controller_spec.rb b/spec/requests/list_controller_spec.rb index 954765e46fc..a7db647bd87 100644 --- a/spec/requests/list_controller_spec.rb +++ b/spec/requests/list_controller_spec.rb @@ -603,10 +603,23 @@ RSpec.describe ListController do expect(json["topic_list"]["topics"].size).to eq(2) end - it "returns 404 if `hide_profile_and_presence` user option is checked" do - user.user_option.update_columns(hide_profile_and_presence: true) - get "/topics/created-by/#{user.username}.json" - expect(response.status).to eq(404) + context 'when `hide_profile_and_presence` is true' do + before do + user.user_option.update_columns(hide_profile_and_presence: true) + end + + it "returns 404" do + get "/topics/created-by/#{user.username}.json" + expect(response.status).to eq(404) + end + + it "should respond with a list when `allow_users_to_hide_profile` is false" do + SiteSetting.allow_users_to_hide_profile = false + get "/topics/created-by/#{user.username}.json" + expect(response.status).to eq(200) + json = response.parsed_body + expect(json["topic_list"]["topics"].size).to eq(2) + end end end diff --git a/spec/requests/posts_controller_spec.rb b/spec/requests/posts_controller_spec.rb index 486fa21498d..20b2488343d 100644 --- a/spec/requests/posts_controller_spec.rb +++ b/spec/requests/posts_controller_spec.rb @@ -1752,6 +1752,17 @@ describe PostsController do get "/u/#{user.username}/activity.json" expect(response.status).to eq(404) end + + it "succeeds when `allow_users_to_hide_profile` is false" do + user.user_option.update_columns(hide_profile_and_presence: true) + SiteSetting.allow_users_to_hide_profile = false + + get "/u/#{user.username}/activity.rss" + expect(response.status).to eq(200) + + get "/u/#{user.username}/activity.json" + expect(response.status).to eq(200) + end end describe '#latest' do diff --git a/spec/requests/user_actions_controller_spec.rb b/spec/requests/user_actions_controller_spec.rb index d0d04ad660f..a12af23d6a8 100644 --- a/spec/requests/user_actions_controller_spec.rb +++ b/spec/requests/user_actions_controller_spec.rb @@ -10,15 +10,6 @@ describe UserActionsController do expect(response.status).to eq(400) end - it "returns a 404 for a user with a hidden profile" do - UserActionManager.enable - post = Fabricate(:post) - post.user.user_option.update_column(:hide_profile_and_presence, true) - - get "/user_actions.json", params: { username: post.user.username } - expect(response.code).to eq("404") - end - it 'renders list correctly' do UserActionManager.enable post = create_post @@ -88,5 +79,25 @@ describe UserActionsController do expect(parsed["no_results_help"]).to eq(I18n.t("user_activity.no_bookmarks.others")) end + context 'hidden profiles' do + fab!(:post) { Fabricate(:post) } + + before do + UserActionManager.enable + post.user.user_option.update_column(:hide_profile_and_presence, true) + end + + it "returns a 404" do + get "/user_actions.json", params: { username: post.user.username } + expect(response.code).to eq("404") + end + + it "succeeds when `allow_users_to_hide_profile` is false" do + SiteSetting.allow_users_to_hide_profile = false + get "/user_actions.json", params: { username: post.user.username } + expect(response.code).to eq("200") + end + end + end end diff --git a/spec/requests/user_badges_controller_spec.rb b/spec/requests/user_badges_controller_spec.rb index 0adf411f1a4..14c47d68b87 100644 --- a/spec/requests/user_badges_controller_spec.rb +++ b/spec/requests/user_badges_controller_spec.rb @@ -44,13 +44,6 @@ describe UserBadgesController do expect(parsed["user_badges"].length).to eq(1) end - it "returns 404 if `hide_profile_and_presence` user option is checked" do - user.user_option.update_columns(hide_profile_and_presence: true) - - get "/user-badges/#{user.username}.json" - expect(response.status).to eq(404) - end - it 'returns user_badges for a user with period in username' do user.update!(username: "myname.test") get "/user-badges/#{user.username}", xhr: true @@ -77,6 +70,24 @@ describe UserBadgesController do parsed = response.parsed_body expect(parsed["user_badges"].first.has_key?('count')).to eq(true) end + + context 'hidden profiles' do + before do + user.user_option.update_columns(hide_profile_and_presence: true) + end + + it "returns 404 if `hide_profile_and_presence` user option is checked" do + get "/user-badges/#{user.username}.json" + expect(response.status).to eq(404) + end + + it "returns user_badges if `allow_users_to_hide_profile` is false" do + SiteSetting.allow_users_to_hide_profile = false + + get "/user-badges/#{user.username}.json" + expect(response.status).to eq(200) + end + end end context 'create' do diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb index 1358355dd86..2909b35fda9 100644 --- a/spec/requests/users_controller_spec.rb +++ b/spec/requests/users_controller_spec.rb @@ -2868,12 +2868,24 @@ describe UsersController do expect(json["user_summary"]["post_count"]).to eq(0) end - it "returns 404 for a hidden profile" do - user = Fabricate(:user) - user.user_option.update_column(:hide_profile_and_presence, true) + context '`hide_profile_and_presence` user option is checked' do + fab!(:user) { Fabricate(:user) } - get "/u/#{user.username_lower}/summary.json" - expect(response.status).to eq(404) + before do + user.user_option.update_columns(hide_profile_and_presence: true) + end + + it "returns 404" do + get "/u/#{user.username_lower}/summary.json" + expect(response.status).to eq(404) + end + + it "returns summary info if `allow_users_to_hide_profile` is false" do + SiteSetting.allow_users_to_hide_profile = false + + get "/u/#{user.username_lower}/summary.json" + expect(response.status).to eq(200) + end end end @@ -3353,13 +3365,28 @@ describe UsersController do expect(response).to redirect_to '/login' end - it "does not include hidden profiles" do - user2.user_option.update(hide_profile_and_presence: true) - get "/user-cards.json?user_ids=#{user.id},#{user2.id}" - expect(response.status).to eq(200) - parsed = response.parsed_body["users"] + context '`hide_profile_and_presence` user option is checked' do + before do + user2.user_option.update_columns(hide_profile_and_presence: true) + end - expect(parsed.map { |u| u["username"] }).to contain_exactly(user.username) + it "does not include hidden profiles" do + get "/user-cards.json?user_ids=#{user.id},#{user2.id}" + expect(response.status).to eq(200) + parsed = response.parsed_body["users"] + + expect(parsed.map { |u| u["username"] }).to contain_exactly(user.username) + end + + it "does include hidden profiles when `allow_users_to_hide_profile` is false" do + SiteSetting.allow_users_to_hide_profile = false + + get "/user-cards.json?user_ids=#{user.id},#{user2.id}" + expect(response.status).to eq(200) + parsed = response.parsed_body["users"] + + expect(parsed.map { |u| u["username"] }).to contain_exactly(user.username, user2.username) + end end end