rbac build
This commit is contained in:
@@ -1483,7 +1483,7 @@ window.addEventListener('resize', () => {
|
||||
},
|
||||
refresh(){ applyFilters(); render(); },
|
||||
clearData() { data = [] },
|
||||
source(newData) { data = []; this.addData(newData); },
|
||||
source(newData) { data = []; this.addData(newData); this.refresh(); },
|
||||
prepareData() { prepareData(); }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,46 +1,176 @@
|
||||
function test() {
|
||||
function createInput({ id, placeholder }) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
input.id = id;
|
||||
input.style.width = 'calc(100% - 30px)';
|
||||
input.placeholder = placeholder;
|
||||
input.required = true;
|
||||
return input;
|
||||
}
|
||||
|
||||
const container = document.createElement('div');
|
||||
container.id = 'rbacAuthCreation';
|
||||
|
||||
container.append(
|
||||
createInput({ id: 'rbacAuthsAMAccountName', placeholder: 'sAMAccountName <Vorname.Nachname>' }),
|
||||
createInput({ id: 'rbacAuthsMail', placeholder: 'E-Mail' }),
|
||||
createInput({ id: 'rbacAuthsSn', placeholder: 'Vorname' }),
|
||||
createInput({ id: 'rbacAuthsGivenName', placeholder: 'Nachname' })
|
||||
);
|
||||
|
||||
feedbox({
|
||||
title: `<span>Erstelle eine neue Authentifizierung</span>`,
|
||||
message: container.outerHTML,
|
||||
buttons: {
|
||||
cancel: {
|
||||
text: 'Abbrechen'
|
||||
},
|
||||
yes: {
|
||||
text: '<b>Erstellen</b>',
|
||||
onClick: () => {
|
||||
fetch('/api/rbac/auths/create', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
sAMAccountName: document.getElementById('rbacAuthsAMAccountName').value,
|
||||
mail: document.getElementById('rbacAuthsMail').value,
|
||||
sn: document.getElementById('rbacAuthsSn').value,
|
||||
givenName: document.getElementById('rbacAuthsGivenName').value
|
||||
})
|
||||
})
|
||||
const vt = virtualTable({
|
||||
tableEl: document.querySelector('#rbacUsersTable'),
|
||||
data: [],
|
||||
rowHeight: 20,
|
||||
buffer: 5,
|
||||
groupKey: 'ObjectSourceName', // optional zum Gruppieren
|
||||
rowKey: 'ObjectGUID',
|
||||
filterConfig: {
|
||||
exceptedColumns: ['Status_ID', 'Anhänge'],
|
||||
columnModes: {
|
||||
ID: 'text', Status: 'dropdown', Objekt: 'text', Priorität: 'dropdown',
|
||||
Erstelldatum: 'text', Gewerk: 'dropdown', Typ: 'dropdown',
|
||||
Bedarfsmelder: 'text', Bearbeiter: 'text', Genehmiger: 'text',
|
||||
Status: 'dropdown'
|
||||
}
|
||||
},
|
||||
customRender: (row, tr) => {
|
||||
|
||||
createTd(tr,
|
||||
`<button class="redbutton"
|
||||
${row['ObjectGUID'] === '00000000-0000-0000-0000-000000000001' ?
|
||||
'disabled data-tooltip="Der Administrator kann nicht gelöscht werden"' :
|
||||
''
|
||||
}>X</button>`, {
|
||||
styles: {
|
||||
'position': 'sticky',
|
||||
'left': '0px',
|
||||
'width': '20px',
|
||||
'z-index': '2'
|
||||
}, classes: [
|
||||
'text-align:left'
|
||||
], onclick: () => {
|
||||
sendUserEvent('RBAC', `Benutzer ${row['sn'][0].toUpperCase() + row['sn'].slice(1)}, ${row['givenName'][0].toUpperCase() + row['givenName'].slice(1)} gelöscht`, null, 3);
|
||||
}
|
||||
});
|
||||
|
||||
createTd(tr, row['ObjectGUID'], { classes: [ 'text-align:left' ], styles: { 'max-width': '100px' }, attributes: { 'data-tooltip': row['ObjectGUID'] } });
|
||||
createTd(tr, row['sAMAccountName'], { classes: [ 'text-align:left' ], attributes: { 'data-tooltip': row['sAMAccountName'] } });
|
||||
createTd(tr, row['sn'], { classes: [ 'text-align:left' ], attributes: { 'data-tooltip': row['sn'] } });
|
||||
createTd(tr, row['givenName'], { classes: [ 'text-align:left' ], attributes: { 'data-tooltip': row['givenName'] } });
|
||||
createTd(tr, row['mail'], { classes: [ 'text-align:left' ], attributes: { 'data-tooltip': row['mail'] } });
|
||||
createTd(tr, row['active'], { classes: [ 'text-align:center' ] });
|
||||
createTd(tr, row['online'], { classes: [ 'text-align:center' ] });
|
||||
createTd(tr, row['RoleCount'], { classes: [ 'text-align:center' ] });
|
||||
createTd(tr, row['GroupCount'], { classes: [ 'text-align:center' ] });
|
||||
createTd(tr, row['ObjectSourceName'], { classes: [ 'text-align:right' ] });
|
||||
}
|
||||
},
|
||||
lock: true
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
async function api(url, method = 'GET', body) {
|
||||
const res = await fetch(url, {
|
||||
method,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: body ? JSON.stringify(body) : undefined
|
||||
});
|
||||
|
||||
return res.json();
|
||||
}
|
||||
|
||||
async function createUser() {
|
||||
const name = document.getElementById('newUserName').value;
|
||||
const sn = name.split('.')[1];
|
||||
const givenName = name.split('.')[0];
|
||||
const mail = `${name}@test.com`;
|
||||
|
||||
const user = await api('/api/rbac/auth/create', 'POST', {
|
||||
sAMAccountName: name,
|
||||
mail: mail,
|
||||
sn: sn[0].toUpperCase() + sn.slice(1),
|
||||
givenName: givenName[0].toUpperCase() + givenName.slice(1)
|
||||
});
|
||||
if(user) {
|
||||
sendUserEvent('RBAC', `Benutzer ${sn[0].toUpperCase() + sn.slice(1)}, ${givenName[0].toUpperCase() + givenName.slice(1)} angelegt`, null, 0);
|
||||
loadUsers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function loadUsers() {
|
||||
try {
|
||||
const users = await api('/api/rbac/auth/get', 'POST');
|
||||
if(users) {
|
||||
vt.source(users);
|
||||
return;
|
||||
}
|
||||
sendUserEvent('RBAC', 'Benutzer konnten nicht geladen', null, 4);
|
||||
} catch(err) {
|
||||
writeEventLog(4, 'RBAC', err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function createGroup() {
|
||||
const name = document.getElementById('newGroupName').value;
|
||||
const group = await api('/api/rbac/group/create', 'POST', {
|
||||
name
|
||||
});
|
||||
if(group) {
|
||||
sendUserEvent('RBAC', `Gruppe ${name} angelegt`, null, 0);
|
||||
loadGroups();
|
||||
}
|
||||
}
|
||||
// HIER WEITER - GRUPPEN KARTEN MÜSSEN HÜBSCHER WERDEN.
|
||||
// BENUTZER UND GRUPPEN KÖNNEN NOCH NICHT GELÖSCHT WERDEN.
|
||||
// GRUPPEN AUCH OBJECTSOURCE_ID 1?
|
||||
async function loadGroups() {
|
||||
try {
|
||||
const rbacGroupContainer = document.getElementById('rbacGroupContainer');
|
||||
rbacGroupContainer.innerHTML = '';
|
||||
const groups = await api('/api/rbac/group/get', 'POST');
|
||||
if(groups) {
|
||||
let fragment = document.createDocumentFragment();
|
||||
groups.forEach(group => {
|
||||
const section = document.createElement('section');
|
||||
section.innerHTML = `<span>${group.Name}</span><div class="removeButton" onclick="this.parentNode.remove()">X</div>`;
|
||||
section.dataset.tooltip = group.Name;
|
||||
fragment.appendChild(section);
|
||||
});
|
||||
rbacGroupContainer.innerHTML = '';
|
||||
rbacGroupContainer.appendChild(fragment);
|
||||
return;
|
||||
}
|
||||
sendUserEvent('RBAC', 'Gruppen konnten nicht geladen', null, 4);
|
||||
} catch(err) {
|
||||
writeEventLog(4, 'RBAC', err);
|
||||
}
|
||||
}
|
||||
|
||||
loadUsers();
|
||||
loadGroups();
|
||||
|
||||
async function createRole() {
|
||||
const name = document.getElementById('newRoleName').value;
|
||||
|
||||
await api('/api/role', 'POST', {
|
||||
name
|
||||
});
|
||||
|
||||
loadRoles();
|
||||
}
|
||||
|
||||
async function loadRoles() {
|
||||
document.getElementById('roleList').innerHTML = 'Reload roles...';
|
||||
}
|
||||
|
||||
|
||||
async function createPermission() {
|
||||
const scope = document.getElementById('permScope').value;
|
||||
const resource = document.getElementById('permResource').value;
|
||||
const action = document.getElementById('permAction').value;
|
||||
|
||||
await api('/permission', 'POST', {
|
||||
scope,
|
||||
resource,
|
||||
action
|
||||
});
|
||||
|
||||
alert('Permission created');
|
||||
}
|
||||
|
||||
|
||||
async function addUserToGroup(authId, groupId) {
|
||||
await api('/api/rbac/group/add-user', 'POST', {
|
||||
authId,
|
||||
groupId
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async function addPermissionToRole(roleId, permissionId) {
|
||||
await api('/role/add-permission', 'POST', {
|
||||
roleId,
|
||||
permissionId
|
||||
});
|
||||
}
|
||||
@@ -18,7 +18,9 @@ input.width\:25px { width:25px; }
|
||||
*::placeholder, input[id="sAMAccountName"] { font-style:italic; font-weight:100; letter-spacing:3px; }
|
||||
|
||||
html, button { font-size: var(--fontSize); font-family: var(--fontFamily); }
|
||||
button.monolyth, button.bluebutton, button.greenbutton, button.yellowbutton, button.redbutton { display:inline-block; padding:8px 10px; margin:0.2rem 1.6rem; font-weight:600; text-align:center; text-decoration:none; color:rgb(255, 255, 255); border:none; border-radius:8px; box-shadow:0 4px 6px rgba(0,0,0,0.1); transition:all var(--times-transition-colors) ease; }
|
||||
/* button.monolyth, button.bluebutton, button.greenbutton, button.yellowbutton, button.redbutton { display:inline-block; padding:8px 10px; margin:0.2rem 1.6rem; font-weight:600; text-align:center; text-decoration:none; color:rgb(255, 255, 255); border:none; border-radius:8px; box-shadow:0 4px 6px rgba(0,0,0,0.1); transition:all var(--times-transition-colors) ease; } */
|
||||
button.monolyth, button.bluebutton, button.greenbutton, button.yellowbutton, button.redbutton { display:inline-block; padding:4px 8px; margin:0px 5px; font-weight:600; text-align:center; text-decoration:none; color:rgb(255, 255, 255); border:none; border-radius:8px; box-shadow:0 4px 6px rgba(0,0,0,0.1); transition:all var(--times-transition-colors) ease; }
|
||||
|
||||
button.monolyth { background-color:transparent; }
|
||||
button:not(:disabled).monolyth:hover { opacity:0.9; }
|
||||
button.bluebutton { color:var(--theme-button-blue-default-color); background:var(--theme-button-blue-default-backcolor); }
|
||||
@@ -406,14 +408,23 @@ label { color:var(--muted); display:block; margin-bottom:6px; }
|
||||
border-bottom:1px solid #eee;
|
||||
}
|
||||
|
||||
button.removeButton {
|
||||
.removeButton {
|
||||
border:none;
|
||||
background:none;
|
||||
color:#d11a2a;
|
||||
background:#d11a2a;
|
||||
color:white;
|
||||
cursor:var(--theme-cursor-pointer) -16 16, pointer;
|
||||
/* font-size:14px; */
|
||||
padding: 0 4px;
|
||||
border-radius: 47%;
|
||||
transition: background var(--times-transition-colors) ease, color var(--times-transition-colors) ease;
|
||||
}
|
||||
|
||||
.removeButton:hover {
|
||||
background:#ec5d4d;
|
||||
color:white;
|
||||
}
|
||||
|
||||
|
||||
|
||||
input[type="file"] {
|
||||
display:none;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ table thead { position:sticky; top:0; z-index:20; }
|
||||
|
||||
/* #endregion */
|
||||
/* echte Tabelle */
|
||||
table { width:calc(100%); border-spacing:0 5px; }
|
||||
table { width:calc(100%); border-spacing:0 2px; }
|
||||
table th, table td { min-width:100px; max-width:250px; overflow:hidden; white-space:nowrap; }
|
||||
|
||||
table tr.grouprow:hover { background: rgba(0,0,0,0.05);}
|
||||
@@ -35,6 +35,7 @@ thead, tbody { display:table-row-group; }
|
||||
|
||||
|
||||
table thead th { padding:5px; }
|
||||
/* table tbody td { padding:0 5px; } */
|
||||
/* table tbody td { padding:5px 0px 5px 20px; } */
|
||||
table tbody td:not(:first-child):not(:last-child), table thead th:not(:first-child):not(:last-child) { border-width:0; border-style:solid; }
|
||||
table tbody tr.grouprow { font-weight:700; }
|
||||
@@ -49,20 +50,21 @@ td { overflow:hidden; text-overflow:ellipsis; /* verhindert, dass Inhalt die Zel
|
||||
border-bottom-width:8px;
|
||||
border-bottom-style:solid;
|
||||
display:flex;
|
||||
justify-content:flex-start;
|
||||
flex-direction:column;
|
||||
flex-wrap:wrap;
|
||||
gap:10px;
|
||||
|
||||
flex-direction:row;
|
||||
gap:0;
|
||||
position:sticky;
|
||||
left:0px;
|
||||
top:0px;
|
||||
width: 100% !important;
|
||||
/* z-index:20; */
|
||||
padding:5px 10px;
|
||||
padding:0px;
|
||||
border-radius:var(--border-raduis) var(--border-raduis) 0 0;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
.table-filter-container .live-counter { position:absolute; right:18px; margin-left:auto; font-weight:bold; }
|
||||
.table-filter-container input, .table-filter-container select { padding:5px !important; }
|
||||
.table-filter-container input { padding:5px !important; }
|
||||
|
||||
|
||||
th.sort-asc::after {
|
||||
|
||||
@@ -4,20 +4,107 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
|
||||
<style>
|
||||
#rbacAdmin {
|
||||
font-family: Arial;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
|
||||
#rbacGroupContainer {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
align-content: flex-start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
section {
|
||||
display:inline-flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 5px;
|
||||
width: 120px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
margin: 0 2px 2px 0;
|
||||
}
|
||||
section span {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container grid" style="height:100vh; grid-template-columns: 1fr 1fr;">
|
||||
<div class="card static" id="rbacEntities">
|
||||
|
||||
<!-- USERS -->
|
||||
<div class="container grid" style="grid-template-columns: calc(50% - 8px) calc(50% - 8px);height:100vh;">
|
||||
<div class="card">
|
||||
Users <input id="newUserName" placeholder="sAMAccountName" /> <button class="bluebutton" onclick="createUser()">Create User</button>
|
||||
<div class="table-wrapper fit-table">
|
||||
<table id="rbacUsersTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-align:left"></th>
|
||||
<th class="text-align:left">ObjectGUID</th>
|
||||
<th class="text-align:left">sAMAccountName</th>
|
||||
<th class="text-align:left">Name</th>
|
||||
<th class="text-align:left">Vorname</th>
|
||||
<th class="text-align:left">Mail</th>
|
||||
<th class="text-align:center">Aktiv</th>
|
||||
<th class="text-align:center">Online</th>
|
||||
<th class="text-align:center">Rollen</th>
|
||||
<th class="text-align:center">Gruppen</th>
|
||||
<th class="text-align:right">Herkunft</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td colspan="100%">BENUTZER WERDEN GELADEN . . .</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card static" id="rbacEntityContent">
|
||||
<!-- GROUPS -->
|
||||
<div class="card static" style="flex:1 0 100vw;">
|
||||
<input id="newGroupName" placeholder="Gruppenname" /> <button class="bluebutton" onclick="createGroup()">Create Group</button>
|
||||
|
||||
<div id="rbacGroupContainer">
|
||||
<span>GRUPPEN WERDEN GELADEN . . .</span>
|
||||
</div>
|
||||
|
||||
<input id="newGroupName" placeholder="Group Name" />
|
||||
<button class="bluebutton" onclick="createGroup()">Create Group</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="static" style="pointer-events:none;position:absolute; bottom:20px;right:0px;">
|
||||
<button id="rbacCreateAuthentication" class="yellowbutton" onclick="test()" style="pointer-events:auto">Neuer Benutzer</button>
|
||||
<!-- ROLES -->
|
||||
<div class="card">
|
||||
<h3>Roles</h3>
|
||||
<div id="roleList"></div>
|
||||
|
||||
<input id="newRoleName" placeholder="Role Name" />
|
||||
<button class="bluebutton" onclick="createRole()">Create Role</button>
|
||||
</div>
|
||||
|
||||
<!-- PERMISSIONS -->
|
||||
<div class="card">
|
||||
<h3>Permissions</h3>
|
||||
|
||||
<input id="permScope" placeholder="Scope" />
|
||||
<input id="permResource" placeholder="Resource" />
|
||||
<input id="permAction" placeholder="Action" />
|
||||
|
||||
<button class="bluebutton" onclick="createPermission()">Create Permission</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -25,11 +112,5 @@
|
||||
|
||||
reloadPluginScript('/javascript/rbacAPI.js');
|
||||
|
||||
|
||||
fetch('/api/rbac/getEntities', { method: 'POST' })
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user