FIX: Show error message if user is already silenced or suspended (#10988)
Users could be silenced or suspended by two staff members at the same time and would not be aware of it. This commit shows an error message if another penalty has been applied.
This commit is contained in:
parent
d384e744a8
commit
d2116f0029
|
@ -1,12 +1,13 @@
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { extractError } from "discourse/lib/ajax-error";
|
||||||
import Mixin from "@ember/object/mixin";
|
import Mixin from "@ember/object/mixin";
|
||||||
import { next } from "@ember/runloop";
|
import { next } from "@ember/runloop";
|
||||||
import { Promise } from "rsvp";
|
import { Promise } from "rsvp";
|
||||||
import bootbox from "bootbox";
|
import bootbox from "bootbox";
|
||||||
|
|
||||||
export default Mixin.create(ModalFunctionality, {
|
export default Mixin.create(ModalFunctionality, {
|
||||||
|
errorMessage: null,
|
||||||
reason: null,
|
reason: null,
|
||||||
message: null,
|
message: null,
|
||||||
postEdit: null,
|
postEdit: null,
|
||||||
|
@ -18,6 +19,7 @@ export default Mixin.create(ModalFunctionality, {
|
||||||
|
|
||||||
resetModal() {
|
resetModal() {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
|
errorMessage: null,
|
||||||
reason: null,
|
reason: null,
|
||||||
message: null,
|
message: null,
|
||||||
loadingUser: true,
|
loadingUser: true,
|
||||||
|
@ -66,6 +68,8 @@ export default Mixin.create(ModalFunctionality, {
|
||||||
callback(result);
|
callback(result);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(popupAjaxError);
|
.catch((error) => {
|
||||||
|
this.set("errorMessage", extractError(error));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -352,28 +352,17 @@ const AdminUser = User.extend({
|
||||||
type: "PUT",
|
type: "PUT",
|
||||||
})
|
})
|
||||||
.then((result) => this.setProperties(result.unsilence))
|
.then((result) => this.setProperties(result.unsilence))
|
||||||
.catch((e) => {
|
|
||||||
const error = I18n.t("admin.user.unsilence_failed", {
|
|
||||||
error: this._formatError(e),
|
|
||||||
});
|
|
||||||
bootbox.alert(error);
|
|
||||||
})
|
|
||||||
.finally(() => this.set("silencingUser", false));
|
.finally(() => this.set("silencingUser", false));
|
||||||
},
|
},
|
||||||
|
|
||||||
silence(data) {
|
silence(data) {
|
||||||
this.set("silencingUser", true);
|
this.set("silencingUser", true);
|
||||||
|
|
||||||
return ajax(`/admin/users/${this.id}/silence`, {
|
return ajax(`/admin/users/${this.id}/silence`, {
|
||||||
type: "PUT",
|
type: "PUT",
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
.then((result) => this.setProperties(result.silence))
|
.then((result) => this.setProperties(result.silence))
|
||||||
.catch((e) => {
|
|
||||||
const error = I18n.t("admin.user.silence_failed", {
|
|
||||||
error: this._formatError(e),
|
|
||||||
});
|
|
||||||
bootbox.alert(error);
|
|
||||||
})
|
|
||||||
.finally(() => this.set("silencingUser", false));
|
.finally(() => this.set("silencingUser", false));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
{{#d-modal-body title="admin.user.silence_modal_title"}}
|
{{#d-modal-body title="admin.user.silence_modal_title"}}
|
||||||
{{#conditional-loading-spinner condition=loadingUser}}
|
{{#conditional-loading-spinner condition=loadingUser}}
|
||||||
|
|
||||||
|
{{#if errorMessage}}
|
||||||
|
<div class="alert alert-error">{{errorMessage}}</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="until-controls">
|
<div class="until-controls">
|
||||||
<label>
|
<label>
|
||||||
{{future-date-input
|
{{future-date-input
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
{{#d-modal-body title="admin.user.suspend_modal_title"}}
|
{{#d-modal-body title="admin.user.suspend_modal_title"}}
|
||||||
{{#conditional-loading-spinner condition=loadingUser}}
|
{{#conditional-loading-spinner condition=loadingUser}}
|
||||||
|
|
||||||
|
{{#if errorMessage}}
|
||||||
|
<div class="alert alert-error">{{errorMessage}}</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if user.canSuspend}}
|
{{#if user.canSuspend}}
|
||||||
<div class="until-controls">
|
<div class="until-controls">
|
||||||
<label>
|
<label>
|
||||||
|
|
|
@ -93,6 +93,16 @@ class Admin::UsersController < Admin::AdminController
|
||||||
|
|
||||||
def suspend
|
def suspend
|
||||||
guardian.ensure_can_suspend!(@user)
|
guardian.ensure_can_suspend!(@user)
|
||||||
|
|
||||||
|
if @user.suspended?
|
||||||
|
suspend_record = @user.suspend_record
|
||||||
|
message = I18n.t("user.already_suspended",
|
||||||
|
staff: suspend_record.acting_user.username,
|
||||||
|
time_ago: FreedomPatches::Rails4.time_ago_in_words(suspend_record.created_at, true, scope: :'datetime.distance_in_words_verbose')
|
||||||
|
)
|
||||||
|
return render json: failed_json.merge(message: message), status: 409
|
||||||
|
end
|
||||||
|
|
||||||
params.require([:suspend_until, :reason])
|
params.require([:suspend_until, :reason])
|
||||||
|
|
||||||
@user.suspended_till = params[:suspend_until]
|
@user.suspended_till = params[:suspend_until]
|
||||||
|
@ -315,6 +325,15 @@ class Admin::UsersController < Admin::AdminController
|
||||||
def silence
|
def silence
|
||||||
guardian.ensure_can_silence_user! @user
|
guardian.ensure_can_silence_user! @user
|
||||||
|
|
||||||
|
if @user.silenced?
|
||||||
|
silenced_record = @user.silenced_record
|
||||||
|
message = I18n.t("user.already_silenced",
|
||||||
|
staff: silenced_record.acting_user.username,
|
||||||
|
time_ago: FreedomPatches::Rails4.time_ago_in_words(silenced_record.created_at, true, scope: :'datetime.distance_in_words_verbose')
|
||||||
|
)
|
||||||
|
return render json: failed_json.merge(message: message), status: 409
|
||||||
|
end
|
||||||
|
|
||||||
message = params[:message]
|
message = params[:message]
|
||||||
|
|
||||||
silencer = UserSilencer.new(
|
silencer = UserSilencer.new(
|
||||||
|
|
|
@ -2507,6 +2507,8 @@ en:
|
||||||
same_ip_address: "Same IP address (%{ip_address}) as other users"
|
same_ip_address: "Same IP address (%{ip_address}) as other users"
|
||||||
inactive_user: "Inactive user"
|
inactive_user: "Inactive user"
|
||||||
email_in_spam_header: "User's first email was flagged as spam"
|
email_in_spam_header: "User's first email was flagged as spam"
|
||||||
|
already_silenced: "User was already silenced by %{staff} %{time_ago}."
|
||||||
|
already_suspended: "User was already suspended by %{staff} %{time_ago}."
|
||||||
|
|
||||||
reviewables_reminder:
|
reviewables_reminder:
|
||||||
submitted:
|
submitted:
|
||||||
|
|
|
@ -149,6 +149,27 @@ RSpec.describe Admin::UsersController do
|
||||||
expect(log.details).to match(/because I said so/)
|
expect(log.details).to match(/because I said so/)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "checks if user is suspended" do
|
||||||
|
put "/admin/users/#{user.id}/suspend.json", params: {
|
||||||
|
suspend_until: 5.hours.from_now,
|
||||||
|
reason: "because I said so"
|
||||||
|
}
|
||||||
|
|
||||||
|
put "/admin/users/#{user.id}/suspend.json", params: {
|
||||||
|
suspend_until: 5.hours.from_now,
|
||||||
|
reason: "because I said so too"
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(response.status).to eq(409)
|
||||||
|
expect(response.parsed_body["message"]).to eq(
|
||||||
|
I18n.t(
|
||||||
|
"user.already_suspended",
|
||||||
|
staff: admin.username,
|
||||||
|
time_ago: FreedomPatches::Rails4.time_ago_in_words(user.suspend_record.created_at, true, scope: :'datetime.distance_in_words_verbose')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
it "requires suspend_until and reason" do
|
it "requires suspend_until and reason" do
|
||||||
expect(user).not_to be_suspended
|
expect(user).not_to be_suspended
|
||||||
put "/admin/users/#{user.id}/suspend.json", params: {}
|
put "/admin/users/#{user.id}/suspend.json", params: {}
|
||||||
|
@ -749,6 +770,27 @@ RSpec.describe Admin::UsersController do
|
||||||
reg_user.reload
|
reg_user.reload
|
||||||
expect(reg_user).to be_silenced
|
expect(reg_user).to be_silenced
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "checks if user is silenced" do
|
||||||
|
put "/admin/users/#{user.id}/silence.json", params: {
|
||||||
|
silenced_till: 5.hours.from_now,
|
||||||
|
reason: "because I said so"
|
||||||
|
}
|
||||||
|
|
||||||
|
put "/admin/users/#{user.id}/silence.json", params: {
|
||||||
|
silenced_till: 5.hours.from_now,
|
||||||
|
reason: "because I said so too"
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(response.status).to eq(409)
|
||||||
|
expect(response.parsed_body["message"]).to eq(
|
||||||
|
I18n.t(
|
||||||
|
"user.already_silenced",
|
||||||
|
staff: admin.username,
|
||||||
|
time_ago: FreedomPatches::Rails4.time_ago_in_words(user.silenced_record.created_at, true, scope: :'datetime.distance_in_words_verbose')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#unsilence' do
|
describe '#unsilence' do
|
||||||
|
|
Loading…
Reference in New Issue