Merge pull request #621 from Retrospring/🦊🔇
Site-wide anonymous blocking
This commit is contained in:
commit
41caf06e70
|
@ -6,13 +6,15 @@ class Ajax::AnonymousBlockController < AjaxController
|
||||||
|
|
||||||
question = Question.find(params[:question])
|
question = Question.find(params[:question])
|
||||||
|
|
||||||
|
raise Errors::Forbidden if params[:global] && !current_user.mod?
|
||||||
|
|
||||||
AnonymousBlock.create!(
|
AnonymousBlock.create!(
|
||||||
user: current_user,
|
user: params[:global] ? nil : current_user,
|
||||||
identifier: question.author_identifier,
|
identifier: question.author_identifier,
|
||||||
question: question
|
question:
|
||||||
)
|
)
|
||||||
|
|
||||||
question.inboxes.first.destroy
|
question.inboxes.first&.destroy
|
||||||
|
|
||||||
@response[:status] = :okay
|
@response[:status] = :okay
|
||||||
@response[:message] = t(".success")
|
@response[:message] = t(".success")
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Moderation::AnonymousBlockController < ApplicationController
|
||||||
|
def index
|
||||||
|
@anonymous_blocks = AnonymousBlock.where(user: nil)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,46 @@
|
||||||
|
import Rails from '@rails/ujs';
|
||||||
|
import swal from 'sweetalert';
|
||||||
|
|
||||||
|
import { showErrorNotification, showNotification } from "utilities/notifications";
|
||||||
|
import I18n from "retrospring/i18n";
|
||||||
|
|
||||||
|
export function blockAnonEventHandler(event: Event): void {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
swal({
|
||||||
|
title: I18n.translate('frontend.mod_mute.confirm.title'),
|
||||||
|
text: I18n.translate('frontend.mod_mute.confirm.text'),
|
||||||
|
type: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#DD6B55",
|
||||||
|
confirmButtonText: I18n.translate('voc.y'),
|
||||||
|
cancelButtonText: I18n.translate('voc.n'),
|
||||||
|
closeOnConfirm: true,
|
||||||
|
}, (dialogResult) => {
|
||||||
|
if (!dialogResult) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sender: HTMLAnchorElement = event.target as HTMLAnchorElement;
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
question: sender.getAttribute('data-q-id'),
|
||||||
|
global: 'true'
|
||||||
|
};
|
||||||
|
|
||||||
|
Rails.ajax({
|
||||||
|
url: '/ajax/block_anon',
|
||||||
|
type: 'POST',
|
||||||
|
data: new URLSearchParams(data).toString(),
|
||||||
|
success: (data) => {
|
||||||
|
if (!data.success) return false;
|
||||||
|
|
||||||
|
showNotification(data.message);
|
||||||
|
},
|
||||||
|
error: (data, status, xhr) => {
|
||||||
|
console.log(data, status, xhr);
|
||||||
|
showErrorNotification(I18n.translate('frontend.error.message'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -2,11 +2,13 @@ import registerEvents from 'utilities/registerEvents';
|
||||||
import { banCheckboxHandler, banFormHandler, permanentBanCheckboxHandler } from './ban';
|
import { banCheckboxHandler, banFormHandler, permanentBanCheckboxHandler } from './ban';
|
||||||
import { destroyReportHandler } from './destroy';
|
import { destroyReportHandler } from './destroy';
|
||||||
import { privilegeCheckHandler } from './privilege';
|
import { privilegeCheckHandler } from './privilege';
|
||||||
|
import { blockAnonEventHandler } from './blockAnon';
|
||||||
|
|
||||||
export default (): void => {
|
export default (): void => {
|
||||||
registerEvents([
|
registerEvents([
|
||||||
{ type: 'click', target: '[type=checkbox][name=check-your-privileges]', handler: privilegeCheckHandler, global: true },
|
{ type: 'click', target: '[type="checkbox"][name="check-your-privileges"]', handler: privilegeCheckHandler, global: true },
|
||||||
{ type: 'click', target: '[name=mod-delete-report]', handler: destroyReportHandler, global: true },
|
{ type: 'click', target: '[name="mod-delete-report"]', handler: destroyReportHandler, global: true },
|
||||||
|
{ type: 'click', target: '[name="mod-block-anon"]', handler: blockAnonEventHandler, global: true },
|
||||||
{ type: 'change', target: '[name="ban"][type="checkbox"]', handler: banCheckboxHandler, global: true },
|
{ type: 'change', target: '[name="ban"][type="checkbox"]', handler: banCheckboxHandler, global: true },
|
||||||
{ type: 'change', target: '[name="permaban"][type="checkbox"]', handler: permanentBanCheckboxHandler, global: true },
|
{ type: 'change', target: '[name="permaban"][type="checkbox"]', handler: permanentBanCheckboxHandler, global: true },
|
||||||
{ type: 'submit', target: '#modal-ban form', handler: banFormHandler, global: true }
|
{ type: 'submit', target: '#modal-ban form', handler: banFormHandler, global: true }
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
require "digest"
|
require "digest"
|
||||||
|
|
||||||
class AnonymousBlock < ApplicationRecord
|
class AnonymousBlock < ApplicationRecord
|
||||||
belongs_to :user
|
belongs_to :user, optional: true
|
||||||
belongs_to :question, optional: true
|
belongs_to :question, optional: true
|
||||||
|
|
||||||
def self.get_identifier(ip)
|
def self.get_identifier(ip)
|
||||||
|
|
|
@ -26,4 +26,8 @@ class Question < ApplicationRecord
|
||||||
return false if Inbox.where(question: self).count > 1
|
return false if Inbox.where(question: self).count > 1
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def generated? = %w[justask retrospring_exporter].include?(author_identifier)
|
||||||
|
|
||||||
|
def anonymous? = author_is_anonymous && author_identifier.present?
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
%a.dropdown-item{ href: "#", tabindex: -1, data: { action: "ab-question-report", q_id: a.question.id } }
|
%a.dropdown-item{ href: "#", tabindex: -1, data: { action: "ab-question-report", q_id: a.question.id } }
|
||||||
%i.fa.fa-exclamation-triangle
|
%i.fa.fa-exclamation-triangle
|
||||||
= t("voc.report")
|
= t("voc.report")
|
||||||
|
- if current_user.mod? && a.question.anonymous? && !a.question.generated?
|
||||||
|
%a.dropdown-item{ href: "#", name: "mod-block-anon", data: { q_id: a.question.id } }
|
||||||
|
%i.fa.fa-volume-off
|
||||||
|
= t("voc.block_site_wide")
|
||||||
- if current_user.has_role? :administrator
|
- if current_user.has_role? :administrator
|
||||||
%a.dropdown-item{ href: rails_admin_path_for_resource(a.question), target: "_blank" }
|
%a.dropdown-item{ href: rails_admin_path_for_resource(a.question), target: "_blank" }
|
||||||
%i.fa.fa-gears
|
%i.fa.fa-gears
|
||||||
|
|
|
@ -22,15 +22,18 @@
|
||||||
.dropdown-menu.dropdown-menu-right{ role: :menu }
|
.dropdown-menu.dropdown-menu-right{ role: :menu }
|
||||||
- if i.question.user_id != current_user.id
|
- if i.question.user_id != current_user.id
|
||||||
%a.dropdown-item{ name: "ib-report", data: { q_id: i.question.id } }
|
%a.dropdown-item{ name: "ib-report", data: { q_id: i.question.id } }
|
||||||
%i.fa.fa-warning
|
%i.fa.fa-fw.fa-warning
|
||||||
= t("voc.report")
|
= t("voc.report")
|
||||||
- if i.question.author_is_anonymous && i.question.author_identifier.present?
|
- if current_user.mod? && i.question.anonymous? && !i.question.generated?
|
||||||
|
%a.dropdown-item{ name: "mod-block-anon", data: { q_id: i.question.id } }
|
||||||
|
%i.fa.fa-fw.fa-volume-off
|
||||||
|
= t("voc.block_site_wide")
|
||||||
%a.dropdown-item{ name: "ib-block-anon", data: { q_id: i.question.id } }
|
%a.dropdown-item{ name: "ib-block-anon", data: { q_id: i.question.id } }
|
||||||
%i.fa.fa-minus-circle
|
%i.fa.fa-fw.fa-minus-circle
|
||||||
= t("voc.block")
|
= t("voc.block")
|
||||||
- if current_user.has_role? :administrator
|
- if current_user.has_role? :administrator
|
||||||
%a.dropdown-item{ href: rails_admin_path_for_resource(i) }
|
%a.dropdown-item{ href: rails_admin_path_for_resource(i) }
|
||||||
%i.fa.fa-gears
|
%i.fa.fa-fw.fa-gears
|
||||||
= t("voc.view_in_rails_admin")
|
= t("voc.view_in_rails_admin")
|
||||||
- if current_user == i.user
|
- if current_user == i.user
|
||||||
.card-body
|
.card-body
|
||||||
|
|
|
@ -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:
|
|
@ -30,6 +30,9 @@
|
||||||
= link_to moderation_toggle_unmask_path, method: :post, class: "dropdown-item" do
|
= link_to moderation_toggle_unmask_path, method: :post, class: "dropdown-item" do
|
||||||
%i.fa.fa-toggle-off
|
%i.fa.fa-toggle-off
|
||||||
= t(".unmask.enable")
|
= t(".unmask.enable")
|
||||||
|
%a.dropdown-item{ href: mod_anon_block_index_path }
|
||||||
|
%i.fa.fa-fw.fa-volume-off
|
||||||
|
= t(".site_wide_blocks")
|
||||||
%a.dropdown-item{ href: moderation_path }
|
%a.dropdown-item{ href: moderation_path }
|
||||||
%i.fa.fa-fw.fa-gavel
|
%i.fa.fa-fw.fa-gavel
|
||||||
= t(".moderation")
|
= t(".moderation")
|
||||||
|
|
|
@ -22,17 +22,7 @@
|
||||||
%p= t(".section.anon_blocks.body")
|
%p= t(".section.anon_blocks.body")
|
||||||
%ul.list-group
|
%ul.list-group
|
||||||
- @anonymous_blocks.each do |block|
|
- @anonymous_blocks.each do |block|
|
||||||
%li.list-group-item
|
= render "shared/anonymous_block", block:
|
||||||
.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")
|
|
||||||
|
|
||||||
- if @anonymous_blocks.empty?
|
- if @anonymous_blocks.empty?
|
||||||
%p.text-muted.text-center= t(".none")
|
%p.text-muted.text-center= t(".none")
|
||||||
|
|
|
@ -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")
|
|
@ -45,6 +45,10 @@ en:
|
||||||
confirm:
|
confirm:
|
||||||
title: "Are you sure?"
|
title: "Are you sure?"
|
||||||
text: "This question will be gone forever."
|
text: "This question will be gone forever."
|
||||||
|
mod_mute:
|
||||||
|
confirm:
|
||||||
|
title: "Are you sure?"
|
||||||
|
text: "This will mute this user for everyone."
|
||||||
report:
|
report:
|
||||||
confirm:
|
confirm:
|
||||||
title: "Are you sure you want to report this %{type}?"
|
title: "Are you sure you want to report this %{type}?"
|
||||||
|
|
|
@ -305,6 +305,7 @@ en:
|
||||||
heading: "Feedback"
|
heading: "Feedback"
|
||||||
bugs: "Bugs"
|
bugs: "Bugs"
|
||||||
features: "Feature Requests"
|
features: "Feature Requests"
|
||||||
|
site_wide_blocks: "Site-wide anonymous blocks"
|
||||||
desktop:
|
desktop:
|
||||||
ask_question: "Ask a question"
|
ask_question: "Ask a question"
|
||||||
list: :user.actions.list
|
list: :user.actions.list
|
||||||
|
@ -348,7 +349,6 @@ en:
|
||||||
blocks:
|
blocks:
|
||||||
index:
|
index:
|
||||||
title: "Blocks"
|
title: "Blocks"
|
||||||
blocked: "blocked %{time} ago"
|
|
||||||
none: "You are not blocking anyone."
|
none: "You are not blocking anyone."
|
||||||
section:
|
section:
|
||||||
blocks:
|
blocks:
|
||||||
|
@ -357,7 +357,6 @@ en:
|
||||||
anon_blocks:
|
anon_blocks:
|
||||||
heading: "Anonymous 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."
|
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:
|
data:
|
||||||
index:
|
index:
|
||||||
title: "Your Data"
|
title: "Your Data"
|
||||||
|
@ -511,6 +510,9 @@ en:
|
||||||
source: "Source code"
|
source: "Source code"
|
||||||
terms: "Terms of Service"
|
terms: "Terms of Service"
|
||||||
privacy: "Privacy Policy"
|
privacy: "Privacy Policy"
|
||||||
|
anonymous_block:
|
||||||
|
deleted_question: "Deleted question"
|
||||||
|
blocked: "blocked %{time} ago"
|
||||||
sidebar:
|
sidebar:
|
||||||
list:
|
list:
|
||||||
title: "Members"
|
title: "Members"
|
||||||
|
@ -572,6 +574,10 @@ en:
|
||||||
heading: "Reason:"
|
heading: "Reason:"
|
||||||
none: "No reason provided"
|
none: "No reason provided"
|
||||||
view: "View reported %{content}"
|
view: "View reported %{content}"
|
||||||
|
anonymous_block:
|
||||||
|
index:
|
||||||
|
title: "Site-wide anonymous blocks"
|
||||||
|
empty: "There are currently no users blocked site-wide."
|
||||||
user:
|
user:
|
||||||
actions:
|
actions:
|
||||||
view_inbox: "View inbox"
|
view_inbox: "View inbox"
|
||||||
|
|
|
@ -2,6 +2,7 @@ en:
|
||||||
voc:
|
voc:
|
||||||
answer: "Answer"
|
answer: "Answer"
|
||||||
block: "Block"
|
block: "Block"
|
||||||
|
block_site_wide: "Block user site-wide"
|
||||||
cancel: "Cancel"
|
cancel: "Cancel"
|
||||||
close: "Close"
|
close: "Close"
|
||||||
confirm: "Are you sure?"
|
confirm: "Are you sure?"
|
||||||
|
|
|
@ -23,6 +23,7 @@ Rails.application.routes.draw do
|
||||||
# Routes only accessible by moderators (moderation panel)
|
# Routes only accessible by moderators (moderation panel)
|
||||||
authenticate :user, ->(user) { user.mod? } do
|
authenticate :user, ->(user) { user.mod? } do
|
||||||
post "/moderation/unmask", to: "moderation#toggle_unmask", as: :moderation_toggle_unmask
|
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(/:type)", to: "moderation#index", as: :moderation, defaults: { type: "all" }
|
||||||
get "/moderation/inbox/:user", to: "moderation/inbox#index", as: :mod_inbox_index
|
get "/moderation/inbox/:user", to: "moderation/inbox#index", as: :mod_inbox_index
|
||||||
namespace :ajax do
|
namespace :ajax do
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class MakeUserIdOnAnonymousBlocksNullable < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
change_column_null :anonymous_blocks, :user_id, true
|
||||||
|
end
|
||||||
|
end
|
12
db/schema.rb
12
db/schema.rb
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2022_07_20_190421) do
|
ActiveRecord::Schema.define(version: 2022_08_20_163035) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -46,6 +46,8 @@ ActiveRecord::Schema.define(version: 2022_07_20_190421) do
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "smile_count", default: 0, null: false
|
t.integer "smile_count", default: 0, null: false
|
||||||
|
t.datetime "deleted_at"
|
||||||
|
t.index ["deleted_at"], name: "index_answers_on_deleted_at"
|
||||||
t.index ["question_id"], name: "index_answers_on_question_id"
|
t.index ["question_id"], name: "index_answers_on_question_id"
|
||||||
t.index ["user_id", "created_at"], name: "index_answers_on_user_id_and_created_at"
|
t.index ["user_id", "created_at"], name: "index_answers_on_user_id_and_created_at"
|
||||||
end
|
end
|
||||||
|
@ -58,6 +60,8 @@ ActiveRecord::Schema.define(version: 2022_07_20_190421) do
|
||||||
t.text "content"
|
t.text "content"
|
||||||
t.datetime "created_at", precision: 6, null: false
|
t.datetime "created_at", precision: 6, null: false
|
||||||
t.datetime "updated_at", precision: 6, null: false
|
t.datetime "updated_at", precision: 6, null: false
|
||||||
|
t.datetime "deleted_at"
|
||||||
|
t.index ["deleted_at"], name: "index_appendables_on_deleted_at"
|
||||||
t.index ["parent_id", "parent_type"], name: "index_appendables_on_parent_id_and_parent_type"
|
t.index ["parent_id", "parent_type"], name: "index_appendables_on_parent_id_and_parent_type"
|
||||||
t.index ["user_id", "created_at"], name: "index_appendables_on_user_id_and_created_at"
|
t.index ["user_id", "created_at"], name: "index_appendables_on_user_id_and_created_at"
|
||||||
end
|
end
|
||||||
|
@ -69,7 +73,9 @@ ActiveRecord::Schema.define(version: 2022_07_20_190421) do
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "smile_count", default: 0, null: false
|
t.integer "smile_count", default: 0, null: false
|
||||||
|
t.datetime "deleted_at"
|
||||||
t.index ["answer_id"], name: "index_comments_on_answer_id"
|
t.index ["answer_id"], name: "index_comments_on_answer_id"
|
||||||
|
t.index ["deleted_at"], name: "index_comments_on_deleted_at"
|
||||||
t.index ["user_id", "created_at"], name: "index_comments_on_user_id_and_created_at"
|
t.index ["user_id", "created_at"], name: "index_comments_on_user_id_and_created_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -144,6 +150,8 @@ ActiveRecord::Schema.define(version: 2022_07_20_190421) do
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "answer_count", default: 0, null: false
|
t.integer "answer_count", default: 0, null: false
|
||||||
t.boolean "direct", default: false, null: false
|
t.boolean "direct", default: false, null: false
|
||||||
|
t.datetime "deleted_at"
|
||||||
|
t.index ["deleted_at"], name: "index_questions_on_deleted_at"
|
||||||
t.index ["user_id", "created_at"], name: "index_questions_on_user_id_and_created_at"
|
t.index ["user_id", "created_at"], name: "index_questions_on_user_id_and_created_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -292,7 +300,9 @@ ActiveRecord::Schema.define(version: 2022_07_20_190421) do
|
||||||
t.datetime "export_created_at"
|
t.datetime "export_created_at"
|
||||||
t.string "otp_secret_key"
|
t.string "otp_secret_key"
|
||||||
t.integer "otp_module", default: 0, null: false
|
t.integer "otp_module", default: 0, null: false
|
||||||
|
t.datetime "deleted_at"
|
||||||
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
|
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
|
||||||
|
t.index ["deleted_at"], name: "index_users_on_deleted_at"
|
||||||
t.index ["email"], name: "index_users_on_email", unique: true
|
t.index ["email"], name: "index_users_on_email", unique: true
|
||||||
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
|
||||||
t.index ["screen_name"], name: "index_users_on_screen_name", unique: true
|
t.index ["screen_name"], name: "index_users_on_screen_name", unique: true
|
||||||
|
|
|
@ -72,7 +72,7 @@ module UseCase
|
||||||
|
|
||||||
def filtered?(question)
|
def filtered?(question)
|
||||||
target_user.mute_rules.any? { |rule| rule.applies_to? question } ||
|
target_user.mute_rules.any? { |rule| rule.applies_to? question } ||
|
||||||
(anonymous && target_user.anonymous_blocks.where(identifier: question.author_identifier).any?)
|
(anonymous && AnonymousBlock.where(identifier: question.author_identifier, user_id: [target_user.id, nil]).any?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def source_user
|
def source_user
|
||||||
|
|
|
@ -13,9 +13,9 @@ describe Ajax::AnonymousBlockController, :ajax_controller, type: :controller do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
end
|
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(:question) { FactoryBot.create(:question, author_identifier: "someidentifier") }
|
||||||
let!(:inbox) { FactoryBot.create(:inbox, user: user, question: question) }
|
let!(:inbox) { FactoryBot.create(:inbox, user:, question:) }
|
||||||
let(:params) do
|
let(:params) do
|
||||||
{ question: question.id }
|
{ question: question.id }
|
||||||
end
|
end
|
||||||
|
@ -35,6 +35,51 @@ describe Ajax::AnonymousBlockController, :ajax_controller, type: :controller do
|
||||||
include_examples "returns the expected response"
|
include_examples "returns the expected response"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "when blocking a user globally" do
|
||||||
|
let(:question) { FactoryBot.create(:question, author_identifier: "someidentifier") }
|
||||||
|
let!(:inbox) { FactoryBot.create(:inbox, user:, 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
|
context "when parameters are missing" do
|
||||||
let(:params) { {} }
|
let(:params) { {} }
|
||||||
let(:expected_response) do
|
let(:expected_response) do
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe Moderation::AnonymousBlockController, :ajax_controller, type: :controller do
|
||||||
|
describe "#index" do
|
||||||
|
subject { get :index }
|
||||||
|
|
||||||
|
shared_examples_for "should render the page successfully" do
|
||||||
|
it "should render the page successfully" do
|
||||||
|
subject
|
||||||
|
expect(response).to have_rendered(:index)
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples_for "empty" do
|
||||||
|
it "should assign an empty result set" do
|
||||||
|
subject
|
||||||
|
expect(assigns(:anonymous_blocks)).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there are no anonymous blocks" do
|
||||||
|
include_examples "empty"
|
||||||
|
include_examples "should render the page successfully"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there are some anonymous blocks set" do
|
||||||
|
before do
|
||||||
|
%w[a b c].each do |identifier|
|
||||||
|
AnonymousBlock.create!(identifier:)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should assign an result set" do
|
||||||
|
subject
|
||||||
|
expect(assigns(:anonymous_blocks).length).to eq(3)
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples "should render the page successfully"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when there are only anonymous blocks assigned for users" do
|
||||||
|
before do
|
||||||
|
user = FactoryBot.create(:user)
|
||||||
|
%w[a b c].each do |identifier|
|
||||||
|
AnonymousBlock.create!(user:, identifier:)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples "empty"
|
||||||
|
include_examples "should render the page successfully"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -79,6 +79,18 @@ describe UseCase::Question::Create do
|
||||||
|
|
||||||
it_behaves_like "creates the question", false
|
it_behaves_like "creates the question", false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "question is from an anon who is blocked globally" do
|
||||||
|
before do
|
||||||
|
AnonymousBlock.create!(
|
||||||
|
identifier: author_identifier,
|
||||||
|
question_id: FactoryBot.create(:question).id,
|
||||||
|
user_id: nil
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like "creates the question", false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "user signed in" do
|
context "user signed in" do
|
||||||
|
|
Loading…
Reference in New Issue