styles bugfix

This commit is contained in:
2026-05-07 15:28:26 +02:00
parent e5ee067db4
commit c848633a1f
8 changed files with 371 additions and 122 deletions

106
package-lock.json generated
View File

@@ -2102,23 +2102,6 @@
"node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/npm/node_modules/@isaacs/balanced-match": {
"version": "4.0.1",
"license": "MIT",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/npm/node_modules/@isaacs/brace-expansion": {
"version": "5.0.0",
"license": "MIT",
"dependencies": {
"@isaacs/balanced-match": "^4.0.1"
},
"engines": {
"node": "20 || >=22"
}
},
"node_modules/npm/node_modules/@isaacs/fs-minipass": {
"version": "4.0.1",
"inBundle": true,
@@ -2637,14 +2620,6 @@
"node": ">=0.3.1"
}
},
"node_modules/npm/node_modules/encoding": {
"version": "0.1.13",
"license": "MIT",
"optional": true,
"dependencies": {
"iconv-lite": "^0.6.2"
}
},
"node_modules/npm/node_modules/env-paths": {
"version": "2.2.1",
"inBundle": true,
@@ -2653,10 +2628,6 @@
"node": ">=6"
}
},
"node_modules/npm/node_modules/err-code": {
"version": "2.0.3",
"license": "MIT"
},
"node_modules/npm/node_modules/exponential-backoff": {
"version": "3.1.3",
"inBundle": true,
@@ -2769,13 +2740,6 @@
"node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/npm/node_modules/imurmurhash": {
"version": "0.1.4",
"license": "MIT",
"engines": {
"node": ">=0.8.19"
}
},
"node_modules/npm/node_modules/ini": {
"version": "6.0.0",
"inBundle": true,
@@ -3448,17 +3412,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/npm/node_modules/promise-retry": {
"version": "2.0.1",
"license": "MIT",
"dependencies": {
"err-code": "^2.0.2",
"retry": "^0.12.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/npm/node_modules/promzard": {
"version": "3.0.1",
"inBundle": true,
@@ -3496,13 +3449,6 @@
"node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/npm/node_modules/retry": {
"version": "0.12.0",
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/npm/node_modules/safer-buffer": {
"version": "2.1.2",
"inBundle": true,
@@ -3582,22 +3528,6 @@
"node": ">= 14"
}
},
"node_modules/npm/node_modules/spdx-correct": {
"version": "3.2.0",
"license": "Apache-2.0",
"dependencies": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": {
"version": "3.0.1",
"license": "MIT",
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/npm/node_modules/spdx-exceptions": {
"version": "2.5.0",
"inBundle": true,
@@ -3727,47 +3657,11 @@
"node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/npm/node_modules/unique-filename": {
"version": "5.0.0",
"license": "ISC",
"dependencies": {
"unique-slug": "^6.0.0"
},
"engines": {
"node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/npm/node_modules/unique-slug": {
"version": "6.0.0",
"license": "ISC",
"dependencies": {
"imurmurhash": "^0.1.4"
},
"engines": {
"node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/npm/node_modules/util-deprecate": {
"version": "1.0.2",
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/validate-npm-package-license": {
"version": "3.0.4",
"license": "Apache-2.0",
"dependencies": {
"spdx-correct": "^3.0.0",
"spdx-expression-parse": "^3.0.0"
}
},
"node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": {
"version": "3.0.1",
"license": "MIT",
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/npm/node_modules/validate-npm-package-name": {
"version": "7.0.2",
"inBundle": true,

View File

@@ -212,13 +212,12 @@ button:not(:disabled).yellowbutton:hover { background:var(--theme-button-yellow-
<span class="cb-box" aria-hidden="true"></span>
</label>
*/
.cb { display:inline-flex; align-items:center; gap:10px; user-select:none; transform:translateY(2px); }
.cb input { position:absolute; opacity:0; width:0; height:0; pointer-events:none; }
.cb-box { width:20px; height:20px; border-radius:6px; background:var(--theme-checkbox-backcolor); border-width:2px; border-style:solid; display:inline-grid; place-items:center; transition:transform var(--times-transition-transform) ease, border-color var(--times-transition-colors) ease, background var(--times-transition-colors) ease; }
.cb-box::after { content:""; width:12px; height:8px; transform:scale(0) translateY(-2px); background-repeat:no-repeat; background-position:center; background-size:contain; background-image:url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 4L4 7l7-7' stroke='%23fff' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); transition:transform var(--times-transition-transform) cubic-bezier(.2,.9,.2,1); }
.cb { display:inline-grid;grid-auto-flow:column;align-items:center;gap:10px;user-select:none;vertical-align:middle; }
.cb input { position:absolute;opacity:0;width:0;height:0;pointer-events:none; }
.cb-box { width:20px;height:20px;border-radius:6px;background:var(--theme-checkbox-backcolor);border:2px solid;display:grid;place-items:center;transition:transform var(--times-transition-transform) ease,border-color var(--times-transition-colors) ease,background var(--times-transition-colors) ease;flex-shrink:0; }
.cb-box::after { content:"";width:10px;height:6px;border-left:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(-45deg)scale(0);transform-origin:center;transition:transform var(--times-transition-transform)cubic-bezier(.2,.9,.2,1); }
.cb input:checked + .cb-box::after { transform: rotate(-45deg) scale(1) translate(1px, -1px); }
.cb input:checked + .cb-box { transform:translateY(-1px); }
.cb input:checked + .cb-box::after { transform:scale(1) translate(-1px, 1px); }
table .cb input:checked + .cb-box::after { transform:scale(1) translate(1px, 1px); }
.cb input:focus-visible + .cb-box { outline:none; }
/* #endregion */

View File

@@ -80,7 +80,6 @@ body, html { margin:0; padding:0; height:100%; overflow: hidden; font-family: va
.start-item.has-submenu > .submenu li { opacity: 0; transform: translateY(-5px); transition: opacity var(--times-transition-opacity), transform 0.2s; }
.start-item.has-submenu.open > .submenu li { opacity: 1; transform: translateY(0); }
img.icon { width: auto; height:20px; object-fit: contain; filter: var(--theme-notifybubble-filter); transform: translate(2px, 2px) }

View File

@@ -6,7 +6,7 @@
min-width: 200px;
max-height: 50vh;
width: max-content; /* 🔑 wächst mit Inhalt */
max-width: 600px; /* aber capped */
max-width: 500px; /* aber capped */
background: var(--theme-taskbar-tray-backcolor);
color: var(--theme-taskbar-tray-color);
border-color: var(--theme-taskbar-tray-border-color);
@@ -14,7 +14,7 @@
overflow-y: auto; /* vertikal scrollen */
overflow-x: hidden; /* horizontal verhindern */
box-shadow: 0 8px 20px rgba(0,0,0,0.4);
padding: 10px 10px 6px 10px;
padding: 6px 6px 0px 6px;
opacity: 0;
pointer-events: none;
transform: translateY(10px);
@@ -28,8 +28,8 @@
.bubble-item {
display: grid;
grid-template-columns: minmax(0, auto) 250px;
gap: 10px;
padding: 6px 8px;
gap: 5px;
padding: 3px 6px;
border-radius: 6px;
/* cursor: pointer; */
align-items: center;
@@ -55,7 +55,9 @@
/* hover Effekt */
.bubble-item:hover {
background: rgba(64,64,64,0.4);
background: var(--theme-accent-hover-backcolor);
color: var(--theme-accent-hover-color);
border-color: var(--theme-accent-hover-border-color);
transform: scale(1.01);
}

View File

@@ -121,10 +121,10 @@ const server = https.createServer(httpsOptions, app);
databaseModel.set('permissionOverviewView', require(`@models/permissionOverviewView`)(service.get('sqlManager').getInstance('main')));
service.set('rbacManager', new RBACManager(databaseModel, runtimeFile.configuration.live.integration.token.secret));
service.set('activeDirectoryManager', new ActiveDirectory(runtimeFile.configuration.live.integration.activedirectory))
service.set('rbacManager', new RBACManager(databaseModel, runtimeFile.configuration.live.integration.token.secret, service));
service.set('authenticationManager', new AuthenticationManager(databaseModel.get('authentication'), runtimeFile.configuration.live.integration.token.secret));
service.set('activeDirectoryManager', new ActiveDirectory(runtimeFile.configuration.live.integration.activedirectory))
// everytime last created service!
service.set('pluginManager', new PluginManager(app, databaseModel.get('plugin'), localPath.plugins, runtimeFile.configuration.live.plugin.chown, service));

View File

@@ -102,6 +102,7 @@ module.exports = {
app.post('/api/rbac/auth/get', async (req, res) => {
try {
console.log(await service.get('rbacManager').syncAuthByActiveDirectory());
rbacUsers = await service.get('rbacManager').getAuth();
res.json(rbacUsers);
} catch (err) {

View File

@@ -56,6 +56,30 @@ class ActiveDirectoryManager {
});
}
async getAllUsers(attributes = this.userAttributes) {
const options = {
baseDN: this.ad.baseDN,
filter: '(&(objectClass=user)(objectCategory=person))',
attributes: ['ObjectGUID'
,'sAMAccountName'
,'mail'
,'givenName'
,'sn'
,'employeeID'
,'title'
,'department'
,'streetAddress'
,'telephoneNumber'
,'physicalDeliveryOfficeName'
,'distinguishedName']
};
const result = await this.ldapSearch(options);
console.log(result)
return result.users || [];
}
async getUserDN(username) {
const user = await this.getUser(username);
return user?.dn || null;
@@ -256,3 +280,309 @@ class ActiveDirectoryManager {
}
module.exports = ActiveDirectoryManager;
// const ldap = require('ldapjs');
// class ActiveDirectoryManager {
// constructor({
// url,
// baseDN,
// username,
// password,
// userAttributes = [],
// groupAttributes = [],
// computerAttributes = []
// }) {
// this.url = url;
// this.baseDN = baseDN;
// this.username = username;
// this.password = password;
// this.userAttributes = userAttributes;
// this.groupAttributes = groupAttributes;
// this.computerAttributes = computerAttributes;
// this.client = ldap.createClient({
// url: this.url,
// reconnect: true,
// timeout: 10000,
// connectTimeout: 10000
// });
// }
// /**
// * -----------------------------------------------------
// * CONNECTION HANDLING
// * -----------------------------------------------------
// */
// async bind() {
// return new Promise((resolve, reject) => {
// this.client.bind(this.username, this.password, (err) => {
// if (err) return reject(err);
// resolve();
// });
// });
// }
// async unbind() {
// return new Promise((resolve, reject) => {
// this.client.unbind(err => {
// if (err) return reject(err);
// resolve();
// });
// });
// }
// async withConnection(fn) {
// try {
// await this.bind();
// return await fn();
// } finally {
// await this.unbind();
// }
// }
// /**
// * -----------------------------------------------------
// * INTERNAL HELPERS
// * -----------------------------------------------------
// */
// escape(value) {
// return String(value).replace(/[*()\\]/g, '\\$&');
// }
// async ldapSearch({ baseDN = this.baseDN, filter, attributes = [] }) {
// const opts = {
// filter,
// scope: 'sub',
// attributes,
// paged: true
// };
// return new Promise((resolve, reject) => {
// const results = [];
// this.client.search(baseDN, opts, (err, res) => {
// if (err) return reject(err);
// res.on('searchEntry', (entry) => {
// results.push(entry.object);
// });
// res.on('error', (err) => reject(err));
// res.on('end', () => resolve(results));
// });
// });
// }
// /**
// * -----------------------------------------------------
// * USER FUNCTIONS
// * -----------------------------------------------------
// */
// async getUser(username, attributes = this.userAttributes) {
// const safe = this.escape(username);
// const filter = `(&(objectCategory=person)(objectClass=user)(|(sAMAccountName=${safe})(mail=${safe})(cn=${safe}))))`;
// const res = await this.ldapSearch({ filter, attributes });
// return res[0] || null;
// }
// async getUserDN(username) {
// const user = await this.getUser(username);
// return user?.distinguishedName || null;
// }
// async findUsers(query, attributes = this.userAttributes) {
// const safe = this.escape(query);
// const filter = `(&(objectCategory=person)(objectClass=user)(|(cn=${safe})(sAMAccountName=${safe})(mail=${safe})(displayName=${safe})))`;
// return await this.ldapSearch({ filter, attributes });
// }
// async getAllUsers(attributes = this.userAttributes) {
// const filter = '(&(objectCategory=person)(objectClass=user))';
// return await this.ldapSearch({ filter, attributes });
// }
// /**
// * -----------------------------------------------------
// * GROUP FUNCTIONS
// * -----------------------------------------------------
// */
// async getGroup(groupName, attributes = this.groupAttributes) {
// const safe = this.escape(groupName);
// const filter = `(&(objectClass=group)(cn=${safe}))`;
// const res = await this.ldapSearch({ filter, attributes });
// return res[0] || null;
// }
// async findGroups(query, attributes = this.groupAttributes) {
// const safe = this.escape(query);
// const filter = `(&(objectClass=group)(cn=${safe}))`;
// return await this.ldapSearch({ filter, attributes });
// }
// async getAllGroups(attributes = this.groupAttributes) {
// const filter = '(objectClass=group)';
// return await this.ldapSearch({ filter, attributes });
// }
// /**
// * -----------------------------------------------------
// * COMPUTER / OU FUNCTIONS
// * -----------------------------------------------------
// */
// async getComputer(name, attributes = this.computerAttributes) {
// const safe = this.escape(name);
// const filter = `(&(objectClass=computer)(|(cn=${safe})(dNSHostName=${safe})))`;
// const res = await this.ldapSearch({ filter, attributes });
// return res[0] || null;
// }
// async getComputers(attributes = this.computerAttributes) {
// const filter = '(objectClass=computer)';
// return await this.ldapSearch({ filter, attributes });
// }
// async getComputersFromOU(ouDn, attributes = this.computerAttributes) {
// const filter = '(objectClass=computer)';
// return await this.ldapSearch({
// baseDN: ouDn,
// filter,
// attributes
// });
// }
// async findComputers(query, attributes = this.computerAttributes) {
// const safe = this.escape(query);
// const filter = `(&(objectClass=computer)(|(cn=${safe})(dNSHostName=${safe})))`;
// return await this.ldapSearch({ filter, attributes });
// }
// /**
// * -----------------------------------------------------
// * GROUP MEMBERSHIP
// * -----------------------------------------------------
// */
// async isUserMemberOfDirect(username, groupName) {
// const user = await this.getUser(username, ['distinguishedName']);
// if (!user) return false;
// const userDN = user.distinguishedName;
// const safeGroup = this.escape(groupName);
// const filter = `(&(objectClass=group)(cn=${safeGroup})(member=${userDN}))`;
// const res = await this.ldapSearch({ filter, attributes: ['cn'] });
// return res.length > 0;
// }
// async isUserMemberOfRecursive(username, groupName, visited = new Set()) {
// const key = groupName.toLowerCase();
// if (visited.has(key)) return false;
// visited.add(key);
// const direct = await this.isUserMemberOfDirect(username, groupName);
// if (direct) return true;
// const group = await this.getGroup(groupName, ['member']);
// if (!group || !group.member) return false;
// const members = Array.isArray(group.member) ? group.member : [group.member];
// for (const dn of members) {
// const match = dn.match(/CN=([^,]+)/i);
// if (!match) continue;
// const subGroup = match[1];
// const found = await this.isUserMemberOfRecursive(username, subGroup, visited);
// if (found) return true;
// }
// return false;
// }
// async getGroupSubgroups(groupName, visited = new Set()) {
// const key = groupName.toLowerCase();
// if (visited.has(key)) return [];
// visited.add(key);
// const group = await this.getGroup(groupName, ['member']);
// if (!group || !group.member) return [];
// const members = Array.isArray(group.member) ? group.member : [group.member];
// const results = [];
// for (const dn of members) {
// const match = dn.match(/CN=([^,]+)/i);
// if (!match) continue;
// const subGroupName = match[1];
// const sub = await this.getGroup(subGroupName).catch(() => null);
// if (!sub) continue;
// results.push(sub);
// results.push(...await this.getGroupSubgroups(subGroupName, visited));
// }
// return results;
// }
// async getGroupRecursive(groupName, visited = new Set()) {
// const key = groupName.toLowerCase();
// if (visited.has(key)) return null;
// visited.add(key);
// const group = await this.getGroup(groupName);
// if (!group) return null;
// const result = {
// ...group,
// subgroups: []
// };
// if (!group.member) return result;
// const members = Array.isArray(group.member) ? group.member : [group.member];
// for (const dn of members) {
// const match = dn.match(/CN=([^,]+)/i);
// if (!match) continue;
// const subGroupName = match[1];
// const subTree = await this.getGroupRecursive(subGroupName, visited);
// if (subTree) result.subgroups.push(subTree);
// }
// return result;
// }
// }
// module.exports = ActiveDirectoryManager;

View File

@@ -1,9 +1,11 @@
const jwt = require('jsonwebtoken');
const sequelize = require('sequelize');
class RBACManager {
constructor(databaseModel, SECRET_KEY) {
constructor(databaseModel, SECRET_KEY, service) {
this.db = databaseModel;
this.SECRET_KEY = SECRET_KEY;
this.service = service;
}
async resolvePermissions(objectGuid) {
@@ -246,6 +248,29 @@ async getAuth() {
return await Auth.findAll({ raw: true });
}
async syncAuthByActiveDirectory() {
const auth = await this.db.get('authentication');
const all = await this.service.get('activeDirectoryManager').getAllUsers();
await Promise.all(
all.map(async (user) => {
user = {...user, userAccountControl_ID: user.userAccountControl};
const [record, created] = await auth.findOrCreate({
where: { dn: user.dn },
defaults: user
});
if (!created) {
await record.update(user);
}
})
);
// return all;
}
async createAuth(data) {
const Auth = this.db.get('authentication');
@@ -429,7 +454,6 @@ async getPermission() {
return await permission.findAll({ raw: true }) || [];
}
async createPermission(data) {
const Permission = this.db.get('permissionModel');