const ctx = new ContextMenu(); ////////////////////////////// // 🌐 API LAYER ////////////////////////////// const api = async (url, method = 'GET', body) => { const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: body ? JSON.stringify(body) : undefined }); if(res.status >= 400) { const text = await res.text(); sendUserEvent('RBAC', `Hoppla, da ist etwas schief gelaufen:\r\n${text}`, null, 4); } return res.json(); }; ////////////////////////////// // 🧠 RBAC SERVICE LAYER ////////////////////////////// const RBAC = { // 👤 USERS loadUsers: async () => (await api('/api/rbac/auth/get', 'POST')) .map(({ active, online, ...rest }) => ({ ...rest, Aktiv: active })) .sort((a, b) => a.sAMAccountName.localeCompare(b.sAMAccountName)), createUser: (data) => api('/api/rbac/auth/create', 'POST', data), deleteUser: (guid) => api(`/api/rbac/auth/${guid}`, 'DELETE'), // 👥 GROUPS loadGroups: () => api('/api/rbac/group/get', 'POST'), createGroup: (name) => api('/api/rbac/group/create', 'POST', { name }), deleteGroup: (guid) => api(`/api/rbac/group/${guid}`, 'DELETE'), // 🔗 ASSIGNMENTS addUserToGroup: (authGuid, groupGuid) => api('/api/rbac/group/add-user', 'POST', { authGuid, groupGuid }), addUserToRole: (authGuid, roleId) => api('/api/rbac/role/add-user', 'POST', { authGuid, roleId }), addGroupToRole: (groupGuid, roleId) => api('/api/rbac/role/add-group', 'POST', { groupGuid, roleId }), addPermissionToRole: (roleId, permissionId) => api('/api/rbac/role/add-permission', 'POST', { roleId, permissionId }) }; ////////////////////////////// // 🖱️ DRAG & DROP ////////////////////////////// function createDragZone(el, data) { el.draggable = true; el.addEventListener('dragstart', (evt) => { evt.dataTransfer.setData('application/json', JSON.stringify(data)); }); } function createDropZone(el, type, target) { const targetValue = target.ObjectGUID || target.Role_ID || target.Permission_ID; let process = { action: null, response: null, failure: false }; el.addEventListener('dragover', e => e.preventDefault()); el.addEventListener('drop', async (e) => { e.preventDefault(); const data = JSON.parse( e.dataTransfer.getData('application/json') ); if(!targetValue) { sendUserEvent('RBAC', 'Deinem Drop-Ziel wurde kein ID-Attribut zugewiesen. Frag einfach Manuel ', null, 2); return; } switch (type) { case 'group': process.action = `Du hast den Benutzer der Gruppe hinzugefügt`; process.response = await RBAC.addUserToGroup(data.ObjectGUID, targetValue); loadUsers(); break; case 'role': process.action = `Du hast den Benutzer der Rolle hinzugefügt`; process.response = await RBAC.addUserToRole(data.ObjectGUID, targetValue); break; case 'group-to-role': process.action = `Du hast die Gruppe der Rolle hinzugefügt`; process.response = await RBAC.addGroupToRole(data.ObjectGUID, targetValue); break; case 'permission': process.action = `Du hast den Berechtigung der Rolle hinzugefügt`; process.response = await RBAC.addPermissionToRole(targetValue, data.ID); break; } if(process.failure) return; sendUserEvent('RBAC', process.action, null, 0); }); } ////////////////////////////// // 📋 TABLE (USERS) ////////////////////////////// const vt = virtualTable({ tableEl: document.querySelector('#rbacUsersTable'), data: [], rowHeight: 20, buffer: 5, groupKey: 'ObjectSourceName', rowKey: 'ObjectGUID', filterConfig: { hideCounter: true, exceptedColumns: ['', 'Rollen', 'Gruppen'], columnModes: { Aktiv: 'dropdown', Online: 'dropdown' } }, customRender: (row, tr) => { createDragZone(tr, row); tr.addEventListener('contextmenu', (evt) => { evt.preventDefault(); ctx.setItems([ { label: "Details", onClick: () => showAuthDetails(row.ObjectGUID) } ]); ctx.show(evt.pageX + 5, { y: evt.pageY + 5 }); }); createTd(tr, ``, { styles: { 'position': 'sticky', 'left': '0px', 'max-width': '20px', 'z-index': '2' }, classes: [ 'text-align:left' ], onclick: () => { if(row['ObjectGUID'] === '00000000-0000-0000-0000-000000000001') return; deleteUser(row['ObjectGUID'], row['sAMAccountName']); } }); 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['RoleCount'], { classes: [ 'text-align:center' ] }); createTd(tr, row['GroupCount'], { classes: [ 'text-align:center' ] }); 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['Aktiv'], { classes: [ 'text-align:center' ] }); } }); ////////////////////////////// // 📥 LOADERS ////////////////////////////// async function loadUsers() { try { vt.source(await RBAC.loadUsers()); } catch (err) { console.error(err); } } async function loadGroups() { const container = document.getElementById('rbacGroupContainer'); container.innerHTML = ''; const groups = await RBAC.loadGroups(); const fragment = document.createDocumentFragment(); groups.forEach(group => { const section = document.createElement('section'); const groupName = document.createElement('span'); groupName.innerHTML = group.Name; groupName.dataset.tooltip = group.Name; groupName.dataset.tooltipMode = 'ellipsis'; section.append(groupName); if(group.ObjectGUID !== '00000000-0000-0000-0000-000000000001') { const removeButton = document.createElement('div'); removeButton.className = 'removeButton'; removeButton.innerHTML = 'X'; removeButton.onclick = async () => { await deleteGroup(group.ObjectGUID, group.Name); }; section.append(removeButton); } createDropZone(section, 'group', group); fragment.appendChild(section); }); container.appendChild(fragment); } 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(); } } ////////////////////////////// // 👤 USER ACTIONS ////////////////////////////// async function createUser() { const name = document.getElementById('newUserName').value; if (!name || !name.includes('.')) return; const [givenName, sn] = name.split('.'); const user = await RBAC.createUser({ sAMAccountName: name, mail: `${name}@test.com`, givenName: givenName[0].toUpperCase() + givenName.slice(1), sn: sn[0].toUpperCase() + sn.slice(1) }); sendUserEvent('RBAC', `Benutzer ${user.sAMAccountName} [${user.ObjectGUID}] angelegt`, null, 0); loadUsers(); } async function deleteUser(guid, name) { feedbox({ title: `Benutzer löschen`, message: `Soll der Benutzer ${name} und
alle seine Zugehörigkeiten entfernt werden`, buttons: { no: { text: 'Nein' }, yes: { text: 'Ja', onClick: async () => { const user = await RBAC.deleteUser(guid); sendUserEvent('RBAC', `Benutzer ${user.sAMAccountName || ''} [${user.ObjectGUID}] gelöscht`, null, 0); loadUsers(); } } } }); } ////////////////////////////// // 👥 GROUP ACTIONS ////////////////////////////// async function deleteGroup(guid, name) { feedbox({ title: `Gruppe löschen`, message: `Möchtest du die Gruppe ${name} [${guid}] wirklich löschen`, buttons: { no: { text: 'Nein' }, yes: { text: 'Ja', onClick: async () => { const group = await RBAC.deleteGroup(guid); sendUserEvent('RBAC', `Du hast die Gruppe ${name || ''} [${group.ObjectGUID}] gelöscht`, null, 0); loadUsers(); loadGroups(); } } } }); } ////////////////////////////// // 🚀 INIT ////////////////////////////// loadUsers(); loadGroups(); // const ctx = new ContextMenu(); // const vt = virtualTable({ // tableEl: document.querySelector('#rbacUsersTable'), // data: [], // rowHeight: 20, // buffer: 5, // groupKey: 'ObjectSourceName', // optional zum Gruppieren // rowKey: 'ObjectGUID', // filterConfig: { // hideCounter: true, // exceptedColumns: ['', 'Rollen', 'Gruppen'], // columnModes: { // Aktiv: 'dropdown', // Online: 'dropdown' // } // }, // customRender: (row, tr) => { // tr.draggable = true; // tr.dataset.guid = row['ObjectGUID']; // tr.dataset.sAMAccountName = row['sAMAccountName']; // tr.ondragstart = (evt) => { // const data = { // guid: tr.dataset.guid, // sAMAccountName: tr.dataset.sAMAccountName // }; // evt.dataTransfer.setData('application/json', JSON.stringify(data)); // }; // tr.oncontextmenu = async evt => { // if (evt.target.tagName === 'BUTTON') return; // ctx.setItems([ { label: "Details", onClick: () => showAuthDetails(row['ObjectGUID']) } ]); // evt.preventDefault(); // ctx.show(evt.pageX + 5, {y: evt.pageY + 5 }); // }; // createTd(tr, // ``, { // styles: { // 'position': 'sticky', // 'left': '0px', // 'width': '20px', // 'z-index': '2' // }, classes: [ // 'text-align:left' // ], onclick: () => { // if(row['ObjectGUID'] === '00000000-0000-0000-0000-000000000001') return; // deleteUser(row['ObjectGUID'], row['sAMAccountName']); // } // }); // 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' ] }); // } // }); // 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 showAuthDetails(guid) { // const details = await api(`/api/rbac/auth/details/${guid}`) // if(!details) return; // feedbox({ // title: `Details`, // message: Object.entries(details).map(([key, value]) => /*html*/`

