FEATURE: Ability to clear a user's penalty history
You can do this manually if you want to allow them to reach TL3 without their penalty history counting against them.
This commit is contained in:
parent
c658fb6e31
commit
4195c7c9ea
|
@ -103,6 +103,16 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||||
anonymize() { return this.get('model').anonymize(); },
|
anonymize() { return this.get('model').anonymize(); },
|
||||||
disableSecondFactor() { return this.get('model').disableSecondFactor(); },
|
disableSecondFactor() { return this.get('model').disableSecondFactor(); },
|
||||||
|
|
||||||
|
|
||||||
|
clearPenaltyHistory() {
|
||||||
|
let user = this.get('model');
|
||||||
|
return ajax(`/admin/users/${user.get('id')}/penalty_history`, {
|
||||||
|
type: 'DELETE'
|
||||||
|
}).then(() => {
|
||||||
|
user.set('tl3_requirements.penalty_counts.total', 0);
|
||||||
|
}).catch(popupAjaxError);
|
||||||
|
},
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
const postCount = this.get('model.post_count');
|
const postCount = this.get('model.post_count');
|
||||||
if (postCount <= 5) {
|
if (postCount <= 5) {
|
||||||
|
|
|
@ -408,6 +408,21 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if model.tl3_requirements.penalty_counts.total}}
|
||||||
|
<div class='display-row clear-penalty-history'>
|
||||||
|
<div class='field'>{{i18n 'admin.user.penalty_count'}}</div>
|
||||||
|
<div class='value'>{{model.tl3_requirements.penalty_counts.total}}</div>
|
||||||
|
{{#if currentUser.admin}}
|
||||||
|
<div class='controls'>
|
||||||
|
{{d-button label="admin.user.clear_penalty_history.title"
|
||||||
|
icon="times"
|
||||||
|
action=(action "clearPenaltyHistory")}}
|
||||||
|
{{i18n "admin.user.clear_penalty_history.description"}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{{#if currentUser.admin}}
|
{{#if currentUser.admin}}
|
||||||
|
|
|
@ -54,6 +54,46 @@ class Admin::UsersController < Admin::AdminController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# DELETE action to delete penalty history for a user
|
||||||
|
def penalty_history
|
||||||
|
|
||||||
|
# We don't delete any history, we merely remove the action type
|
||||||
|
# with a removed type. It can still be viewed in the logs but
|
||||||
|
# will not affect TL3 promotions.
|
||||||
|
sql = <<~SQL
|
||||||
|
UPDATE user_histories
|
||||||
|
SET action = CASE
|
||||||
|
WHEN action = :silence_user THEN :removed_silence_user
|
||||||
|
WHEN action = :unsilence_user THEN :removed_unsilence_user
|
||||||
|
WHEN action = :suspend_user THEN :removed_suspend_user
|
||||||
|
WHEN action = :unsuspend_user THEN :removed_unsuspend_user
|
||||||
|
END
|
||||||
|
WHERE target_user_id = :user_id
|
||||||
|
AND action IN (
|
||||||
|
:silence_user,
|
||||||
|
:suspend_user,
|
||||||
|
:unsilence_user,
|
||||||
|
:unsuspend_user
|
||||||
|
)
|
||||||
|
SQL
|
||||||
|
|
||||||
|
UserHistory.exec_sql(
|
||||||
|
sql,
|
||||||
|
UserHistory.actions.slice(
|
||||||
|
:silence_user,
|
||||||
|
:suspend_user,
|
||||||
|
:unsilence_user,
|
||||||
|
:unsuspend_user,
|
||||||
|
:removed_silence_user,
|
||||||
|
:removed_unsilence_user,
|
||||||
|
:removed_suspend_user,
|
||||||
|
:removed_unsuspend_user
|
||||||
|
).merge(user_id: params[:user_id].to_i)
|
||||||
|
)
|
||||||
|
|
||||||
|
render json: success_json
|
||||||
|
end
|
||||||
|
|
||||||
def suspend
|
def suspend
|
||||||
guardian.ensure_can_suspend!(@user)
|
guardian.ensure_can_suspend!(@user)
|
||||||
@user.suspended_till = params[:suspend_until]
|
@user.suspended_till = params[:suspend_until]
|
||||||
|
|
|
@ -76,6 +76,10 @@ class UserHistory < ActiveRecord::Base
|
||||||
create_badge: 57,
|
create_badge: 57,
|
||||||
change_badge: 58,
|
change_badge: 58,
|
||||||
delete_badge: 59,
|
delete_badge: 59,
|
||||||
|
removed_silence_user: 60,
|
||||||
|
removed_suspend_user: 61,
|
||||||
|
removed_unsilence_user: 62,
|
||||||
|
removed_unsuspend_user: 63,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -90,6 +94,8 @@ class UserHistory < ActiveRecord::Base
|
||||||
:change_site_text,
|
:change_site_text,
|
||||||
:suspend_user,
|
:suspend_user,
|
||||||
:unsuspend_user,
|
:unsuspend_user,
|
||||||
|
:removed_suspend_user,
|
||||||
|
:removed_unsuspend_user,
|
||||||
:grant_badge,
|
:grant_badge,
|
||||||
:revoke_badge,
|
:revoke_badge,
|
||||||
:check_email,
|
:check_email,
|
||||||
|
@ -106,6 +112,8 @@ class UserHistory < ActiveRecord::Base
|
||||||
:create_category,
|
:create_category,
|
||||||
:silence_user,
|
:silence_user,
|
||||||
:unsilence_user,
|
:unsilence_user,
|
||||||
|
:removed_silence_user,
|
||||||
|
:removed_unsilence_user,
|
||||||
:grant_admin,
|
:grant_admin,
|
||||||
:revoke_admin,
|
:revoke_admin,
|
||||||
:grant_moderation,
|
:grant_moderation,
|
||||||
|
|
|
@ -3365,6 +3365,8 @@ en:
|
||||||
change_site_text: "change site text"
|
change_site_text: "change site text"
|
||||||
suspend_user: "suspend user"
|
suspend_user: "suspend user"
|
||||||
unsuspend_user: "unsuspend user"
|
unsuspend_user: "unsuspend user"
|
||||||
|
removed_suspend_user: "suspend user (removed)"
|
||||||
|
removed_unsuspend_user: "unsuspend user (removed)"
|
||||||
grant_badge: "grant badge"
|
grant_badge: "grant badge"
|
||||||
revoke_badge: "revoke badge"
|
revoke_badge: "revoke badge"
|
||||||
check_email: "check email"
|
check_email: "check email"
|
||||||
|
@ -3379,6 +3381,8 @@ en:
|
||||||
create_category: "create category"
|
create_category: "create category"
|
||||||
silence_user: "silence user"
|
silence_user: "silence user"
|
||||||
unsilence_user: "unsilence user"
|
unsilence_user: "unsilence user"
|
||||||
|
removed_silence_user: "silence user (removed)"
|
||||||
|
removed_unsilence_user: "unsilence user (removed)"
|
||||||
grant_admin: "grant admin"
|
grant_admin: "grant admin"
|
||||||
revoke_admin: "revoke admin"
|
revoke_admin: "revoke admin"
|
||||||
grant_moderation: "grant moderation"
|
grant_moderation: "grant moderation"
|
||||||
|
@ -3563,6 +3567,10 @@ en:
|
||||||
penalty_post_delete: "Delete the post"
|
penalty_post_delete: "Delete the post"
|
||||||
penalty_post_edit: "Edit the post"
|
penalty_post_edit: "Edit the post"
|
||||||
penalty_post_none: "Do nothing"
|
penalty_post_none: "Do nothing"
|
||||||
|
penalty_count: "Penalty Count"
|
||||||
|
clear_penalty_history:
|
||||||
|
title: "Clear Penalty History"
|
||||||
|
description: "users with penalties cannot reach TL3"
|
||||||
|
|
||||||
# keys ending with _MF use message format, see https://meta.discourse.org/t/message-format-support-for-localization/7035 for details
|
# keys ending with _MF use message format, see https://meta.discourse.org/t/message-format-support-for-localization/7035 for details
|
||||||
delete_all_posts_confirm_MF: "You are about to delete {POSTS, plural, one {1 post} other {# posts}} and {TOPICS, plural, one {1 topic} other {# topics}}. Are you sure?"
|
delete_all_posts_confirm_MF: "You are about to delete {POSTS, plural, one {1 post} other {# posts}} and {TOPICS, plural, one {1 topic} other {# topics}}. Are you sure?"
|
||||||
|
|
|
@ -103,6 +103,7 @@ Discourse::Application.routes.draw do
|
||||||
put "approve-bulk" => "users#approve_bulk"
|
put "approve-bulk" => "users#approve_bulk"
|
||||||
delete "reject-bulk" => "users#reject_bulk"
|
delete "reject-bulk" => "users#reject_bulk"
|
||||||
end
|
end
|
||||||
|
delete "penalty_history", constraints: AdminConstraint.new
|
||||||
put "suspend"
|
put "suspend"
|
||||||
put "delete_all_posts"
|
put "delete_all_posts"
|
||||||
put "unsuspend"
|
put "unsuspend"
|
||||||
|
|
|
@ -47,4 +47,42 @@ RSpec.describe Admin::UsersController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#penalty_history" do
|
||||||
|
let(:moderator) { Fabricate(:moderator) }
|
||||||
|
let(:logger) { StaffActionLogger.new(admin) }
|
||||||
|
|
||||||
|
it "doesn't allow moderators to clear a user's history" do
|
||||||
|
sign_in(moderator)
|
||||||
|
delete "/admin/users/#{user.id}/penalty_history.json"
|
||||||
|
expect(response.code).to eq("404")
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_logs(action)
|
||||||
|
UserHistory.where(target_user_id: user.id, action: UserHistory.actions[action])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "allows admins to clear a user's history" do
|
||||||
|
logger.log_user_suspend(user, "suspend reason")
|
||||||
|
logger.log_user_unsuspend(user)
|
||||||
|
logger.log_unsilence_user(user)
|
||||||
|
logger.log_silence_user(user)
|
||||||
|
|
||||||
|
sign_in(admin)
|
||||||
|
delete "/admin/users/#{user.id}/penalty_history.json"
|
||||||
|
expect(response.code).to eq("200")
|
||||||
|
|
||||||
|
expect(find_logs(:suspend_user)).to be_blank
|
||||||
|
expect(find_logs(:unsuspend_user)).to be_blank
|
||||||
|
expect(find_logs(:silence_user)).to be_blank
|
||||||
|
expect(find_logs(:unsilence_user)).to be_blank
|
||||||
|
|
||||||
|
expect(find_logs(:removed_suspend_user)).to be_present
|
||||||
|
expect(find_logs(:removed_unsuspend_user)).to be_present
|
||||||
|
expect(find_logs(:removed_silence_user)).to be_present
|
||||||
|
expect(find_logs(:removed_unsilence_user)).to be_present
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue