From 136eac8bddae4d5828cd5e532ebe3f1e1cb451b0 Mon Sep 17 00:00:00 2001 From: Karina Kwiatek Date: Sat, 13 Aug 2022 20:01:22 +0200 Subject: [PATCH] Add page for managing site-wide anonymous-blocks --- .../ajax/anonymous_block_controller.rb | 6 ++- .../moderation/anonymous_block_controller.rb | 5 ++ .../moderation/anonymous_block/index.haml | 10 ++++ app/views/navigation/dropdown/_profile.haml | 2 +- app/views/settings/blocks/index.haml | 12 +---- app/views/shared/_anonymous_block.haml | 11 +++++ config/locales/views.en.yml | 10 +++- config/locales/voc.en.yml | 1 + config/routes.rb | 1 + .../ajax/anonymous_block_controller_spec.rb | 47 ++++++++++++++++++- 10 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 app/controllers/moderation/anonymous_block_controller.rb create mode 100644 app/views/moderation/anonymous_block/index.haml create mode 100644 app/views/shared/_anonymous_block.haml diff --git a/app/controllers/ajax/anonymous_block_controller.rb b/app/controllers/ajax/anonymous_block_controller.rb index 4e7a86f4..c6477ba8 100644 --- a/app/controllers/ajax/anonymous_block_controller.rb +++ b/app/controllers/ajax/anonymous_block_controller.rb @@ -6,10 +6,12 @@ class Ajax::AnonymousBlockController < AjaxController question = Question.find(params[:question]) + raise Errors::Forbidden if params[:global] && !current_user.has_role?(:moderator) + AnonymousBlock.create!( - user: current_user, + user: params[:global] ? nil : current_user, identifier: question.author_identifier, - question: question + question:, ) question.inboxes.first.destroy diff --git a/app/controllers/moderation/anonymous_block_controller.rb b/app/controllers/moderation/anonymous_block_controller.rb new file mode 100644 index 00000000..1f6b2e29 --- /dev/null +++ b/app/controllers/moderation/anonymous_block_controller.rb @@ -0,0 +1,5 @@ +class Moderation::AnonymousBlockController < ApplicationController + def index + @anonymous_blocks = AnonymousBlock.where(user: nil) + end +end diff --git a/app/views/moderation/anonymous_block/index.haml b/app/views/moderation/anonymous_block/index.haml new file mode 100644 index 00000000..689669f6 --- /dev/null +++ b/app/views/moderation/anonymous_block/index.haml @@ -0,0 +1,10 @@ +- provide(:title, generate_title(t(".title"))) + +.container-lg.container--main + .card + .card-body + #entries + - if @anonymous_blocks.empty? + .text-center= t(".empty") + - @anonymous_blocks.each do |block| + = render "shared/anonymous_block", block: diff --git a/app/views/navigation/dropdown/_profile.haml b/app/views/navigation/dropdown/_profile.haml index 3388da00..95dfcf88 100644 --- a/app/views/navigation/dropdown/_profile.haml +++ b/app/views/navigation/dropdown/_profile.haml @@ -32,7 +32,7 @@ = t(".unmask.enable") %a.dropdown-item{ href: mod_anon_block_index_path } %i.fa.fa-fw.fa-volume-off - = t("views.navigation.blocks") + = t(".site_wide_blocks") %a.dropdown-item{ href: moderation_path } %i.fa.fa-fw.fa-gavel = t(".moderation") diff --git a/app/views/settings/blocks/index.haml b/app/views/settings/blocks/index.haml index ab3947dc..38608e0d 100644 --- a/app/views/settings/blocks/index.haml +++ b/app/views/settings/blocks/index.haml @@ -22,17 +22,7 @@ %p= t(".section.anon_blocks.body") %ul.list-group - @anonymous_blocks.each do |block| - %li.list-group-item - .d-flex - %div - - if block.question.present? - %p.mb-0= block.question.content - - else - %p.mb-0.text-muted.font-italic= t(".deleted_question") - %p.text-muted.mb-0= t(".blocked", time: time_ago_in_words(block.created_at)) - .ml-auto.d-inline-flex - %button.btn.btn-default.align-self-center{ data: { action: "anon-unblock", target: block.id } } - %span.pe-none= t("voc.unblock") + = render "shared/anonymous_block", block: - if @anonymous_blocks.empty? %p.text-muted.text-center= t(".none") diff --git a/app/views/shared/_anonymous_block.haml b/app/views/shared/_anonymous_block.haml new file mode 100644 index 00000000..39cb20a9 --- /dev/null +++ b/app/views/shared/_anonymous_block.haml @@ -0,0 +1,11 @@ +%li.list-group-item + .d-flex + %div + - if block.question.present? + %p.mb-0= block.question.content + - else + %p.mb-0.text-muted.font-italic= t(".deleted_question") + %p.text-muted.mb-0= t(".blocked", time: time_ago_in_words(block.created_at)) + .ml-auto.d-inline-flex + %button.btn.btn-default.align-self-center{ data: { action: "anon-unblock", target: block.id } } + %span.pe-none= t("voc.unblock") \ No newline at end of file diff --git a/config/locales/views.en.yml b/config/locales/views.en.yml index eba04ea0..66ad3f1e 100644 --- a/config/locales/views.en.yml +++ b/config/locales/views.en.yml @@ -305,6 +305,7 @@ en: heading: "Feedback" bugs: "Bugs" features: "Feature Requests" + site_wide_blocks: "Site-wide anonymous blocks" desktop: ask_question: "Ask a question" list: :user.actions.list @@ -348,7 +349,6 @@ en: blocks: index: title: "Blocks" - blocked: "blocked %{time} ago" none: "You are not blocking anyone." section: blocks: @@ -357,7 +357,6 @@ en: anon_blocks: heading: "Anonymous Blocks" body: "Each anonymous user you've blocked is listed here, along with a way to unblock them. We also display the question they asked you to add some more context. You can block anonymous users directly from the question in your inbox." - deleted_question: "Deleted question" data: index: title: "Your Data" @@ -511,6 +510,9 @@ en: source: "Source code" terms: "Terms of Service" privacy: "Privacy Policy" + anonymous_block: + deleted_question: "Deleted question" + blocked: "blocked %{time} ago" sidebar: list: title: "Members" @@ -572,6 +574,10 @@ en: heading: "Reason:" none: "No reason provided" view: "View reported %{content}" + anonymous_block: + index: + title: "Site-wide anonymous blocks" + empty: "There are currently no users blocked site-wide." user: actions: view_inbox: "View inbox" diff --git a/config/locales/voc.en.yml b/config/locales/voc.en.yml index 3533a892..fc15602f 100644 --- a/config/locales/voc.en.yml +++ b/config/locales/voc.en.yml @@ -2,6 +2,7 @@ en: voc: answer: "Answer" block: "Block" + block_site_wide: "Block user site-wide" cancel: "Cancel" close: "Close" confirm: "Are you sure?" diff --git a/config/routes.rb b/config/routes.rb index e484097a..ab4eca51 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -23,6 +23,7 @@ Rails.application.routes.draw do # Routes only accessible by moderators (moderation panel) authenticate :user, ->(user) { user.mod? } do post "/moderation/unmask", to: "moderation#toggle_unmask", as: :moderation_toggle_unmask + get "/moderation/blocks", to: "moderation/anonymous_block#index", as: :mod_anon_block_index get "/moderation(/:type)", to: "moderation#index", as: :moderation, defaults: { type: "all" } get "/moderation/inbox/:user", to: "moderation/inbox#index", as: :mod_inbox_index namespace :ajax do diff --git a/spec/controllers/ajax/anonymous_block_controller_spec.rb b/spec/controllers/ajax/anonymous_block_controller_spec.rb index 24730037..22d212a8 100644 --- a/spec/controllers/ajax/anonymous_block_controller_spec.rb +++ b/spec/controllers/ajax/anonymous_block_controller_spec.rb @@ -13,7 +13,7 @@ describe Ajax::AnonymousBlockController, :ajax_controller, type: :controller do sign_in(user) end - context "when all parameters are given" do + context "when all required parameters are given" do let(:question) { FactoryBot.create(:question, author_identifier: "someidentifier") } let!(:inbox) { FactoryBot.create(:inbox, user: user, question: question) } let(:params) do @@ -35,6 +35,51 @@ describe Ajax::AnonymousBlockController, :ajax_controller, type: :controller do include_examples "returns the expected response" end + context "when blocking a user globally" do + let(:question) { FactoryBot.create(:question, author_identifier: "someidentifier") } + let!(:inbox) { FactoryBot.create(:inbox, user: user, question: question) } + let(:params) do + { question: question.id, global: "true" } + end + + context "as a moderator" do + let(:expected_response) do + { + "success" => true, + "status" => "okay", + "message" => anything + } + end + + before do + user.add_role(:moderator) + end + + it "creates an site-wide anonymous block" do + expect { subject }.to(change { AnonymousBlock.count }.by(1)) + expect(AnonymousBlock.last.user_id).to be_nil + end + + include_examples "returns the expected response" + end + + context "as a regular user" do + let(:expected_response) do + { + "success" => false, + "status" => "forbidden", + "message" => anything + } + end + + it "does not create an anonymous block" do + expect { subject }.not_to(change { AnonymousBlock.count }) + end + + include_examples "returns the expected response" + end + end + context "when parameters are missing" do let(:params) { {} } let(:expected_response) do