Feature: Delete user, Fix: Create default entity (00000000-0000-0000-0000-000000000000) with table

This commit is contained in:
Keanu D?lle 2020-11-06 20:39:15 +01:00
parent 8c9722855f
commit b125343547
11 changed files with 189 additions and 7 deletions

View File

@ -4,4 +4,6 @@ create table entities
entity_id uuid default uuid_generate_v1() not null,
constraint entities_pk
primary key (entity_id)
);
);
INSERT INTO entities (entity_id) VALUES ('00000000-0000-0000-0000-000000000000');

View File

@ -0,0 +1,54 @@
$( document ).ready(function() {
$(".delete_member_button").on("click", MemberSelection.delete_button_listener);
//Searchbar typing events:
$("#member_delete_modal_name_confirmation").on("keyup", MemberSelection.name_confirmation_typing);
$("#member_delete_modal_name_confirmation").bind("paste", MemberSelection.name_confirmation_typing);
$("#member_delete_modal_name_confirmation").bind("cut", MemberSelection.name_confirmation_typing);
$("#member_delete_modal_delete_button").on("click", MemberSelection.delete_member);
});
var name = "";
var uuid = "";
MemberSelection = ( function() {
var delete_button_listener = function(){
$("#member_delete_modal_delete_button").prop("disabled", true);
$("#member_delete_modal_member_name").html("");
$("#member_delete_modal_name_confirmation").val("");
$("#member_delete_modal_name_confirmation").attr("placeholder", "");
name = $(this).data("member-firstname")+" "+$(this).data("member-lastname");
uuid = $(this).data("member-id");
$("#member_delete_modal_member_name").html(name);
$("#member_delete_modal_name_confirmation").attr("placeholder", name);
$("#member_delete_modal").modal();
};
var delete_member = function(){
$.ajax({
url: '/api/members/'+uuid,
type: 'DELETE',
contentType: 'application/json',
success: function(data) {
if(is_ok(data)) {
location.reload();
}
},
timeout: 3000,
error: function() {
alert("Verbindung zum Server unterbrochen!");
}
});
};
var name_confirmation_typing = function(){
if($("#member_delete_modal_name_confirmation").val() === name){
$('#member_delete_modal_delete_button').removeClass('disabled');
$('#member_delete_modal_delete_button').prop("disabled", false);
}
};
return{
delete_button_listener: delete_button_listener,
name_confirmation_typing: name_confirmation_typing,
delete_member: delete_member,
};
})();

View File