${key}:${value}

`).join(''), // buttons: { // yes: { // text: 'Schließen' // } // }, // lock: true, // primary: 'yes' // }) // } // async function createUser() { // const name = document.getElementById('newUserName').value; // if(!name || !name.includes('.')) { // sendUserEvent('RBAC', 'Der sAMAccountName muss einen Punkt enthalten
Der Benutzer wurde nicht angelegt', null, 2); // return; // } // 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 deleteUser(guid, sAMAccountName) { // feedbox({ // title: `Benutzer löschen`, // message: ` //

Möchtest du den Benutzer ${sAMAccountName} [${guid}] wirklich löschen

// `, // buttons: { // no: { // text: 'Nein' // }, // yes: { // text: 'Ja', // onClick: async () => { // const user = await api(`/api/rbac/auth/${guid}`, 'DELETE', { // guid // }); // if(user) { // loadUsers(); // sendUserEvent('RBAC', `Benutzer ${user.sAMAccountName || ''} [${user.ObjectGUID}] gelöscht`, null, 0); // } // } // } // } // }); // } // 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(); // } // } // async function deleteGroup(guid, name) { // feedbox({ // title: `Gruppe löschen`, // message: ` //

Möchtest du die Gruppe ${name} [${guid}] wirklich löschen

// `, // buttons: { // no: { // text: 'Nein' // }, // yes: { // text: 'Ja', // onClick: async () => { // const group = await api(`/api/rbac/group/${guid}`, 'DELETE', { // guid // }); // if(group) { // sendUserEvent('RBAC', `Gruppe ${group.Name || ''} [${group.ObjectGUID}] gelöscht`, null, 0); // loadGroups(); // } // } // } // } // }); // // 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'); // createDropZone(section, 'group', group.ObjectGUID); // section.innerHTML = `${group.Name}
X
`; // 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'); // } // function createDropZone(element, direction, keyAttribute) { // element.addEventListener('dragover', (evt) => { // evt.preventDefault(); // }); // // 📥 Drop verarbeiten // element.addEventListener('drop', (evt) => { // evt.preventDefault(); // const attributeValue = element.dataset[keyAttribute]; // ObjectGuid or ID // const data = JSON.parse( // evt.dataTransfer.getData('application/json') // ); // switch (direction) { // case 'user-to-group': // addUserToGroup(data.guid, attributeValue); // break; // case 'user-to-role': // addPermissionToRole(data.guid, attributeValue); // break; // case 'group-to-role': // addGroupToRole(data.guid, attributeValue); // break; // case 'permission-to-role': // addPermissionToRole(data.roleId, attributeValue) // default: // break; // } // }); // } // async function addUserToGroup(authGuid, groupGuid) { // await api('/api/rbac/group/add-user', 'POST', { // authGuid, // groupGuid // }); // } // async function addUserToRole(authGuid, roleId) { // await api('/api/rbac/role/add-user', 'POST', { // authGuid, // roleId // }); // } // async function addGroupToRole(groupGuid, roleId) { // await api('/api/rbac/role/add-group', 'POST', { // groupGuid, // roleId // }); // } // async function addPermissionToRole(roleId, permissionId) { // await api('/api/rbac/role/add-permission', 'POST', { // roleId, // permissionId // }); // }