Expose deletion of users through the UI

This supports soft-deleting users

refs FOO-921

test plan:
- Create a user and navigate to their profile page
- Click the  Delete from ALL accounts button
- After a confirmation dialog, the user should be deleted

Change-Id: I3a1a4c07db68d3d188319c31daf278c669ba5c14
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/256529
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Simon Williams <simon@instructure.com>
QA-Review: Simon Williams <simon@instructure.com>
Product-Review: Simon Williams <simon@instructure.com>
This commit is contained in:
Jacob Burroughs 2021-01-12 07:49:00 -06:00
parent dafe4ee71c
commit 67f8d5be1f
5 changed files with 55 additions and 11 deletions

View File

@ -2524,6 +2524,14 @@ class UsersController < ApplicationController
end
end
def destroy
user = api_find(User, params[:id])
if user && authorized_action(@domain_root_account, @current_user, :manage_site_settings)
user.destroy
render json: { status: "ok" }
end
end
protected
def teacher_activity_report(teacher, course, student_enrollments)

View File

@ -95,8 +95,13 @@
<a href="<%= account_confirm_delete_user_url(root_account.id, @user.id) %>"><%= t('delete_from_account', 'Delete from %{account}', :account => root_account.name) %></a>
<% end %>
<% if @domain_root_account.grants_right?(@current_user, :manage_site_settings) %>
<%= "|" unless first %><% first = false %>
<a class="destroy_user_link" href="<%= api_v1_destroy_user_url(@user) %>"><%= t('Delete from ALL accounts') %></a>
<% end %>
<% if Canvas::CacheRegister.enabled? && @domain_root_account.grants_right?(@current_user, :manage_site_settings) %>
<%= "|" unless first %>
<%= "|" unless first %><% first = false %>
<a class="clear_user_cache_link" href="<%= api_v1_clear_cache_url(@user) %>"><%= t('Clear User Cache') %></a>
<% end %>
</td>

View File

@ -45,6 +45,11 @@
</div>
</div>
<% end %>
<% if @user.workflow_state == 'deleted' %>
<div class="alert alert-danger">
<i class="icon-warning" aria-hidden="true"></i> <%= t("This user has been deleted") %>
</div>
<% end %>
<h2><%= @user.short_name %> <% if @user.pronouns %><i>(<%= @user.pronouns %>)</i><% end %></h2>
<style type="text/css" media="screen">

View File

@ -1391,6 +1391,7 @@ CanvasRails::Application.routes.draw do
get 'users/:id', action: :api_show
put 'users/:id', action: :update
delete 'users/:id', action: :destroy, as: 'destroy_user'
post 'users/:user_id/files', action: :create_file
get 'users/:user_id/files', controller: :files, action: :api_index, as: 'user_files'

View File

@ -26,6 +26,8 @@ import 'compiled/jquery/fixDialogButtons'
import 'compiled/jquery.rails_flash_notifications'
import './jquery.templateData'
import {showConfirmationDialog} from 'jsx/shared/ConfirmationDialog'
$(document).ready(function() {
$('#name_and_email').delegate('.edit_user_link', 'click', event => {
event.preventDefault()
@ -37,7 +39,7 @@ $(document).ready(function() {
.select()
})
$('#edit_student_form').formSubmit({
beforeSubmit(data) {
beforeSubmit(_data) {
$(this)
.find('button')
.attr('disabled', true)
@ -53,7 +55,7 @@ $(document).ready(function() {
$('#name_and_email .user_details').fillTemplateData({data})
$('#edit_student_dialog').dialog('close')
},
error(data) {
error(_data) {
$(this)
.find('button')
.attr('disabled', false)
@ -69,15 +71,16 @@ $(document).ready(function() {
$('#edit_student_dialog .cancel_button').click(() => {
$('#edit_student_dialog').dialog('close')
})
$('.remove_avatar_picture_link').click(function(event) {
$('.remove_avatar_picture_link').click(async function(event) {
event.preventDefault()
const $link = $(this)
const result = confirm(
I18n.t(
const result = await showConfirmationDialog({
label: I18n.t('Confirm Removal'),
body: I18n.t(
'confirms.remove_profile_picture',
"Are you sure you want to remove this user's profile picture?"
)
)
})
if (!result) {
return
}
@ -86,14 +89,14 @@ $(document).ready(function() {
$link.attr('href'),
'PUT',
{'avatar[state]': 'none'},
data => {
_data => {
$link
.parents('tr')
.find('.avatar_image')
.remove()
$link.remove()
},
data => {
_data => {
$link.text(
I18n.t('errors.failed_to_remove_image', 'Failed to remove the image, please try again')
)
@ -109,11 +112,11 @@ $(document).ready(function() {
$link.attr('href'),
'POST',
{},
data => {
_data => {
$link.after(htmlEscape(I18n.t('notices.image_reported', 'This image has been reported')))
$link.remove()
},
data => {
_data => {
$link.text(
I18n.t('errors.failed_to_report_image', 'Failed to report the image, please try again')
)
@ -135,4 +138,26 @@ $(document).ready(function() {
}
)
})
$('.destroy_user_link').click(async function(event) {
event.preventDefault()
const result = await showConfirmationDialog({
label: I18n.t('Confirm Deletion'),
body: I18n.t('Are you sure you want to permanently remove the user from ALL accounts')
})
if (!result) {
return
}
const $link = $(this)
$.ajaxJSON(
$link.attr('href'),
'DELETE',
{},
_data => {
$.flashMessage(I18n.t('User removed successfully'))
},
_data => {
$.flashMessage(I18n.t('Failed to remove user'))
}
)
})
})