bans: don't allow users to be double banned.
This commit is contained in:
@@ -6,11 +6,15 @@ class Ban < ApplicationRecord
|
|||||||
after_destroy :create_unban_mod_action
|
after_destroy :create_unban_mod_action
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :banner, :class_name => "User"
|
belongs_to :banner, :class_name => "User"
|
||||||
|
|
||||||
validates_presence_of :reason, :duration
|
validates_presence_of :reason, :duration
|
||||||
|
validate :user, :validate_user_is_bannable, on: :create
|
||||||
|
|
||||||
scope :unexpired, -> { where("bans.expires_at > ?", Time.now) }
|
scope :unexpired, -> { where("bans.expires_at > ?", Time.now) }
|
||||||
scope :expired, -> { where("bans.expires_at <= ?", Time.now) }
|
scope :expired, -> { where("bans.expires_at <= ?", Time.now) }
|
||||||
|
|
||||||
|
attr_reader :duration
|
||||||
|
|
||||||
def self.is_banned?(user)
|
def self.is_banned?(user)
|
||||||
exists?(["user_id = ? AND expires_at > ?", user.id, Time.now])
|
exists?(["user_id = ? AND expires_at > ?", user.id, Time.now])
|
||||||
end
|
end
|
||||||
@@ -48,6 +52,10 @@ class Ban < ApplicationRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_user_is_bannable
|
||||||
|
self.errors[:user] << "is already banned" if user.is_banned?
|
||||||
|
end
|
||||||
|
|
||||||
def update_user_on_create
|
def update_user_on_create
|
||||||
user.update!(is_banned: true)
|
user.update!(is_banned: true)
|
||||||
end
|
end
|
||||||
@@ -69,8 +77,6 @@ class Ban < ApplicationRecord
|
|||||||
@duration = dur
|
@duration = dur
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :duration
|
|
||||||
|
|
||||||
def humanized_duration
|
def humanized_duration
|
||||||
ApplicationController.helpers.distance_of_time_in_words(created_at, expires_at)
|
ApplicationController.helpers.distance_of_time_in_words(created_at, expires_at)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
FactoryBot.define do
|
FactoryBot.define do
|
||||||
factory(:ban) do |f|
|
factory(:ban) do |f|
|
||||||
banner :factory => :admin_user
|
banner :factory => :admin_user
|
||||||
|
user
|
||||||
reason {FFaker::Lorem.words.join(" ")}
|
reason {FFaker::Lorem.words.join(" ")}
|
||||||
duration {60}
|
duration {60}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,10 +4,7 @@ class BansControllerTest < ActionDispatch::IntegrationTest
|
|||||||
context "A bans controller" do
|
context "A bans controller" do
|
||||||
setup do
|
setup do
|
||||||
@mod = create(:moderator_user)
|
@mod = create(:moderator_user)
|
||||||
@user = create(:user)
|
@ban = create(:ban)
|
||||||
as(@mod) do
|
|
||||||
@ban = create(:ban, user: @user)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context "new action" do
|
context "new action" do
|
||||||
@@ -40,7 +37,7 @@ class BansControllerTest < ActionDispatch::IntegrationTest
|
|||||||
|
|
||||||
context "search action" do
|
context "search action" do
|
||||||
should "render" do
|
should "render" do
|
||||||
get_auth bans_path(search: {user_name: @user.name}), @mod
|
get_auth bans_path(search: { user_name: @ban.user.name }), @mod
|
||||||
assert_response :success
|
assert_response :success
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -48,6 +45,7 @@ class BansControllerTest < ActionDispatch::IntegrationTest
|
|||||||
context "create action" do
|
context "create action" do
|
||||||
should "allow mods to ban members" do
|
should "allow mods to ban members" do
|
||||||
assert_difference("Ban.count", 1) do
|
assert_difference("Ban.count", 1) do
|
||||||
|
@user = create(:user)
|
||||||
post_auth bans_path, @mod, params: { ban: { duration: 60, reason: "xxx", user_id: @user.id }}
|
post_auth bans_path, @mod, params: { ban: { duration: 60, reason: "xxx", user_id: @user.id }}
|
||||||
|
|
||||||
assert_redirected_to bans_path
|
assert_redirected_to bans_path
|
||||||
@@ -77,12 +75,20 @@ class BansControllerTest < ActionDispatch::IntegrationTest
|
|||||||
|
|
||||||
should "not allow regular users to ban anyone" do
|
should "not allow regular users to ban anyone" do
|
||||||
assert_difference("Ban.count", 0) do
|
assert_difference("Ban.count", 0) do
|
||||||
|
@user = create(:user)
|
||||||
post_auth bans_path, @user, params: { ban: { duration: 60, reason: "xxx", user_id: @mod.id }}
|
post_auth bans_path, @user, params: { ban: { duration: 60, reason: "xxx", user_id: @mod.id }}
|
||||||
|
|
||||||
assert_response 403
|
assert_response 403
|
||||||
assert_equal(false, @mod.reload.is_banned?)
|
assert_equal(false, @mod.reload.is_banned?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
should "not allow users to be double banned" do
|
||||||
|
assert_difference("Ban.count", 0) do
|
||||||
|
post_auth bans_path, @mod, params: { ban: { duration: 60, reason: "xxx", user_id: @ban.user.id }}
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "update action" do
|
context "update action" do
|
||||||
|
|||||||
Reference in New Issue
Block a user