diff --git a/app/controllers/settings/privacy_controller.rb b/app/controllers/settings/privacy_controller.rb index 55d553e8..6deea58a 100644 --- a/app/controllers/settings/privacy_controller.rb +++ b/app/controllers/settings/privacy_controller.rb @@ -11,7 +11,8 @@ class Settings::PrivacyController < ApplicationController :privacy_allow_public_timeline, :privacy_allow_stranger_answers, :privacy_show_in_search, - :privacy_require_user) + :privacy_require_user, + :privacy_hide_social_graph) if current_user.update(user_attributes) flash[:success] = t(".success") else diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 119bd17a..f71e41dc 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -1,6 +1,10 @@ +# frozen_string_literal: true + class UserController < ApplicationController + before_action :set_user + before_action :hidden_social_graph_redirect, only: %i[followers followings] + def show - @user = User.where('LOWER(screen_name) = ?', params[:username].downcase).includes(:profile).first! @answers = @user.cursored_answers(last_id: params[:last_id]) @answers_last_id = @answers.map(&:id).min @more_data_available = !@user.cursored_answers(last_id: @answers_last_id, size: 1).count.zero? @@ -20,8 +24,7 @@ class UserController < ApplicationController end def followers - @title = 'Followers' - @user = User.where('LOWER(screen_name) = ?', params[:username].downcase).includes(:profile).first! + @title = "Followers" @relationships = @user.cursored_follower_relationships(last_id: params[:last_id]) @relationships_last_id = @relationships.map(&:id).min @more_data_available = !@user.cursored_follower_relationships(last_id: @relationships_last_id, size: 1).count.zero? @@ -34,10 +37,8 @@ class UserController < ApplicationController end end - # rubocop:disable Metrics/AbcSize def followings - @title = 'Following' - @user = User.where('LOWER(screen_name) = ?', params[:username].downcase).includes(:profile).first! + @title = "Following" @relationships = @user.cursored_following_relationships(last_id: params[:last_id]) @relationships_last_id = @relationships.map(&:id).min @more_data_available = !@user.cursored_following_relationships(last_id: @relationships_last_id, size: 1).count.zero? @@ -49,11 +50,9 @@ class UserController < ApplicationController format.turbo_stream { render "show_follow" } end end - # rubocop:enable Metrics/AbcSize def questions - @title = 'Questions' - @user = User.where('LOWER(screen_name) = ?', params[:username].downcase).includes(:profile).first! + @title = "Questions" @questions = @user.cursored_questions(author_is_anonymous: false, direct: belongs_to_current_user? || moderation_view?, last_id: params[:last_id]) @questions_last_id = @questions.map(&:id).min @more_data_available = !@user.cursored_questions(author_is_anonymous: false, direct: belongs_to_current_user? || moderation_view?, last_id: @questions_last_id, size: 1).count.zero? @@ -66,5 +65,15 @@ class UserController < ApplicationController private + def set_user + @user = User.where("LOWER(screen_name) = ?", params[:username].downcase).includes(:profile).first! + end + + def hidden_social_graph_redirect + return if belongs_to_current_user? || !@user.privacy_hide_social_graph + + redirect_to user_path(@user) + end + def belongs_to_current_user? = @user == current_user end diff --git a/app/views/settings/privacy/edit.html.haml b/app/views/settings/privacy/edit.html.haml index a0f25626..f320c928 100644 --- a/app/views/settings/privacy/edit.html.haml +++ b/app/views/settings/privacy/edit.html.haml @@ -6,6 +6,7 @@ = f.check_box :privacy_require_user = f.check_box :privacy_allow_public_timeline = f.check_box :privacy_allow_stranger_answers + = f.check_box :privacy_hide_social_graph = f.primary diff --git a/app/views/tabs/_profile.html.haml b/app/views/tabs/_profile.html.haml index ee490edd..06ceceac 100644 --- a/app/views/tabs/_profile.html.haml +++ b/app/views/tabs/_profile.html.haml @@ -2,5 +2,6 @@ .list-group.list-group-horizontal-sm.text-center = list_group_item t(".answers"), user_path(user), badge: user.answered_count = list_group_item t(".questions"), show_user_questions_path(user.screen_name), badge: user.asked_count - = list_group_item t(".followers"), show_user_followers_path(user.screen_name), badge: user.followers.count - = list_group_item t(".following"), show_user_followings_path(user.screen_name), badge: user.followings.count + - if user == current_user || !user.privacy_hide_social_graph + = list_group_item t(".followers"), show_user_followers_path(user.screen_name), badge: user.followers.count + = list_group_item t(".following"), show_user_followings_path(user.screen_name), badge: user.followings.count diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index 956a3d5e..2d619968 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -72,6 +72,7 @@ en: privacy_require_user: "Require users to be logged in to ask you questions" privacy_allow_public_timeline: "Show your answers in the public timeline" privacy_allow_stranger_answers: "Allow other people to answer your questions" + privacy_hide_social_graph: "Hide your social graph from others" profile_picture: "Profile picture" profile_header: "Profile header" sign_in_count: "Sign in count" diff --git a/db/migrate/20221115194933_add_privacy_hide_social_graph.rb b/db/migrate/20221115194933_add_privacy_hide_social_graph.rb new file mode 100644 index 00000000..8685dafb --- /dev/null +++ b/db/migrate/20221115194933_add_privacy_hide_social_graph.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddPrivacyHideSocialGraph < ActiveRecord::Migration[6.1] + def up + add_column :users, :privacy_hide_social_graph, :boolean, default: false + end + + def down + remove_column :users, :privacy_hide_social_graph + end +end diff --git a/db/schema.rb b/db/schema.rb index 1ba38cf6..907abcfd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_11_14_214508) do +ActiveRecord::Schema.define(version: 2022_11_15_194933) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" diff --git a/spec/controllers/user_controller_spec.rb b/spec/controllers/user_controller_spec.rb index 11599f0a..b66b50b8 100644 --- a/spec/controllers/user_controller_spec.rb +++ b/spec/controllers/user_controller_spec.rb @@ -9,6 +9,32 @@ describe UserController, type: :controller do otp_secret_key: "EJFNIJPYXXTCQSRTQY6AG7XQLAT2IDG5H7NGLJE3" end + shared_examples_for "social graph hidden" do + context "user has social graph hidden" do + before(:each) do + user.update(privacy_hide_social_graph: true) + end + + it "shows the followers template to the current user" do + sign_in user + subject + expect(assigns(:user)).to eq(user) + expect(response).to render_template("user/show_follow") + end + + it "redirects to the user profile page if not logged in" do + subject + expect(response).to redirect_to(user_path(user)) + end + + it "redirects to the user profile page if logged in as a different user" do + sign_in FactoryBot.create(:user) + subject + expect(response).to redirect_to(user_path(user)) + end + end + end + describe "#show" do subject { get :show, params: { username: user.screen_name } } @@ -35,6 +61,8 @@ describe UserController, type: :controller do expect(response).to render_template("user/show_follow") end end + + include_examples "social graph hidden" end describe "#followings" do @@ -49,6 +77,8 @@ describe UserController, type: :controller do expect(response).to render_template("user/show_follow") end end + + include_examples "social graph hidden" end describe "#questions" do diff --git a/yarn.lock b/yarn.lock index c2e25844..1f13d71d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4784,9 +4784,9 @@ loader-runner@^2.4.0: integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.1.tgz#278ad7006660bccc4d2c0c1578e17c5c78d5c0e0" - integrity sha512-1Qo97Y2oKaU+Ro2xnDMR26g1BwMT29jNbem1EvcujW2jqt+j5COXyscjM7bLQkM9HaxI7pkWeW7gnI072yMI9Q== + version "1.4.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" + integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== dependencies: big.js "^5.2.2" emojis-list "^3.0.0"