diff --git a/static/js/dist/app/users.min.js b/static/js/dist/app/users.min.js
index 6c195c56..7e07194f 100644
--- a/static/js/dist/app/users.min.js
+++ b/static/js/dist/app/users.min.js
@@ -1 +1 @@
-let users=[];const save=e=>{if($("#password").val()!==$("#confirm_password").val())return void modalError("Passwords must match.");let t={username:$("#username").val(),password:$("#password").val(),role:$("#role").val(),password_change_required:$("#force_password_change_checkbox").prop("checked"),account_locked:$("#account_locked_checkbox").prop("checked")};-1!=e?(t.id=e,api.userId.put(t).success((e=>{successFlash("User "+escapeHtml(t.username)+" updated successfully!"),load(),dismiss(),$("#modal").modal("hide")})).error((e=>{modalError(e.responseJSON.message)}))):api.users.post(t).success((e=>{successFlash("User "+escapeHtml(t.username)+" registered successfully!"),load(),dismiss(),$("#modal").modal("hide")})).error((e=>{modalError(e.responseJSON.message)}))},dismiss=()=>{$("#username").val(""),$("#password").val(""),$("#confirm_password").val(""),$("#role").val(""),$("#force_password_change_checkbox").prop("checked",!0),$("#account_locked_checkbox").prop("checked",!1),$("#modal\\.flashes").empty()},edit=e=>{$("#modalSubmit").unbind("click").click((()=>{save(e)})),$("#role").select2(),-1==e?($("#userModalLabel").text("New User"),$("#role").val("user"),$("#role").trigger("change")):($("#userModalLabel").text("Edit User"),api.userId.get(e).success((e=>{$("#username").val(e.username),$("#role").val(e.role.slug),$("#role").trigger("change"),$("#force_password_change_checkbox").prop("checked",e.password_change_required),$("#account_locked_checkbox").prop("checked",e.account_locked)})).error((function(){errorFlash("Error fetching user")})))},deleteUser=e=>{var s=users.find((t=>t.id==e));t&&Swal.fire({title:"Are you sure?",text:"This will delete the account for "+escapeHtml(t.username)+" as well as all of the objects they have created.\n\nThis can't be undone!",type:"warning",animation:!1,showCancelButton:!0,confirmButtonText:"Delete",confirmButtonColor:"#428bca",reverseButtons:!0,allowOutsideClick:!1,preConfirm:function(){return new Promise(((t,s)=>{api.userId.delete(e).success((e=>{t()})).error((e=>{s(e.responseJSON.message)}))})).catch((e=>{Swal.showValidationMessage(e)}))}}).then((function(e){e.value&&Swal.fire("User Deleted!","The user account for "+escapeHtml(t.username)+" and all associated objects have been deleted!","success"),$('button:contains("OK")').on("click",(function(){location.reload()}))}))},impersonate=e=>{var s=users.find((t=>t.id==e));t&&Swal.fire({title:"Are you sure?",html:"You will be logged out of your account and logged in as "+escapeHtml(t.username)+"",type:"warning",animation:!1,showCancelButton:!0,confirmButtonText:"Swap User",confirmButtonColor:"#428bca",reverseButtons:!0,allowOutsideClick:!1}).then((e=>{e.value&&fetch("/impersonate",{method:"post",body:"username="+t.username+"&csrf_token="+encodeURIComponent(csrf_token),headers:{"Content-Type":"application/x-www-form-urlencoded"}}).then((e=>{200==e.status?Swal.fire({title:"Success!",html:"Successfully changed to user "+escapeHtml(t.username)+".",type:"success",showCancelButton:!1,confirmButtonText:"Home",allowOutsideClick:!1}).then((e=>{e.value&&(window.location.href="/")})):Swal.fire({title:"Error!",type:"error",html:"Failed to change to user "+escapeHtml(t.username)+".",showCancelButton:!1})}))}))},load=()=>{$("#userTable").hide(),$("#loading").show(),api.users.get().success((e=>{users=e,$("#loading").hide(),$("#userTable").show();let t=$("#userTable").DataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]});t.clear(),userRows=[],$.each(users,((e,t)=>{lastlogin="Never","0001-01-01T00:00:00Z"!=t.last_login&&(lastlogin=moment(t.last_login).format("MMMM Do YYYY, h:mm:ss a")),userRows.push([escapeHtml(t.username),escapeHtml(t.role.name),lastlogin,"
"])})),t.rows.add(userRows).draw()})).error((()=>{errorFlash("Error fetching users")}))};$(document).ready((function(){load(),$("#modal").on("hide.bs.modal",(function(){dismiss()})),$.fn.select2.defaults.set("width","100%"),$.fn.select2.defaults.set("dropdownParent",$("#role-select")),$.fn.select2.defaults.set("theme","bootstrap"),$.fn.select2.defaults.set("sorter",(function(e){return e.sort((function(e,t){return e.text.toLowerCase()>t.text.toLowerCase()?1:e.text.toLowerCase()e.id==t)))&&Swal.fire({title:"Are you sure?",text:"This will delete the account for "+escapeHtml(s.username)+" as well as all of the objects they have created.\n\nThis can't be undone!",type:"warning",animation:!1,showCancelButton:!0,confirmButtonText:"Delete",confirmButtonColor:"#428bca",reverseButtons:!0,allowOutsideClick:!1,preConfirm:function(){return new Promise(((e,s)=>{api.userId.delete(t).success((t=>{e()})).error((e=>{s(e.responseJSON.message)}))})).catch((e=>{Swal.showValidationMessage(e)}))}}).then((function(e){e.value&&Swal.fire("User Deleted!","The user account for "+escapeHtml(s.username)+" and all associated objects have been deleted!","success"),$('button:contains("OK")').on("click",(function(){location.reload()}))}))})),$("#userTable").on("click",".impersonate_button",(function(e){var t,s;t=$(this).attr("data-user-id"),(s=users.find((e=>e.id==t)))&&Swal.fire({title:"Are you sure?",html:"You will be logged out of your account and logged in as "+escapeHtml(s.username)+"",type:"warning",animation:!1,showCancelButton:!0,confirmButtonText:"Swap User",confirmButtonColor:"#428bca",reverseButtons:!0,allowOutsideClick:!1}).then((e=>{e.value&&fetch("/impersonate",{method:"post",body:"username="+s.username+"&csrf_token="+encodeURIComponent(csrf_token),headers:{"Content-Type":"application/x-www-form-urlencoded"}}).then((e=>{200==e.status?Swal.fire({title:"Success!",html:"Successfully changed to user "+escapeHtml(s.username)+".",type:"success",showCancelButton:!1,confirmButtonText:"Home",allowOutsideClick:!1}).then((e=>{e.value&&(window.location.href="/")})):Swal.fire({title:"Error!",type:"error",html:"Failed to change to user "+escapeHtml(s.username)+".",showCancelButton:!1})}))}))}))}));
\ No newline at end of file
+let users=[];const save=id=>{if($("#password").val()!==$("#confirm_password").val()){modalError("Passwords must match.");return}let user={username:$("#username").val(),password:$("#password").val(),role:$("#role").val(),password_change_required:$("#force_password_change_checkbox").prop("checked"),account_locked:$("#account_locked_checkbox").prop("checked")};if(id!=-1){user.id=id;api.userId.put(user).success(data=>{successFlash("User "+escapeHtml(user.username)+" updated successfully!");load();dismiss();$("#modal").modal("hide")}).error(data=>{modalError(data.responseJSON.message)})}else{api.users.post(user).success(data=>{successFlash("User "+escapeHtml(user.username)+" registered successfully!");load();dismiss();$("#modal").modal("hide")}).error(data=>{modalError(data.responseJSON.message)})}};const dismiss=()=>{$("#username").val("");$("#password").val("");$("#confirm_password").val("");$("#role").val("");$("#force_password_change_checkbox").prop("checked",true);$("#account_locked_checkbox").prop("checked",false);$("#modal\\.flashes").empty()};const edit=id=>{$("#username").attr("disabled",false);$("#modalSubmit").unbind("click").click(()=>{save(id)});$("#role").select2();if(id==-1){$("#userModalLabel").text("New User");$("#role").val("user");$("#role").trigger("change")}else{$("#userModalLabel").text("Edit User");api.userId.get(id).success(user=>{$("#username").val(user.username);$("#role").val(user.role.slug);$("#role").trigger("change");$("#force_password_change_checkbox").prop("checked",user.password_change_required);$("#account_locked_checkbox").prop("checked",user.account_locked);if(user.username=="admin"){$("#username").attr("disabled",true)}}).error(function(){errorFlash("Error fetching user")})}};const deleteUser=id=>{var user=users.find(x=>x.id==id);if(!user){return}Swal.fire({title:"Are you sure?",text:"This will delete the account for "+escapeHtml(user.username)+" as well as all of the objects they have created.\n\nThis can't be undone!",type:"warning",animation:false,showCancelButton:true,confirmButtonText:"Delete",confirmButtonColor:"#428bca",reverseButtons:true,allowOutsideClick:false,preConfirm:function(){return new Promise((resolve,reject)=>{api.userId.delete(id).success(msg=>{resolve()}).error(data=>{reject(data.responseJSON.message)})}).catch(error=>{Swal.showValidationMessage(error)})}}).then(function(result){if(result.value){Swal.fire("User Deleted!","The user account for "+escapeHtml(user.username)+" and all associated objects have been deleted!","success")}$('button:contains("OK")').on("click",function(){location.reload()})})};const impersonate=id=>{var user=users.find(x=>x.id==id);if(!user){return}Swal.fire({title:"Are you sure?",html:"You will be logged out of your account and logged in as "+escapeHtml(user.username)+"",type:"warning",animation:false,showCancelButton:true,confirmButtonText:"Swap User",confirmButtonColor:"#428bca",reverseButtons:true,allowOutsideClick:false}).then(result=>{if(result.value){fetch("/impersonate",{method:"post",body:"username="+user.username+"&csrf_token="+encodeURIComponent(csrf_token),headers:{"Content-Type":"application/x-www-form-urlencoded"}}).then(response=>{if(response.status==200){Swal.fire({title:"Success!",html:"Successfully changed to user "+escapeHtml(user.username)+".",type:"success",showCancelButton:false,confirmButtonText:"Home",allowOutsideClick:false}).then(result=>{if(result.value){window.location.href="/"}})}else{Swal.fire({title:"Error!",type:"error",html:"Failed to change to user "+escapeHtml(user.username)+".",showCancelButton:false})}})}})};const load=()=>{$("#userTable").hide();$("#loading").show();api.users.get().success(us=>{users=us;$("#loading").hide();$("#userTable").show();let userTable=$("#userTable").DataTable({destroy:true,columnDefs:[{orderable:false,targets:"no-sort"}]});userTable.clear();userRows=[];$.each(users,(i,user)=>{lastlogin="Never";if(user.last_login!="0001-01-01T00:00:00Z"){lastlogin=moment(user.last_login).format("MMMM Do YYYY, h:mm:ss a")}userRows.push([escapeHtml(user.username),escapeHtml(user.role.name),lastlogin,"