discourse/app/services/user_silencer.rb
Robin Ward bc3efab816 FIX: When disagreeing with a flag that silenced a user, unsilence them
Previously it would unhide their post but leave them silenced.

This fix also cleans up some of the helper classes to make it easier
to pass extra data to the silencing code (for example, a link to the
post that caused the user to be silenced.)

This patch also refactors the auto_silence specs to avoid using
stubs.
2019-02-08 08:50:50 -05:00

87 lines
2.5 KiB
Ruby

require_dependency 'staff_message_format'
class UserSilencer
attr_reader :user_history
def initialize(user, by_user = nil, opts = {})
@user, @by_user, @opts = user, by_user, opts
end
def self.silence(user, by_user = nil, opts = {})
UserSilencer.new(user, by_user, opts).silence
end
def self.unsilence(user, by_user = nil, opts = {})
UserSilencer.new(user, by_user, opts).unsilence
end
def self.was_silenced_for?(post)
return false unless post.present?
UserHistory.where(action: UserHistory.actions[:silence_user], post: post).exists?
end
def silence
hide_posts unless @opts[:keep_posts]
unless @user.silenced_till.present?
@user.silenced_till = @opts[:silenced_till] || 1000.years.from_now
if @user.save
message_type = @opts[:message] || :silenced_by_staff
details = StaffMessageFormat.new(
:silence,
@opts[:reason],
@opts[:message_body]
).format
context = "#{message_type}: '#{post.topic&.title rescue ''}' #{@opts[:reason]}"
SystemMessage.create(@user, message_type)
if @by_user
log_params = { context: context, details: details }
log_params[:post_id] = @opts[:post_id].to_i if @opts[:post_id]
@user_history = StaffActionLogger.new(@by_user).log_silence_user(
@user,
log_params
)
end
DiscourseEvent.trigger(
:user_silenced,
user: @user,
silenced_by: @by_user,
reason: @opts[:reason],
message: @opts[:message_body],
user_history: @user_history,
post_id: @opts[:post_id],
silenced_till: @user.silenced_till,
silenced_at: DateTime.now
)
return true
end
else
false
end
end
def hide_posts
return unless @user.trust_level == TrustLevel[0]
Post.where(user_id: @user.id).where("created_at > ?", 24.hours.ago).update_all(["hidden = true, hidden_reason_id = COALESCE(hidden_reason_id, ?)", Post.hidden_reasons[:new_user_spam_threshold_reached]])
topic_ids = Post.where(user_id: @user.id, post_number: 1).where("created_at > ?", 24.hours.ago).pluck(:topic_id)
Topic.where(id: topic_ids).update_all(visible: false) unless topic_ids.empty?
end
def unsilence
@user.silenced_till = nil
if @user.save
DiscourseEvent.trigger(:user_unsilenced, user: @user)
SystemMessage.create(@user, :unsilenced)
StaffActionLogger.new(@by_user).log_unsilence_user(@user) if @by_user
end
end
end