@ -11,14 +11,15 @@ $( document ).ready(function() {
//Remove current searchbar value on click
$("#searchbar").on("click", Searchbar.searchbar_onclick);
//Searchbar typing events:
$("#searchbar").on("keypress", Searchbar.searchbar_typing);
/*$("#searchbar").on("keypress", Searchbar.searchbar_typing);
$("#searchbar").on("keyup", function(e){
if (e.keyCode == 8 || e.keyCode == 46) { //backspace and delete key
Searchbar.searchbar_typing();
}else{
e.preventDefault();
}
});
});*/
$("#searchbar").on("keyup", Searchbar.searchbar_typing);
$("#searchbar").bind("paste", Searchbar.searchbar_typing);
$("#searchbar").bind("cut", Searchbar.searchbar_typing);
$("#searchbar").on("mouseenter", function (){

View File

@ -0,0 +1,21 @@
<div class="modal fade" id="member_delete_modal" tabindex="-1" role="dialog" aria-labelledby="member_delete_modal_label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="member_delete_modal_label">Mitglied löschen</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<b>Soll das Mitglied <span id="member_delete_modal_member_name"></span> UNWIDERRUFLICH gelöscht werden?</b>
<p>Zur Bestätigung den vollständigen Namen eintragen:</p>
<input type="text" class="form-control" id="member_delete_modal_name_confirmation">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" id="member_delete_modal_abort_button" data-dismiss="modal">Abbrechen</button>
<button type="button" class="btn btn-danger" id="member_delete_modal_delete_button">Mitglied löschen</button>
</div>
</div>
</div>
</div>

View File

@ -1,4 +1,5 @@
{{> header }}
{{> delete-member-modal}}
<div class="container-fluid">
<div class="row">
<div class="wrapper">
@ -91,12 +92,12 @@
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456l-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/>
<path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z"/>
</svg></a>{{/if}}{{#if delete}}
<a href="/portal/mm/profile?action=delete&id={{member.entity_id}}">
<button class="iconbutton delete_member_button" data-member-id="{{member.entity_id}}" data-member-firstname="{{member.firstname}}" data-member-lastname="{{member.lastname}}">
<svg width="1.5em" height="1.5em" viewBox="0 0 16 16" class="bi bi-trash" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4L4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
</svg>
</a>{{/if}}
</button>{{/if}}
</td>
</tr>
{{/each}}

View File

@ -123,3 +123,14 @@ pub fn get_member_search_result_by_name(
Ok(members)
}
pub fn delete_entity(
settings: &State<Settings>,
entity_id_to_delete: uuid::Uuid,
) -> Result<usize, diesel::result::Error> {
use crate::schema::entities::dsl::*;
let connection = establish_connection(&settings);
diesel::delete(entities.filter(entity_id.eq(entity_id_to_delete))).execute(&connection)
}

View File

@ -70,6 +70,7 @@ fn main() {
modules::api::member_management::view::member_communication::api_member_remove_communication_target,
modules::api::members::get_member::api_members_get,
modules::api::members::get_member::api_members_search_name,
modules::api::members::delete_member::api_members_delete,
],
)
.mount("/css", StaticFiles::from("resources/css"))

View File

@ -0,0 +1,61 @@
use crate::database::controller::api_members::delete_entity;
use crate::database::controller::groups::get_groups_for_member;
use crate::helper::check_access::check_access;
use crate::helper::session_cookies::model::SessionCookie;
use crate::helper::settings::Settings;
use crate::modules::api::member_management::controller::parser::{
parse_entity_id, parse_member_cookie,
};
use crate::modules::api::members::get_member::MemberSearchResult;
use crate::modules::api::model::api_outcome::{ApiError, ApiErrorWrapper};
use rocket::State;
use rocket_contrib::json::Json;
#[delete("/api/members/<entity_id>", format = "json")]
pub fn api_members_delete(
cookie: SessionCookie,
settings: State<Settings>,
entity_id: String,
) -> Result<(), Json<ApiErrorWrapper>> {
let caller = parse_member_cookie(cookie.member)?;
let member_id = parse_entity_id(entity_id)?;
let groups = get_groups_for_member(&settings, member_id);
if !check_access(
&settings,
member_id,
groups,
caller.entity_id,
"modules.member_management.profile.delete".to_string(),
) {
return Err(Json(
ApiError::new(401, "Keine Berechtigung Mitglied zu löschen!".to_string()).to_wrapper(),
));
}
match delete_entity(&settings, member_id) {
Ok(result) => {
if result == 1 {
Ok(())
} else {
Err(Json(
ApiError::new(500, "Es ist ein Datenbankfehler aufgetreten!".to_string())
.to_wrapper(),
))
}
}
Err(e) => match e {
diesel::result::Error::NotFound => Err(Json(
ApiError::new(
404,
"Das angeforderte Mitglied konnte nicht gefunden werden!".to_string(),
)
.to_wrapper(),
)),
_ => Err(Json(
ApiError::new(500, "Es ist ein Datenbankfehler aufgetreten!".to_string())
.to_wrapper(),
)),
},
}
}

View File

@ -1 +1,2 @@
pub mod delete_member;
pub mod get_member;

View File

@ -2,7 +2,7 @@ use crate::database::controller::groups::get_groups;
use crate::database::controller::members::get_members;
use crate::helper::check_access::check_access_legacy;
use crate::helper::settings::Settings;
use crate::helper::sitebuilder::model::general::{Footer, Header, Stylesheet};
use crate::helper::sitebuilder::model::general::{Footer, Header, Script, Stylesheet};
use crate::helper::sitebuilder::model::sidebar::Sidebar;
use crate::modules::member_management::model::member::{Member, MemberWithAccess};
use crate::modules::member_management::model::member_module::MemberModuleSelection;
@ -20,7 +20,11 @@ pub fn get_selection_context(
path: "/css/errms.css".to_string(),
}],
};
let footer = Footer { scripts: vec![] };
let footer = Footer {
scripts: vec![Script {
path: "/js/member_management_selection.js".to_string(),
}],
};
let mut sidebar = Sidebar::new(member.clone());
sidebar.member_management.active = true;

View File

@ -1,5 +1,6 @@
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
addresses (id) {
id -> Uuid,
@ -14,6 +15,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
addresses_entities (address_id, entitiy_id) {
address_id -> Uuid,
@ -23,6 +25,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
buildings (entity_id) {
entity_id -> Uuid,
@ -33,6 +36,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
communication_targets (target_id) {
target_id -> Uuid,
@ -45,6 +49,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
communication_types (type_id) {
type_id -> Uuid,
@ -54,6 +59,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
entities (entity_id) {
entity_id -> Uuid,
@ -62,6 +68,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
groups (entity_id) {
entity_id -> Uuid,
@ -72,6 +79,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
groups_entities (group_id, entity_id) {
group_id -> Uuid,
@ -80,6 +88,9 @@ table! {
}
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
license_categories (name) {
name -> Text,
description -> Nullable<Text>,
@ -88,6 +99,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
licenses_members (member_id, license_name) {
member_id -> Uuid,
@ -98,6 +110,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
members (entity_id) {
entity_id -> Uuid,
@ -119,6 +132,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
members_roles (member_id, role_id) {
member_id -> Uuid,
@ -128,6 +142,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
permissions (permission) {
permission -> Text,
@ -137,6 +152,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
qualification_categories (id) {
id -> Uuid,
@ -147,6 +163,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
qualifications (id) {
id -> Uuid,
@ -158,6 +175,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
qualifications_members (member_id, qualification_id) {
member_id -> Uuid,
@ -167,6 +185,8 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
roles (id) {
id -> Text,
description -> Nullable<Text>,
@ -175,6 +195,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
roles_permissions (role_permission_id) {
role_id -> Text,
@ -185,6 +206,8 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
roles_permissions_context (role_permission_id, entity) {
role_permission_id -> Uuid,
entity -> Uuid,
@ -193,6 +216,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
users (id) {
id -> Uuid,
@ -203,6 +227,7 @@ table! {
table! {
use diesel::sql_types::*;
use diesel_geometry::sql_types::*;
vehicles (entity_id) {
entity_id -> Uuid,