diff --git a/app/controllers/settings/privacy_controller.rb b/app/controllers/settings/privacy_controller.rb index 7921ef08..55d553e8 100644 --- a/app/controllers/settings/privacy_controller.rb +++ b/app/controllers/settings/privacy_controller.rb @@ -10,7 +10,8 @@ class Settings::PrivacyController < ApplicationController :privacy_allow_anonymous_questions, :privacy_allow_public_timeline, :privacy_allow_stranger_answers, - :privacy_show_in_search) + :privacy_show_in_search, + :privacy_require_user) if current_user.update(user_attributes) flash[:success] = t(".success") else diff --git a/app/views/application/_questionbox.html.haml b/app/views/application/_questionbox.html.haml index 1bb6d725..ec5d3560 100644 --- a/app/views/application/_questionbox.html.haml +++ b/app/views/application/_questionbox.html.haml @@ -17,6 +17,9 @@ - elsif user.inbox_locked? .text-center %strong= t(".status.locked") + - elsif !user_signed_in? && user.privacy_require_user? + .text-center + %strong= t(".status.require_user_html", sign_in: link_to(t("voc.login"), new_user_session_path), sign_up: link_to(t("voc.register"), new_user_registration_path)) - else - if user_signed_in? || user.privacy_allow_anonymous_questions? #question-box{ data: { controller: "character-count", "character-count-max-value": 512 }} @@ -54,4 +57,5 @@ .col-xs-12.col-sm-10.offset-sm-1.text-center %small= t(".promote.join", app_title: APP_CONFIG["site_name"]) - else - %p= raw t(".required", signup: link_to(t("voc.register"), new_user_registration_path)) + .text-center + %strong= t(".status.non_anonymous_html", sign_in: link_to(t("voc.login"), new_user_session_path), sign_up: link_to(t("voc.register"), new_user_registration_path)) diff --git a/app/views/settings/privacy/edit.html.haml b/app/views/settings/privacy/edit.html.haml index 55465898..a0f25626 100644 --- a/app/views/settings/privacy/edit.html.haml +++ b/app/views/settings/privacy/edit.html.haml @@ -3,6 +3,7 @@ = bootstrap_form_for(current_user, url: settings_privacy_path, method: :patch, data: { turbo: false }) do |f| = f.check_box :privacy_lock_inbox = f.check_box :privacy_allow_anonymous_questions + = f.check_box :privacy_require_user = f.check_box :privacy_allow_public_timeline = f.check_box :privacy_allow_stranger_answers diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index 9863908f..956a3d5e 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -69,6 +69,7 @@ en: password_confirmation: "Confirm your password" privacy_lock_inbox: "Lock inbox and don't allow new questions" privacy_allow_anonymous_questions: "Allow anonymous questions" + 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" profile_picture: "Profile picture" diff --git a/config/locales/errors.en.yml b/config/locales/errors.en.yml index d5e1ff32..82516fff 100644 --- a/config/locales/errors.en.yml +++ b/config/locales/errors.en.yml @@ -34,3 +34,5 @@ en: invalid_parameter: "Invalid parameter" record_not_found: "Record not found" + + not_authorized: "You need to be logged in to perform this action" diff --git a/config/locales/views.en.yml b/config/locales/views.en.yml index 0fc0891f..c626effb 100644 --- a/config/locales/views.en.yml +++ b/config/locales/views.en.yml @@ -110,7 +110,6 @@ en: hide: "Answered by" questionbox: title: "Ask something!" - required: "This user does not want to get asked by strangers. Why don't you %{signup}?" placeholder: "Type your question here…" anonymous: "Hide your name" load: "Asking…" @@ -124,6 +123,12 @@ en: blocking: "You are blocking this user." blocked: "This user has blocked you." locked: "This user currently does not accept questions." + require_user_html: | + This user requires others to be logged in to ask questions.
+ (%{sign_in} or %{sign_up}) + non_anonymous_html: | + This user does not want to receive anonymous questions.
+ (%{sign_in} or %{sign_up}) devise: registrations: edit: diff --git a/db/migrate/20221113110942_add_privacy_require_user_to_users.rb b/db/migrate/20221113110942_add_privacy_require_user_to_users.rb new file mode 100644 index 00000000..74e2fed7 --- /dev/null +++ b/db/migrate/20221113110942_add_privacy_require_user_to_users.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddPrivacyRequireUserToUsers < ActiveRecord::Migration[6.1] + def up + add_column :users, :privacy_require_user, :boolean, default: false + end + + def down + remove_column :users, :privacy_require_user + end +end diff --git a/db/schema.rb b/db/schema.rb index 1c9173f3..ebffd650 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_06_130744) do +ActiveRecord::Schema.define(version: 2022_11_13_110942) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -292,6 +292,8 @@ ActiveRecord::Schema.define(version: 2022_11_06_130744) do t.datetime "export_created_at" t.string "otp_secret_key" t.integer "otp_module", default: 0, null: false + t.datetime "deleted_at" + t.boolean "privacy_require_user", default: false t.boolean "privacy_lock_inbox", default: false t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true diff --git a/lib/errors.rb b/lib/errors.rb index 5d94f3cd..9d613e95 100644 --- a/lib/errors.rb +++ b/lib/errors.rb @@ -47,6 +47,12 @@ module Errors end end + class NotAuthorized < Base + def status + 401 + end + end + class UserNotFound < NotFound end diff --git a/lib/use_case/question/create.rb b/lib/use_case/question/create.rb index 05c9ad1b..eb085350 100644 --- a/lib/use_case/question/create.rb +++ b/lib/use_case/question/create.rb @@ -14,6 +14,7 @@ module UseCase option :direct, type: Types::Params::Bool, default: proc { true } def call + check_user check_lock check_anonymous_rules check_blocks @@ -64,6 +65,10 @@ module UseCase raise Errors::AskingSelfBlockedOther if source_user.blocking?(target_user) end + def check_user + raise Errors::NotAuthorized if target_user.privacy_require_user && !source_user_id + end + def increment_asked_count unless source_user_id && !anonymous && !direct # Only increment the asked count of the source user if the question diff --git a/spec/lib/use_case/question/create_spec.rb b/spec/lib/use_case/question/create_spec.rb index 79ae1aca..23972032 100644 --- a/spec/lib/use_case/question/create_spec.rb +++ b/spec/lib/use_case/question/create_spec.rb @@ -44,6 +44,12 @@ describe UseCase::Question::Create do end end + shared_examples "not authorized" do + it "raises an error" do + expect { subject }.to raise_error(Errors::NotAuthorized) + end + end + shared_examples "validates content" do context "content is empty" do let(:content) { "" } @@ -175,6 +181,19 @@ describe UseCase::Question::Create do it_behaves_like "invalid params" end end + + context "target user does not allow non-logged in questions" do + let(:allow_anon) { true } + let(:anonymous) { true } + let(:content) { "Hello world" } + let(:author_identifier) { "qwerty" } + + before do + target_user.update!(privacy_require_user: true) + end + + it_behaves_like "not authorized" + end end end end