UX: suspend forever time period messages (#13776)

When the Forever option is selected for suspending a user, the user is suspended for 1000 years. Without customizing the site’s text, this time period is displayed to the user in the suspension email that is sent to the user, and if the user attempts to log back into the site. Telling someone that they have been suspended for 1000 years seems likely to come across as a bad attempt at humour.

This PR special case messages when a user suspended or silenced forever.
This commit is contained in:
Andrei Prigorshnev 2021-07-20 14:42:08 +04:00 committed by GitHub
parent 351ef6c2cc
commit 1a8c949900
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 94 additions and 26 deletions

View File

@ -589,13 +589,8 @@ class SessionController < ApplicationController
end end
def failed_to_login(user) def failed_to_login(user)
message = user.suspend_reason ? "login.suspended_with_reason" : "login.suspended"
{ {
error: I18n.t(message, error: user.suspended_message,
date: I18n.l(user.suspended_till, format: :date_only),
reason: Rack::Utils.escape_html(user.suspend_reason)
),
reason: 'suspended' reason: 'suspended'
} }
end end

View File

@ -153,13 +153,22 @@ class UserNotifications < ActionMailer::Base
return unless user_history = opts[:user_history] return unless user_history = opts[:user_history]
build_email( if user.silenced_forever?
user.email, build_email(
template: "user_notifications.account_silenced", user.email,
locale: user_locale(user), template: "user_notifications.account_silenced_forever",
reason: user_history.details, locale: user_locale(user),
silenced_till: I18n.l(user.silenced_till, format: :long) reason: user_history.details
) )
else
build_email(
user.email,
template: "user_notifications.account_silenced",
locale: user_locale(user),
reason: user_history.details,
silenced_till: I18n.l(user.silenced_till, format: :long)
)
end
end end
def account_suspended(user, opts = nil) def account_suspended(user, opts = nil)
@ -167,13 +176,22 @@ class UserNotifications < ActionMailer::Base
return unless user_history = opts[:user_history] return unless user_history = opts[:user_history]
build_email( if user.suspended_forever?
user.email, build_email(
template: "user_notifications.account_suspended", user.email,
locale: user_locale(user), template: "user_notifications.account_suspended_forever",
reason: user_history.details, locale: user_locale(user),
suspended_till: I18n.l(user.suspended_till, format: :long) reason: user_history.details
) )
else
build_email(
user.email,
template: "user_notifications.account_suspended",
locale: user_locale(user),
reason: user_history.details,
suspended_till: I18n.l(user.suspended_till, format: :long)
)
end
end end
def account_exists(user, opts = {}) def account_exists(user, opts = {})

View File

@ -958,6 +958,10 @@ class User < ActiveRecord::Base
silenced_record.try(:created_at) if silenced? silenced_record.try(:created_at) if silenced?
end end
def silenced_forever?
silenced_till > 100.years.from_now
end
def suspend_record def suspend_record
UserHistory.for(self, :suspend_user).order('id DESC').first UserHistory.for(self, :suspend_user).order('id DESC').first
end end
@ -974,6 +978,27 @@ class User < ActiveRecord::Base
nil nil
end end
def suspended_message
return nil unless suspended?
message = "login.suspended"
if suspend_reason
if suspended_forever?
message = "login.suspended_with_reason_forever"
else
message = "login.suspended_with_reason"
end
end
I18n.t(message,
date: I18n.l(suspended_till, format: :date_only),
reason: Rack::Utils.escape_html(suspend_reason))
end
def suspended_forever?
suspended_till > 100.years.from_now
end
# Use this helper to determine if the user has a particular trust level. # Use this helper to determine if the user has a particular trust level.
# Takes into account admin, etc. # Takes into account admin, etc.
def has_trust_level?(level) def has_trust_level?(level)

View File

@ -2515,6 +2515,7 @@ en:
reset_not_allowed_from_ip_address: "You can't request a password reset from that IP address." reset_not_allowed_from_ip_address: "You can't request a password reset from that IP address."
suspended: "You can't log in until %{date}." suspended: "You can't log in until %{date}."
suspended_with_reason: "Account suspended until %{date}: %{reason}" suspended_with_reason: "Account suspended until %{date}: %{reason}"
suspended_with_reason_forever: "Account suspended: %{reason}"
errors: "%{errors}" errors: "%{errors}"
not_available: "Not available. Try %{suggestion}?" not_available: "Not available. Try %{suggestion}?"
something_already_taken: "Something went wrong, perhaps the username or email is already registered. Try the forgot password link." something_already_taken: "Something went wrong, perhaps the username or email is already registered. Try the forgot password link."
@ -3703,6 +3704,14 @@ en:
Reason - %{reason} Reason - %{reason}
account_suspended_forever:
title: "Account Suspended"
subject_template: "[%{email_prefix}] Your account has been suspended"
text_body_template: |
You have been suspended from the forum.
Reason - %{reason}
account_silenced: account_silenced:
title: "Account Silenced" title: "Account Silenced"
subject_template: "[%{email_prefix}] Your account has been silenced" subject_template: "[%{email_prefix}] Your account has been silenced"
@ -3711,6 +3720,14 @@ en:
Reason - %{reason} Reason - %{reason}
account_silenced_forever:
title: "Account Silenced"
subject_template: "[%{email_prefix}] Your account has been silenced"
text_body_template: |
You have been silenced from the forum.
Reason - %{reason}
account_exists: account_exists:
title: "Account already exists" title: "Account already exists"
subject_template: "[%{email_prefix}] Account already exists" subject_template: "[%{email_prefix}] Account already exists"

View File

@ -111,8 +111,7 @@ class Auth::Result
if user&.suspended? if user&.suspended?
return { return {
suspended: true, suspended: true,
suspended_message: I18n.t(user.suspend_reason ? "login.suspended_with_reason" : "login.suspended", suspended_message: user.suspended_message
date: I18n.l(user.suspended_till, format: :date_only), reason: user.suspend_reason)
} }
end end

View File

@ -1401,11 +1401,25 @@ RSpec.describe SessionController do
login: user.username, password: 'myawesomepassword' login: user.username, password: 'myawesomepassword'
} }
expected_message = I18n.t('login.suspended_with_reason',
date: I18n.l(user.suspended_till, format: :date_only),
reason: Rack::Utils.escape_html(user.suspend_reason))
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(response.parsed_body['error']).to eq(I18n.t('login.suspended_with_reason', expect(response.parsed_body['error']).to eq(expected_message)
date: I18n.l(user.suspended_till, format: :date_only), end
reason: Rack::Utils.escape_html(user.suspend_reason)
)) it 'when suspended forever should return an error without suspended till date' do
user.suspended_till = 101.years.from_now
user.suspended_at = Time.now
user.save!
StaffActionLogger.new(user).log_user_suspend(user, "<strike>banned</strike>")
post "/session.json", params: {
login: user.username, password: 'myawesomepassword'
}
expected_message = I18n.t('login.suspended_with_reason_forever', reason: Rack::Utils.escape_html(user.suspend_reason))
expect(response.parsed_body['error']).to eq(expected_message)
end end
end end