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