Add mark as spam button on user profile for admins (#20794)
This commit is contained in:
parent
6b8c363487
commit
b0086c9171
8 changed files with 121 additions and 0 deletions
|
|
@ -266,6 +266,37 @@ class UsersController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def toggle_spam
|
||||
@target_user = User.find_by(id: params[:id])
|
||||
render json, status: :not_found unless @target_user
|
||||
|
||||
authorize @current_user
|
||||
|
||||
begin
|
||||
case request.method_symbol
|
||||
when :put
|
||||
manager = Moderator::ManageActivityAndRoles.new(admin: @current_user, user: @target_user, user_params: {})
|
||||
manager.handle_user_status("Spam", "Mark as Spam from user profile")
|
||||
payload = { action: "mark_as_spam", target_user_id: params[:id] }
|
||||
Audit::Logger.log(:admin, @current_user, payload)
|
||||
when :delete
|
||||
manager = Moderator::ManageActivityAndRoles.new(admin: @current_user, user: @target_user, user_params: {})
|
||||
manager.handle_user_status("Good standing", "Set in good standing from user profile")
|
||||
payload = { action: "remove_spam_role_from_user", target_user_id: params[:id] }
|
||||
Audit::Logger.log(:admin, @current_user, payload)
|
||||
else
|
||||
render json, status: :method_not_allowed
|
||||
end
|
||||
head :no_content
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("Failed to toggle spam status for user #{params[:id]}: #{e.message}")
|
||||
respond_to do |format|
|
||||
format.html { redirect_to "/dashboard", notice: I18n.t("articles_controller.deleted") }
|
||||
format.json { head :internal_server_error }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_organization_tab
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { initBlock } from '../profileDropdown/blockButton';
|
||||
import { initFlag } from '../profileDropdown/flagButton';
|
||||
import { initSpam } from '../profileDropdown/spamButton';
|
||||
import { initializeDropdown } from '@utilities/dropdownUtils';
|
||||
|
||||
/* global userData */
|
||||
|
|
@ -7,6 +8,7 @@ import { initializeDropdown } from '@utilities/dropdownUtils';
|
|||
function initButtons() {
|
||||
initBlock();
|
||||
initFlag();
|
||||
initSpam();
|
||||
}
|
||||
|
||||
function initDropdown() {
|
||||
|
|
|
|||
66
app/javascript/profileDropdown/spamButton.js
Normal file
66
app/javascript/profileDropdown/spamButton.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/* global userData */
|
||||
/* eslint-disable no-alert, import/order */
|
||||
import { request } from '@utilities/http';
|
||||
import { getUserDataAndCsrfToken } from '@utilities/getUserDataAndCsrfToken';
|
||||
|
||||
function addSpamButton(spamButton) {
|
||||
const { profileUserId, profileUserName } = spamButton.dataset;
|
||||
|
||||
let isUserSpam = spamButton.dataset.isUserSpam === 'true';
|
||||
|
||||
function toggleSpam() {
|
||||
const confirm = window.confirm(
|
||||
isUserSpam
|
||||
? 'Are you sure you want to remove the spam role from this user? This will make all of their posts and comments visible again, and regain their access to new posts'
|
||||
: 'Are you sure you want to add the spam role to this user? This will hide all of their posts and comments and restrict their access to create new posts and comments',
|
||||
);
|
||||
|
||||
if (confirm) {
|
||||
request(`/users/${profileUserId}/spam`, {
|
||||
method: isUserSpam ? 'DELETE' : 'PUT',
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
isUserSpam = !isUserSpam;
|
||||
spamButton.innerHTML = isUserSpam ? `Set ${profileUserName} in Good standing` : `Mark ${profileUserName} as Spam`;
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
Honeybadger.notify(
|
||||
isUserSpam ? 'Unable to remove spam role from user' : 'Unable to mark user as spam',
|
||||
profileUserId,
|
||||
);
|
||||
window.alert(`Something went wrong: ${e}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
spamButton.addEventListener('click', toggleSpam);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a spam button visible only to admin users on profile pages.
|
||||
* @function initSpam
|
||||
* @returns {(void|undefined)} This function has no useable return value.
|
||||
*/
|
||||
|
||||
export function initSpam() {
|
||||
const spamButton = document.getElementById(
|
||||
'user-profile-dropdownmenu-spam-button',
|
||||
);
|
||||
|
||||
if (!spamButton) {
|
||||
// button not always present when this is called
|
||||
return;
|
||||
}
|
||||
|
||||
getUserDataAndCsrfToken().then(() => {
|
||||
const user = userData();
|
||||
if (!user || !user.admin) {
|
||||
spamButton.remove();
|
||||
return;
|
||||
}
|
||||
addSpamButton(spamButton);
|
||||
});
|
||||
}
|
||||
/* eslint-enable no-alert */
|
||||
|
|
@ -97,6 +97,7 @@ class UserPolicy < ApplicationPolicy
|
|||
alias manage_user_roles? elevated_user?
|
||||
alias unpublish_all_articles? elevated_user?
|
||||
alias search_by_email? elevated_user?
|
||||
alias toggle_spam? elevated_user?
|
||||
|
||||
def moderation_routes?
|
||||
(user.has_trusted_role? || elevated_user?) && !user.spam_or_suspended?
|
||||
|
|
|
|||
|
|
@ -50,6 +50,15 @@
|
|||
class="border-none crayons-link crayons-link--block">
|
||||
<%= t("views.users.#{@flag_status ? 'unflag' : 'flag'}", user: @user.username) %>
|
||||
</a>
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
id="user-profile-dropdownmenu-spam-button"
|
||||
data-profile-user-id="<%= @user.id %>"
|
||||
data-profile-user-name="@<%= @user.username %>"
|
||||
data-is-user-spam="<%= @user.spam? %>"
|
||||
class="border-none crayons-link crayons-link--block">
|
||||
<%= t("views.users.#{@user.spam? ? 'unspam' : 'spam'}", user: @user.username) %>
|
||||
</a>
|
||||
<% end %>
|
||||
<span class="report-abuse-link-wrapper" data-path="/report-abuse?url=<%= user_url(@user) %>"></span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ en:
|
|||
notice_html: All private interactions <b>must</b> abide by the %{code}.
|
||||
placeholder: Enter your message here...
|
||||
submit: Send
|
||||
spam: Mark @%{user} as Spam
|
||||
social: "%{service} website"
|
||||
unflag: Unflag @%{user}
|
||||
unspam: Set @%{user} in Good standing
|
||||
website: Personal website
|
||||
|
|
|
|||
|
|
@ -92,5 +92,7 @@ fr:
|
|||
placeholder: Enter your message here...
|
||||
submit: Send
|
||||
social: "%{service} website"
|
||||
spam: Marquer @%{user} comme spam
|
||||
unflag: Unflag @%{user}
|
||||
unspam: Définir @%{user} en règle
|
||||
website: Personal website
|
||||
|
|
|
|||
|
|
@ -117,6 +117,10 @@ Rails.application.routes.draw do
|
|||
end
|
||||
resources :comment_mutes, only: %i[update]
|
||||
resources :users, only: %i[index show], defaults: { format: :json } do # internal API
|
||||
member do
|
||||
put "spam", to: "users#toggle_spam"
|
||||
delete "spam", to: "users#toggle_spam"
|
||||
end
|
||||
collection do
|
||||
resources :devices, only: %i[create destroy]
|
||||
end
|
||||
|
|
@ -247,6 +251,10 @@ Rails.application.routes.draw do
|
|||
delete "users/api_secrets/:id", to: "api_secrets#destroy", as: :users_api_secret
|
||||
post "users/update_password", to: "users#update_password", as: :user_update_password
|
||||
|
||||
# Internal Admin API
|
||||
# put "/users/:id/spam", to: "users#toggle_spam", as: :user_toggle_spam
|
||||
# delete "/users/:id/spam", to: "users#toggle_spam", as: :user_toggle_spam
|
||||
|
||||
# The priority is based upon order of creation: first created -> highest priority.
|
||||
# See how all your routes lay out with "rake routes".
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue