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
This commit is contained in:
Julianna Tetreault 2021-02-16 10:50:10 -07:00 committed by GitHub
parent 3f02045458
commit 71b35f28a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 101 additions and 16 deletions

View file

@ -40,6 +40,30 @@ module Admin
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

View file

@ -10,17 +10,4 @@
<li><%= @user.badge_achievements_count %> badges</li>
</ul>
</div>
<div class="col-sm-6">
<h2>Current Roles</h2>
<p>(view full history in notes below)</p>
<ul>
<% @user.roles.each do |role| %>
<% if role.name == "banned" %>
<li>suspended</li>
<% else %>
<li><%= role.name %> <em><%= role.resource_name.to_s %></em></li>
<% end %>
<% end %>
</ul>
</div>
</div>

View file

@ -0,0 +1,21 @@
<div class="crayons-card p-6 grid gap-2">
<h2>Current Roles</h2>
<p>(View full history in notes below)</p>
<div class="crayons-card__body">
<ul>
<% @user.roles.each do |role| %>
<% if role.name == "banned" %>
<li>Suspended</li>
<% elsif role.name == "super_admin" || @user.id == current_user.id %>
<li><%= role.name.titlecase %> <em><%= role.resource_name.to_s %></em></li>
<% else %>
<li>
<%= role.name.titlecase %> <em><%= role.resource_name.to_s %></em> &nbsp;
<%= link_to "X", url_for(action: :destroy, user_id: @user.id, role: role.name.to_sym, resource_type: role.resource_type), method: :delete, data: { confirm: "Are you sure?" },
class: "crayons-btn crayons-btn--danger crayons-btn--s lh-base fs-xs" %>
</li>
<% end %>
<% end %>
</ul>
</div>
</div>

View file

@ -14,6 +14,7 @@
</div>
<%= render "activity" %>
<%= render "current_roles" %>
<div class="crayons-card p-6">
<div>

View file

@ -110,7 +110,7 @@ Rails.application.routes.draw do
resources :tags, only: %i[index new create update edit] do
resource :moderator, only: %i[create destroy], module: "tags"
end
resources :users, only: %i[index show edit update] do
resources :users, only: %i[index show edit update destroy] do
resources :email_messages, only: :show
member do

View file

@ -164,6 +164,53 @@ RSpec.describe "Admin::Users", type: :request do
put "/admin/users/#{user.id}", params: { user: { remove_credits: "3" } }
expect(user.credits.size).to eq(2)
end
it "removes non-admin roles from non-super_admin users", :aggregate_failures do
user.add_role(:trusted)
expect do
delete "/admin/users/#{user.id}", params: { user_id: user.id, role: :trusted }
end.to change(user.roles, :count).by(-1)
expect(user.has_role?(:trusted)).to be false
expect(request.flash["success"]).to include("successfully removed from the user!")
end
it "removes the correct resource_admin_role from non-super_admin users", :aggregate_failures do
user.add_role(:single_resource_admin, Comment)
user.add_role(:single_resource_admin, Broadcast)
expect do
delete "/admin/users/#{user.id}",
params: { user_id: user.id, role: :single_resource_admin, resource_type: Comment }
end.to change(user.roles, :count).by(-1)
expect(user.has_role?(:single_resource_admin, Comment)).to be false
expect(user.has_role?(:single_resource_admin, Broadcast)).to be true
expect(request.flash["success"]).to include("successfully removed from the user!")
end
it "does not allow super_admin roles to be removed", :aggregate_failures do
user.add_role(:super_admin)
expect do
delete "/admin/users/#{user.id}", params: { user_id: user.id, role: :super_admin }
end.not_to change(user.roles, :count)
expect(user.has_role?(:super_admin)).to be true
expect(request.flash["danger"]).to include("cannot be removed.")
end
it "does not allow a admins to remove a role from themselves", :aggregate_failures do
super_admin.add_role(:trusted)
expect do
delete "/admin/users/#{super_admin.id}", params: { user_id: super_admin.id, role: :trusted }
end.not_to change(super_admin.roles, :count)
expect(super_admin.has_role?(:trusted)).to be true
expect(request.flash["danger"]).to include("cannot remove roles")
end
end
context "when deleting user" do

View file

@ -34,14 +34,14 @@ RSpec.describe "admin/users", type: :request do
it "only displays limited information about the user" do
user.update_columns(registered: false)
get "/admin/users/#{user.id}"
expect(response.body).not_to include("Current Roles")
expect(response.body).not_to include("Activity")
end
end
context "when a user is registered" do
it "renders the Admin User profile as expected" do
get "/admin/users/#{user.id}"
expect(response.body).to include("Current Roles")
expect(response.body).to include("Activity")
end
end
@ -72,6 +72,11 @@ RSpec.describe "admin/users", type: :request do
expect { get "/admin/users/#{user.id}/edit" }.to raise_error(Pundit::NotAuthorizedError)
end
it "displays the 'Current Roles' section" do
get "/admin/users/#{user.id}/edit"
expect(response.body).to include("Current Roles")
end
it "displays the 'Recent Reactions' section" do
get "/admin/users/#{user.id}/edit"
expect(response.body).to include("Recent Reactions")