bugfix rbac
This commit is contained in:
18
dbcreate.sql
18
dbcreate.sql
@@ -149,7 +149,7 @@ CREATE TABLE dbo.GroupClosure (
|
|||||||
Depth INT,
|
Depth INT,
|
||||||
PRIMARY KEY (ParentGroup_ObjectGUID, ChildGroup_ObjectGUID)
|
PRIMARY KEY (ParentGroup_ObjectGUID, ChildGroup_ObjectGUID)
|
||||||
);
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
/* =========================================================
|
/* =========================================================
|
||||||
RBAC
|
RBAC
|
||||||
@@ -160,25 +160,28 @@ CREATE TABLE dbo.AuthenticationRoles (
|
|||||||
Role_ID INT,
|
Role_ID INT,
|
||||||
PRIMARY KEY (Authentication_ObjectGUID, Role_ID)
|
PRIMARY KEY (Authentication_ObjectGUID, Role_ID)
|
||||||
);
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
CREATE TABLE dbo.AuthenticationGroups (
|
CREATE TABLE dbo.AuthenticationGroups (
|
||||||
Authentication_ObjectGUID UNIQUEIDENTIFIER,
|
Authentication_ObjectGUID UNIQUEIDENTIFIER,
|
||||||
Group_ObjectGUID UNIQUEIDENTIFIER,
|
Group_ObjectGUID UNIQUEIDENTIFIER,
|
||||||
PRIMARY KEY (Authentication_ObjectGUID, Group_ObjectGUID)
|
PRIMARY KEY (Authentication_ObjectGUID, Group_ObjectGUID)
|
||||||
);
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
CREATE TABLE dbo.GroupRoles (
|
CREATE TABLE dbo.GroupRoles (
|
||||||
Group_ObjectGUID UNIQUEIDENTIFIER,
|
Group_ObjectGUID UNIQUEIDENTIFIER,
|
||||||
Role_ID INT,
|
Role_ID INT,
|
||||||
PRIMARY KEY (Group_ObjectGUID, Role_ID)
|
PRIMARY KEY (Group_ObjectGUID, Role_ID)
|
||||||
);
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
CREATE TABLE dbo.RolePermissions (
|
CREATE TABLE dbo.RolePermissions (
|
||||||
Role_ID INT,
|
Role_ID INT,
|
||||||
Permission_ID INT,
|
Permission_ID INT,
|
||||||
PRIMARY KEY (Role_ID, Permission_ID)
|
PRIMARY KEY (Role_ID, Permission_ID)
|
||||||
);
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
/* =========================================================
|
/* =========================================================
|
||||||
EVENT SYSTEM
|
EVENT SYSTEM
|
||||||
@@ -215,6 +218,7 @@ CREATE TABLE dbo.NotifyTrayObjects (
|
|||||||
CreatedAt DATETIME2,
|
CreatedAt DATETIME2,
|
||||||
ExpiresAt DATETIME2
|
ExpiresAt DATETIME2
|
||||||
);
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
CREATE TABLE dbo.NotifyTray (
|
CREATE TABLE dbo.NotifyTray (
|
||||||
ID INT IDENTITY(1,1) PRIMARY KEY,
|
ID INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
@@ -222,7 +226,7 @@ CREATE TABLE dbo.NotifyTray (
|
|||||||
NotifyTrayObject_ID INT,
|
NotifyTrayObject_ID INT,
|
||||||
SeenAt DATETIME2
|
SeenAt DATETIME2
|
||||||
);
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
/* =========================================================
|
/* =========================================================
|
||||||
SECURITY VIEWS
|
SECURITY VIEWS
|
||||||
@@ -241,7 +245,7 @@ FROM dbo.Authentication a
|
|||||||
JOIN dbo.AuthenticationGroups ag ON ag.Authentication_ObjectGUID = a.ObjectGUID
|
JOIN dbo.AuthenticationGroups ag ON ag.Authentication_ObjectGUID = a.ObjectGUID
|
||||||
JOIN dbo.GroupRoles gr ON gr.Group_ObjectGUID = ag.Group_ObjectGUID
|
JOIN dbo.GroupRoles gr ON gr.Group_ObjectGUID = ag.Group_ObjectGUID
|
||||||
JOIN dbo.[Role] r ON r.ID = gr.Role_ID;
|
JOIN dbo.[Role] r ON r.ID = gr.Role_ID;
|
||||||
|
GO
|
||||||
|
|
||||||
CREATE VIEW dbo.vAuthenticationEffectivePermissions AS
|
CREATE VIEW dbo.vAuthenticationEffectivePermissions AS
|
||||||
SELECT DISTINCT
|
SELECT DISTINCT
|
||||||
@@ -254,7 +258,7 @@ FROM dbo.Authentication a
|
|||||||
JOIN dbo.vAuthenticationRoles r ON r.ObjectGUID = a.ObjectGUID
|
JOIN dbo.vAuthenticationRoles r ON r.ObjectGUID = a.ObjectGUID
|
||||||
JOIN dbo.RolePermissions rp ON rp.Role_ID = r.Role_ID
|
JOIN dbo.RolePermissions rp ON rp.Role_ID = r.Role_ID
|
||||||
JOIN dbo.Permission p ON p.ID = rp.Permission_ID;
|
JOIN dbo.Permission p ON p.ID = rp.Permission_ID;
|
||||||
|
GO
|
||||||
|
|
||||||
/* =========================================================
|
/* =========================================================
|
||||||
FIXED vEventLog (SEQUELIZE MATCH + SYSTEM FIX)
|
FIXED vEventLog (SEQUELIZE MATCH + SYSTEM FIX)
|
||||||
@@ -308,7 +312,7 @@ CREATE VIEW dbo.vAuthentications AS
|
|||||||
SELECT a.*, os.Name AS ObjectSource
|
SELECT a.*, os.Name AS ObjectSource
|
||||||
FROM dbo.Authentication a
|
FROM dbo.Authentication a
|
||||||
LEFT JOIN dbo.ObjectSource os ON os.ID = a.ObjectSource_ID;
|
LEFT JOIN dbo.ObjectSource os ON os.ID = a.ObjectSource_ID;
|
||||||
|
GO
|
||||||
|
|
||||||
/* =========================================================
|
/* =========================================================
|
||||||
GROUP VIEW
|
GROUP VIEW
|
||||||
@@ -316,7 +320,7 @@ LEFT JOIN dbo.ObjectSource os ON os.ID = a.ObjectSource_ID;
|
|||||||
|
|
||||||
CREATE VIEW dbo.vGroupHierarchy AS
|
CREATE VIEW dbo.vGroupHierarchy AS
|
||||||
SELECT * FROM dbo.GroupClosure;
|
SELECT * FROM dbo.GroupClosure;
|
||||||
|
GO
|
||||||
|
|
||||||
/* =========================================================
|
/* =========================================================
|
||||||
NOTIFY VIEWS
|
NOTIFY VIEWS
|
||||||
|
|||||||
@@ -135,8 +135,8 @@ const server = https.createServer(httpsOptions, app);
|
|||||||
databaseModel.set('roleModel', require(`@models/roleModel`)(service.get('sqlManager').getInstance('main')));
|
databaseModel.set('roleModel', require(`@models/roleModel`)(service.get('sqlManager').getInstance('main')));
|
||||||
databaseModel.set('rolePermissionsModel', require(`@models/rolePermissionsModel`)(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('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))
|
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
|
require(`${app.locals.path.source}/routes/adminRoutes.js`).route(app, service); // #3 - token security always enabled
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
app.use(service.get('authenticationManager').authenticate());
|
app.use(service.get('rbacManager').authenticate());
|
||||||
|
|
||||||
//#region Implements sockets
|
//#region Implements sockets
|
||||||
require(`${app.locals.path.source}/sockets/mainSocket.js`)(
|
require(`${app.locals.path.source}/sockets/mainSocket.js`)(
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ module.exports = {
|
|||||||
|
|
||||||
|
|
||||||
// Geschützte Route
|
// 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({
|
res.json(JSON.stringify({
|
||||||
user: {
|
user: {
|
||||||
name: req.user
|
name: req.user
|
||||||
@@ -63,7 +63,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Logout
|
// 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);
|
const logout = await service.get('authenticationManager').logout(req.user.sAMAccountName);
|
||||||
|
|
||||||
// socketManager.sendTo('/', req.user.objectGuid, 'login_status', { levelId: logout.levelId, message: logout.message } )
|
// socketManager.sendTo('/', req.user.objectGuid, 'login_status', { levelId: logout.levelId, message: logout.message } )
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ const jwt = require('jsonwebtoken');
|
|||||||
const bcrypt = require('bcryptjs');
|
const bcrypt = require('bcryptjs');
|
||||||
|
|
||||||
class AuthenticationManager {
|
class AuthenticationManager {
|
||||||
|
|
||||||
constructor(model, secretKey) {
|
constructor(model, secretKey) {
|
||||||
this.Authentication = model;
|
this.Authentication = model;
|
||||||
this.SECRET_KEY = secretKey;
|
this.SECRET_KEY = secretKey;
|
||||||
@@ -113,81 +114,6 @@ class AuthenticationManager {
|
|||||||
return { valid: false, levelId: 4 };
|
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;
|
module.exports = AuthenticationManager;
|
||||||
@@ -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) {
|
normalize(permissions) {
|
||||||
return permissions.map(p => ({
|
return permissions.map(p => ({
|
||||||
scope: p.scope,
|
scope: p.scope,
|
||||||
|
|||||||
5
utils.js
5
utils.js
@@ -54,10 +54,7 @@ module.exports = startMenuItems = async function (app, objectGuid, debug = false
|
|||||||
// Load user permissions
|
// Load user permissions
|
||||||
// =========================
|
// =========================
|
||||||
const rbacManager = service.get('rbacManager');
|
const rbacManager = service.get('rbacManager');
|
||||||
|
const userPermissions = objectGuid === undefined ? [] : (await rbacManager.resolvePermissions(objectGuid))?.permissions;
|
||||||
const userPermissions =
|
|
||||||
(await rbacManager.resolvePermissions(objectGuid))
|
|
||||||
?.permissions || [];
|
|
||||||
|
|
||||||
const normalizedPermissions = userPermissions.map(p => ({
|
const normalizedPermissions = userPermissions.map(p => ({
|
||||||
scope: p.scope,
|
scope: p.scope,
|
||||||
|
|||||||
Reference in New Issue
Block a user