bugfix rbac

This commit is contained in:
2026-04-27 15:49:56 +02:00
parent 2ab69bda98
commit 5f494bb837
6 changed files with 93 additions and 90 deletions

View File

@@ -149,7 +149,7 @@ CREATE TABLE dbo.GroupClosure (
Depth INT,
PRIMARY KEY (ParentGroup_ObjectGUID, ChildGroup_ObjectGUID)
);
GO
/* =========================================================
RBAC
@@ -160,25 +160,28 @@ CREATE TABLE dbo.AuthenticationRoles (
Role_ID INT,
PRIMARY KEY (Authentication_ObjectGUID, Role_ID)
);
GO
CREATE TABLE dbo.AuthenticationGroups (
Authentication_ObjectGUID UNIQUEIDENTIFIER,
Group_ObjectGUID UNIQUEIDENTIFIER,
PRIMARY KEY (Authentication_ObjectGUID, Group_ObjectGUID)
);
GO
CREATE TABLE dbo.GroupRoles (
Group_ObjectGUID UNIQUEIDENTIFIER,
Role_ID INT,
PRIMARY KEY (Group_ObjectGUID, Role_ID)
);
GO
CREATE TABLE dbo.RolePermissions (
Role_ID INT,
Permission_ID INT,
PRIMARY KEY (Role_ID, Permission_ID)
);
GO
/* =========================================================
EVENT SYSTEM
@@ -215,6 +218,7 @@ CREATE TABLE dbo.NotifyTrayObjects (
CreatedAt DATETIME2,
ExpiresAt DATETIME2
);
GO
CREATE TABLE dbo.NotifyTray (
ID INT IDENTITY(1,1) PRIMARY KEY,
@@ -222,7 +226,7 @@ CREATE TABLE dbo.NotifyTray (
NotifyTrayObject_ID INT,
SeenAt DATETIME2
);
GO
/* =========================================================
SECURITY VIEWS
@@ -241,7 +245,7 @@ FROM dbo.Authentication a
JOIN dbo.AuthenticationGroups ag ON ag.Authentication_ObjectGUID = a.ObjectGUID
JOIN dbo.GroupRoles gr ON gr.Group_ObjectGUID = ag.Group_ObjectGUID
JOIN dbo.[Role] r ON r.ID = gr.Role_ID;
GO
CREATE VIEW dbo.vAuthenticationEffectivePermissions AS
SELECT DISTINCT
@@ -254,7 +258,7 @@ FROM dbo.Authentication a
JOIN dbo.vAuthenticationRoles r ON r.ObjectGUID = a.ObjectGUID
JOIN dbo.RolePermissions rp ON rp.Role_ID = r.Role_ID
JOIN dbo.Permission p ON p.ID = rp.Permission_ID;
GO
/* =========================================================
FIXED vEventLog (SEQUELIZE MATCH + SYSTEM FIX)
@@ -308,7 +312,7 @@ CREATE VIEW dbo.vAuthentications AS
SELECT a.*, os.Name AS ObjectSource
FROM dbo.Authentication a
LEFT JOIN dbo.ObjectSource os ON os.ID = a.ObjectSource_ID;
GO
/* =========================================================
GROUP VIEW
@@ -316,7 +320,7 @@ LEFT JOIN dbo.ObjectSource os ON os.ID = a.ObjectSource_ID;
CREATE VIEW dbo.vGroupHierarchy AS
SELECT * FROM dbo.GroupClosure;
GO
/* =========================================================
NOTIFY VIEWS

View File

@@ -135,8 +135,8 @@ const server = https.createServer(httpsOptions, app);
databaseModel.set('roleModel', require(`@models/roleModel`)(service.get('sqlManager').getInstance('main')));
databaseModel.set('rolePermissionsModel', require(`@models/rolePermissionsModel`)(service.get('sqlManager').getInstance('main')));
service.set('authenticationManager', new AuthenticationManager(databaseModel.get('authentication'), app.locals.configuration.integration.token.secret));
service.set('rbacManager', new RBACManager(databaseModel));
service.set('authenticationManager', new AuthenticationManager(databaseModel.get('authentication'), app.locals.configuration.integration.token.secret));
service.set('activeDirectoryManager', new ActiveDirectory(app.locals.configuration.integration.activedirectory))
@@ -228,7 +228,7 @@ const server = https.createServer(httpsOptions, app);
require(`${app.locals.path.source}/routes/adminRoutes.js`).route(app, service); // #3 - token security always enabled
//#endregion
app.use(service.get('authenticationManager').authenticate());
app.use(service.get('rbacManager').authenticate());
//#region Implements sockets
require(`${app.locals.path.source}/sockets/mainSocket.js`)(

View File

@@ -40,7 +40,7 @@ module.exports = {
// Geschützte Route
app.get('/me', service.get('authenticationManager').authenticate(), (req, res) => {
app.get('/me', service.get('rbacManager').authenticate(), (req, res) => {
res.json(JSON.stringify({
user: {
name: req.user
@@ -63,7 +63,7 @@ module.exports = {
});
// Logout
app.post('/logout', service.get('authenticationManager').authenticate(), async (req, res) => {
app.post('/logout', service.get('rbacManager').authenticate(), async (req, res) => {
const logout = await service.get('authenticationManager').logout(req.user.sAMAccountName);
// socketManager.sendTo('/', req.user.objectGuid, 'login_status', { levelId: logout.levelId, message: logout.message } )

View File

@@ -2,6 +2,7 @@ const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
class AuthenticationManager {
constructor(model, secretKey) {
this.Authentication = model;
this.SECRET_KEY = secretKey;
@@ -113,81 +114,6 @@ class AuthenticationManager {
return { valid: false, levelId: 4 };
}
}
// =========================================================
// 🔥 MIDDLEWARE BLEIBT HIER
// =========================================================
authenticate() {
return async (req, res, next) => {
try {
// =====================================================
// 🔥 GLOBAL PUBLIC ROUTE BYPASS (ROBUST)
// =====================================================
const url = req.originalUrl.split('?')[0];
const publicRoutes = [
'/login',
'/public'
];
const isPublicRoute = publicRoutes.some(route =>
url === route || url.startsWith(route + '/')
);
if (isPublicRoute) {
return next();
}
// =====================================================
// 🔐 AUTH FLOW
// =====================================================
const sAMAccountName = req.cookies?.sAMAccountName;
if (!sAMAccountName) {
return res.redirect('/login');
}
const user = await this.findUser(sAMAccountName);
if (!user || !user.active) {
return res.redirect('/login');
}
let payload;
try {
payload = jwt.verify(user.refreshtoken, this.SECRET_KEY);
} catch {
return res.redirect('/login');
}
const rbac = await this.rbac.resolvePermissions(user.ObjectGUID);
const normalized = this.rbac.normalize(rbac.permissions);
const isSuperAdmin = this.rbac.isSuperAdmin(normalized);
req.user = {
...user.toJSON(),
jwt: payload,
groups: rbac.groups,
roles: rbac.roles,
permissions: normalized,
isSuperAdmin
};
next();
} catch (err) {
console.error(err);
return res.redirect('/login');
}
};
}
}
module.exports = AuthenticationManager;

View File

@@ -151,6 +151,82 @@ class RBACManager {
};
}
// =========================================================
// 🔥 MIDDLEWARE BLEIBT HIER
// =========================================================
authenticate() {
return async (req, res, next) => {
try {
// =====================================================
// 🔥 GLOBAL PUBLIC ROUTE BYPASS (ROBUST)
// =====================================================
const url = req.originalUrl.split('?')[0];
const publicRoutes = [
'/login',
'/public'
];
const isPublicRoute = publicRoutes.some(route =>
url === route || url.startsWith(route + '/')
);
if (isPublicRoute) {
return next();
}
// =====================================================
// 🔐 AUTH FLOW
// =====================================================
const sAMAccountName = req.cookies?.sAMAccountName;
if (!sAMAccountName) {
return res.redirect('/login');
}
const user = await this.db.get('authentication').findOne( { where: { sAMAccountName } } );
if (!user || !user.active) {
return res.redirect('/login');
}
let payload;
try {
payload = jwt.verify(user.refreshtoken, this.SECRET_KEY);
} catch {
return res.redirect('/login');
}
const rbac = await this.resolvePermissions(user.ObjectGUID);
const normalized = this.normalize(rbac.permissions);
const isSuperAdmin = this.isSuperAdmin(normalized);
req.user = {
...user.toJSON(),
jwt: payload,
groups: rbac.groups,
roles: rbac.roles,
permissions: normalized,
isSuperAdmin
};
next();
} catch (err) {
console.error(err);
return res.redirect('/login');
}
};
}
normalize(permissions) {
return permissions.map(p => ({
scope: p.scope,

View File

@@ -54,10 +54,7 @@ module.exports = startMenuItems = async function (app, objectGuid, debug = false
// Load user permissions
// =========================
const rbacManager = service.get('rbacManager');
const userPermissions =
(await rbacManager.resolvePermissions(objectGuid))
?.permissions || [];
const userPermissions = objectGuid === undefined ? [] : (await rbacManager.resolvePermissions(objectGuid))?.permissions;
const normalizedPermissions = userPermissions.map(p => ({
scope: p.scope,