docbrown/app/controllers/admin/users_controller.rb
Julianna Tetreault 71b35f28a0
Remove Roles via Admin (#12582) [deploy]
* Add the ability to remove a role from a non-super_admin in Admin::UsersController
 - Adds a #destroy action to the Admin::UsersController
 - Adds a destroy route for the action

* Add a removal button to non-super_admin roles on admin user pages
  - Pulls Current Roles out of _activity and into own partial
  - Adds a _current_roles partial to /admin/users/show
  - Adds REMOVE buttons to non-super_admin roles
  - Conditionally renders REMOVE buttons for certain roles only

* Add tests around the removal of roles to users_manage_spec

* Adjust formatting of link_to in _current_roles.html.erb

* Use :aggregate_failures in role-related tests in users_manage_spec.rb

* Refactors Admin::UsersController#destroy and role params

* Update admin/users_spec.rb to take into account _current_roles partial

* Replace REMOVE text with X on role removal buttons

* Add additional elsif to handle single_resource_admin removal
  - Adds resource_type params to Admin::UsersController
  - Adds elsif to handle removal of single_resource_admin roles
  - Adds resource_type to the removal button in _current_roles
  - Adds a spec around removing single_resource_admin roles

* Add .constantize to resource_type in Admin::UsersController

* Move .constantize to resource_type arg rather than params in #destroy

* Use .safe_constantize rather than .constantize for params[:resource_type]

* Remove .safe_constantize from params and onto inline var instead

* Add nil check to removal of :single_resource_admin role in #destroy

* Update users_manage_spec.rb to remove proper role in test

* Add resource_name to current user and super admin _current_roles list

* Add additional test around removing :single_resource_admin role
2021-02-16 10:50:10 -07:00

211 lines
7.2 KiB
Ruby

module Admin
class UsersController < Admin::ApplicationController
layout "admin"
using StringToBoolean
after_action only: %i[update user_status banish full_delete merge] do
Audit::Logger.log(:moderator, current_user, params.dup)
end
def index
@users = Admin::UsersQuery.call(
options: params.permit(:role, :search),
).page(params[:page]).per(50)
end
def edit
@user = User.find(params[:id])
@notes = @user.notes.order(created_at: :desc).limit(10).load
set_feedback_messages
set_related_reactions
end
def show
@user = User.find(params[:id])
@organizations = @user.organizations.order(:name)
@notes = @user.notes.order(created_at: :desc).limit(10)
@organization_memberships = @user.organization_memberships
.joins(:organization)
.order("organizations.name" => :asc)
.includes(:organization)
@last_email_verification_date = @user.email_authorizations
.where.not(verified_at: nil)
.order(created_at: :desc).first&.verified_at || "Never"
end
def update
@user = User.find(params[:id])
Credits::Manage.call(@user, user_params)
add_note if user_params[:new_note]
redirect_to "/admin/users/#{params[:id]}"
end
def destroy
role = params[:role].to_sym
resource_type = params[:resource_type]
if role == :super_admin
flash[:danger] = "Super Admin roles cannot be removed."
redirect_to "/admin/users/#{params[:id]}/edit" and return
end
@user = User.find(params[:user_id])
if @user.id == current_user.id
flash[:danger] = "Admins cannot remove roles from themselves."
elsif role == :single_resource_admin && !resource_type.safe_constantize.nil?
User.find(params[:user_id]).remove_role(role, resource_type.safe_constantize)
flash[:success] = "Role: #{role.to_s.humanize.titlecase} has been successfully removed from the user!"
elsif User.find(params[:user_id]).remove_role(role)
flash[:success] = "Role: #{role.to_s.humanize.titlecase} has been successfully removed from the user!"
else
flash[:danger] = "There was an issue removing this role. Please try again."
end
redirect_to edit_admin_user_path(@user.id)
end
def user_status
@user = User.find(params[:id])
begin
Moderator::ManageActivityAndRoles.handle_user_roles(admin: current_user, user: @user, user_params: user_params)
flash[:success] = "User has been updated"
rescue StandardError => e
flash[:danger] = e.message
end
redirect_to "/admin/users/#{@user.id}/edit"
end
def export_data
user = User.find(params[:id])
send_to_admin = params[:send_to_admin].to_boolean
if send_to_admin
email = SiteConfig.email_addresses[:contact]
receiver = "admin"
else
email = user.email
receiver = "user"
end
ExportContentWorker.perform_async(user.id, email)
flash[:success] = "Data exported to the #{receiver}. The job will complete momentarily."
redirect_to edit_admin_user_path(user.id)
end
def banish
Moderator::BanishUserWorker.perform_async(current_user.id, params[:id].to_i)
flash[:success] = "This user is being banished in the background. The job will complete soon."
redirect_to "/admin/users/#{params[:id]}/edit"
end
def full_delete
@user = User.find(params[:id])
begin
Moderator::DeleteUser.call(user: @user)
link = helpers.tag.a("the page", href: admin_users_gdpr_delete_requests_path, data: { "no-instant" => true })
message = "@#{@user.username} (email: #{@user.email.presence || 'no email'}, user_id: #{@user.id}) " \
"has been fully deleted. " \
"If this is a GDPR delete, delete them from Mailchimp & Google Analytics " \
" and confirm on "
flash[:success] = helpers.safe_join([message, link, "."])
rescue StandardError => e
flash[:danger] = e.message
end
redirect_to "/admin/users"
end
def merge
@user = User.find(params[:id])
begin
Moderator::MergeUser.call(admin: current_user, keep_user: @user, delete_user_id: user_params["merge_user_id"])
rescue StandardError => e
flash[:danger] = e.message
end
redirect_to "/admin/users/#{@user.id}/edit"
end
def remove_identity
identity = Identity.find(user_params[:identity_id])
@user = identity.user
begin
identity.destroy
@user.update("#{identity.provider}_username" => nil)
# GitHub repositories are tied with the existence of the GitHub identity
# as we use the user's GitHub token to fetch them from the API.
# We should delete them when a user unlinks their GitHub account.
@user.github_repos.destroy_all if identity.provider.to_sym == :github
flash[:success] = "The #{identity.provider.capitalize} identity was successfully deleted and backed up."
rescue StandardError => e
flash[:danger] = e.message
end
redirect_to "/admin/users/#{@user.id}/edit"
end
def send_email
if NotifyMailer.with(params).user_contact_email.deliver_now
redirect_back(fallback_location: users_path)
else
flash[:danger] = "Email failed to send!"
end
end
def verify_email_ownership
if VerificationMailer.with(user_id: params[:user_id]).account_ownership_verification_email.deliver_now
flash[:success] = "Email Verification Mailer sent!"
redirect_back(fallback_location: admin_users_path)
else
flash[:danger] = "Email failed to send!"
end
end
def unlock_access
@user = User.find(params[:id])
@user.unlock_access!
flash[:success] = "Unlocked User account!"
redirect_to admin_user_path(@user)
end
private
def add_note
Note.create(
author_id: current_user.id,
noteable_id: @user.id,
noteable_type: "User",
reason: "misc_note",
content: user_params[:new_note],
)
end
def set_feedback_messages
@related_reports = FeedbackMessage.where(id: @user.reporter_feedback_messages.ids)
.or(FeedbackMessage.where(id: @user.affected_feedback_messages.ids))
.or(FeedbackMessage.where(id: @user.offender_feedback_messages.ids))
.order(created_at: :desc).limit(15)
end
def set_related_reactions
user_article_ids = @user.articles.ids
user_comment_ids = @user.comments.ids
@related_vomit_reactions = Reaction.where(reactable_type: "Comment", reactable_id: user_comment_ids,
category: "vomit")
.or(Reaction.where(reactable_type: "Article", reactable_id: user_article_ids, category: "vomit"))
.or(Reaction.where(reactable_type: "User", user_id: @user.id, category: "vomit"))
.includes(:reactable)
.order(created_at: :desc).limit(15)
end
def user_params
allowed_params = %i[
new_note note_for_current_role user_status
pro merge_user_id add_credits remove_credits
add_org_credits remove_org_credits
organization_id identity_id
]
params.require(:user).permit(allowed_params)
end
end
end