auth bugfix + licences
This commit is contained in:
17
dbcreate.sql
17
dbcreate.sql
@@ -43,12 +43,29 @@ DROP TABLE IF EXISTS dbo.Permission;
|
|||||||
DROP TABLE IF EXISTS dbo.Plugins;
|
DROP TABLE IF EXISTS dbo.Plugins;
|
||||||
DROP TABLE IF EXISTS dbo.ObjectSource;
|
DROP TABLE IF EXISTS dbo.ObjectSource;
|
||||||
DROP TABLE IF EXISTS dbo.AuthenticationUAC;
|
DROP TABLE IF EXISTS dbo.AuthenticationUAC;
|
||||||
|
DROP TABLE IF EXISTS dbo.Vault;
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
|
||||||
/* =========================================================
|
/* =========================================================
|
||||||
CORE TABLES
|
CORE TABLES
|
||||||
========================================================= */
|
========================================================= */
|
||||||
|
CREATE TABLE Vault (
|
||||||
|
ID UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(),
|
||||||
|
|
||||||
|
Customer_ID NVARCHAR(128) NOT NULL, -- ehem. tenantId
|
||||||
|
Feature NVARCHAR(128) NOT NULL, -- z.B. AD_SYNC, DEMO_PLUGIN
|
||||||
|
|
||||||
|
Payload NVARCHAR(MAX) NOT NULL, -- flexible JSON (config, limits etc.)
|
||||||
|
Signature NVARCHAR(MAX) NOT NULL, -- RSA-Signatur (Base64)
|
||||||
|
|
||||||
|
Active BIT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
ExpiresAt DATETIME NULL,
|
||||||
|
|
||||||
|
CreatedAt DATETIME NOT NULL DEFAULT GETDATE(),
|
||||||
|
UpdatedAt DATETIME NULL DEFAULT GETDATE()
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE dbo.ObjectSource (
|
CREATE TABLE dbo.ObjectSource (
|
||||||
ID INT IDENTITY(1,1) PRIMARY KEY,
|
ID INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
|||||||
0
public/views/authentications.hbs
Normal file
0
public/views/authentications.hbs
Normal file
@@ -56,10 +56,9 @@
|
|||||||
<li><hr></li>
|
<li><hr></li>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if this.authorized}}
|
{{#if this.authorized}}
|
||||||
<li class="start-item {{#unless ../this.active}}unload{{/unless}}" data-active="{{#equaler ../this.active "&&" this.authorized}}true{{else}}false{{/equaler}}" data-appname="{{../this.name}}" data-appview="{{this.view}}" data-viewlabel="{{this.label}}">
|
<li class="start-item {{#unless ../this.active}}unload{{/unless}}" {{#if this.description}}data-tooltip="{{this.description}}"{{/if}} data-active="{{#equaler ../this.active "&&" this.authorized}}true{{else}}false{{/equaler}}" data-appname="{{../this.name}}" data-appview="{{this.view}}" data-viewlabel="{{this.label}}">
|
||||||
{{#if this.icon}}
|
{{#if this.icon}}
|
||||||
<img src="{{#if ../this.pluginPath}}/{{../this.name}}{{/if}}/images/{{this.icon}}" class="start-icon" />
|
<img src="{{#if ../this.pluginPath}}/{{../this.name}}{{/if}}/images/{{this.icon}}" class="start-icon" />
|
||||||
{{else}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<span>{{this.label}}</span>
|
<span>{{this.label}}</span>
|
||||||
{{#if this.version}}<small>v{{this.version}}</small>{{/if}}
|
{{#if this.version}}<small>v{{this.version}}</small>{{/if}}
|
||||||
|
|||||||
25
server.js
25
server.js
@@ -97,6 +97,7 @@ const server = https.createServer(httpsOptions, app);
|
|||||||
let FileSystemManager = require(`@services/fileSystemManager.js`);
|
let FileSystemManager = require(`@services/fileSystemManager.js`);
|
||||||
let AuthenticationManager = require(`@services/authenticationManager.js`);
|
let AuthenticationManager = require(`@services/authenticationManager.js`);
|
||||||
let ActiveDirectory = require(`@services/activeDirectoryManager.js`);
|
let ActiveDirectory = require(`@services/activeDirectoryManager.js`);
|
||||||
|
let VaultifyManager = require(`@services/vaultifyManager.js`);
|
||||||
|
|
||||||
service.set('socketManager', new SocketManager(io));
|
service.set('socketManager', new SocketManager(io));
|
||||||
await service.get('socketManager').addAsync('/');
|
await service.get('socketManager').addAsync('/');
|
||||||
@@ -129,10 +130,9 @@ const server = https.createServer(httpsOptions, app);
|
|||||||
databaseModel.set('permissionModel', require(`@models/permissionModel`)(service.get('sqlManager').getInstance('main')));
|
databaseModel.set('permissionModel', require(`@models/permissionModel`)(service.get('sqlManager').getInstance('main')));
|
||||||
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, databaseModel));
|
service.set('authenticationManager', new AuthenticationManager(databaseModel.get('authentication'), app.locals.configuration.integration.token.secret, databaseModel));
|
||||||
|
|
||||||
|
// service.set('vaultifyManager', new VaultifyManager());
|
||||||
service.set('activeDirectoryManager', new ActiveDirectory(app.locals.configuration.integration.activedirectory))
|
service.set('activeDirectoryManager', new ActiveDirectory(app.locals.configuration.integration.activedirectory))
|
||||||
|
|
||||||
// everytime last created service!
|
// everytime last created service!
|
||||||
@@ -149,6 +149,8 @@ const server = https.createServer(httpsOptions, app);
|
|||||||
let helpers = service.get('fileSystemManager').loadAllFiles(`${app.locals.path.public}/helpers`, '.js');
|
let helpers = service.get('fileSystemManager').loadAllFiles(`${app.locals.path.public}/helpers`, '.js');
|
||||||
exports.helpers = helpers;
|
exports.helpers = helpers;
|
||||||
|
|
||||||
|
// app.use(service.get('vaultifyManager').createMiddleware());
|
||||||
|
|
||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ extended: true }));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
@@ -214,22 +216,9 @@ const server = https.createServer(httpsOptions, app);
|
|||||||
|
|
||||||
|
|
||||||
//#region Implement routes
|
//#region Implement routes
|
||||||
require(`${app.locals.path.source}/routes/indexRoutes.js`).route(app, service);
|
require(`${app.locals.path.source}/routes/loginRoutes.js`).route(app, service); // #1 - no token security! important: first!!!
|
||||||
require(`${app.locals.path.source}/routes/loginRoutes.js`).route(
|
require(`${app.locals.path.source}/routes/indexRoutes.js`).route(app, service); // #2 - token security enabled at this point
|
||||||
app,
|
require(`${app.locals.path.source}/routes/adminRoutes.js`).route(app, service); // #3 - token security always enabled
|
||||||
service.get('authenticationManager'),
|
|
||||||
service.get('socketManager'),
|
|
||||||
service.get('eventManager')
|
|
||||||
);
|
|
||||||
require(`${app.locals.path.source}/routes/adminRoutes.js`).route(
|
|
||||||
app,
|
|
||||||
service.get('authenticationManager'),
|
|
||||||
service.get('pluginManager'),
|
|
||||||
service.get('eventManager'),
|
|
||||||
service.get('socketManager'),
|
|
||||||
service.get('activeDirectoryManager'),
|
|
||||||
`${app.locals.path.source}/models/stylesheet.json`
|
|
||||||
);
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,23 @@
|
|||||||
"action": "Administration"
|
"action": "Administration"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "RBAC",
|
||||||
|
"description": "Role-Based Access Control ist eine rollenbasierte Zugriffskontrolle, die auf Basis von Rollen und Gruppen, systemweite Berechtigungen vergibt",
|
||||||
|
"view": "rbac.hbs",
|
||||||
|
"defaultSize": {
|
||||||
|
"width": "800px",
|
||||||
|
"height": "600px"
|
||||||
|
},
|
||||||
|
"icon": "app.png",
|
||||||
|
"license": "rbac",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"scope": "SYSTEM",
|
||||||
|
"action": "Administration"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
59
src/models/vaulModel.js
Normal file
59
src/models/vaulModel.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
const { DataTypes } = require('sequelize');
|
||||||
|
|
||||||
|
module.exports = (sequelize) => {
|
||||||
|
|
||||||
|
const Vault = sequelize.define('Vault', {
|
||||||
|
|
||||||
|
ID: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
primaryKey: true,
|
||||||
|
defaultValue: DataTypes.UUIDV4
|
||||||
|
},
|
||||||
|
|
||||||
|
Customer_ID: {
|
||||||
|
type: DataTypes.STRING(128),
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
|
||||||
|
Feature: {
|
||||||
|
type: DataTypes.STRING(128),
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
|
||||||
|
Payload: {
|
||||||
|
type: DataTypes.TEXT, // NVARCHAR(MAX)
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
|
||||||
|
Signature: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
|
||||||
|
Active: {
|
||||||
|
type: DataTypes.BOOLEAN,
|
||||||
|
defaultValue: true
|
||||||
|
},
|
||||||
|
|
||||||
|
ExpiresAt: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
allowNull: true
|
||||||
|
},
|
||||||
|
|
||||||
|
CreatedAt: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
defaultValue: DataTypes.NOW
|
||||||
|
},
|
||||||
|
|
||||||
|
UpdatedAt: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
defaultValue: DataTypes.NOW
|
||||||
|
}
|
||||||
|
|
||||||
|
}, {
|
||||||
|
tableName: 'Vault',
|
||||||
|
timestamps: false
|
||||||
|
});
|
||||||
|
|
||||||
|
return Vault;
|
||||||
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { service } = require('@root/server.js');
|
|
||||||
|
|
||||||
|
|
||||||
const configurationFile = path.join(require('@root/server.js').path.source, 'models', 'configuration.json');
|
const configurationFile = path.join(require('@root/server.js').path.source, 'models', 'configuration.json');
|
||||||
@@ -10,7 +9,7 @@ const serverInfoFile = path.join(require('@root/server.js').path.root, 'package.
|
|||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
route(app, authenticationManager, pluginManager, eventManager, socketManager, activeDirectoryManager, stylesheetJson) {
|
route(app, service) {
|
||||||
// JSON configuration abrufen
|
// JSON configuration abrufen
|
||||||
app.post('/api/getConfig', (req, res) => {
|
app.post('/api/getConfig', (req, res) => {
|
||||||
fs.readFile(configurationFile, 'utf8', (err, data) => {
|
fs.readFile(configurationFile, 'utf8', (err, data) => {
|
||||||
@@ -62,7 +61,7 @@ module.exports = {
|
|||||||
|
|
||||||
|
|
||||||
app.post('/api/eventlog/clearlog', (req, res) => {
|
app.post('/api/eventlog/clearlog', (req, res) => {
|
||||||
eventManager.clear();
|
service.get('eventManager').clear();
|
||||||
res.status(200).send({ status: 'ok' })
|
res.status(200).send({ status: 'ok' })
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -87,10 +86,10 @@ module.exports = {
|
|||||||
res.status(200).send({ status: 'ok' });
|
res.status(200).send({ status: 'ok' });
|
||||||
// exec(`kill -9 ${process.pid}`, (error, stdout, stderr) => {
|
// exec(`kill -9 ${process.pid}`, (error, stdout, stderr) => {
|
||||||
// if (error) {
|
// if (error) {
|
||||||
// service.get('eventManager').write(req.cookies.ObjectGUID, 4, null, error.message);
|
// service.get('service.get('eventManager')').write(req.cookies.ObjectGUID, 4, null, error.message);
|
||||||
// return res.status(500).send({ status: 'error', message: error.message });
|
// return res.status(500).send({ status: 'error', message: error.message });
|
||||||
// }
|
// }
|
||||||
// service.get('eventManager').write(req.cookies.ObjectGUID, 0, null, `Server neu gestartet`);
|
// service.get('service.get('eventManager')').write(req.cookies.ObjectGUID, 0, null, `Server neu gestartet`);
|
||||||
// res.status(200).send({ status: 'ok' });
|
// res.status(200).send({ status: 'ok' });
|
||||||
// });
|
// });
|
||||||
});
|
});
|
||||||
@@ -100,22 +99,19 @@ module.exports = {
|
|||||||
const { name, state } = req.body;
|
const { name, state } = req.body;
|
||||||
let result = null;
|
let result = null;
|
||||||
if(state) {
|
if(state) {
|
||||||
result = await pluginManager.load(name, true);
|
result = await service.get('pluginManager').load(name, true);
|
||||||
} else {
|
} else {
|
||||||
result = await pluginManager.unload(name);
|
result = await service.get('pluginManager').unload(name);
|
||||||
}
|
}
|
||||||
console.log(result)
|
|
||||||
// result = { ...result, authorized: result.metadata.permissions.some(async permission => { await activeDirectoryManager.getGroup(permission) != null && await activeDirectoryManager.isUserMemberOfRecursive(req.cookies.sAMAccountName, permission)}) }
|
|
||||||
|
|
||||||
eventManager.write(null, result.levelId, name, result.message);
|
service.get('eventManager').write(null, result.levelId, name, result.message);
|
||||||
// socketManager.broadcast('admin', 'plugin_status', result);
|
service.get('socketManager').broadcast('/', 'plugin_status', result);
|
||||||
socketManager.broadcast('/', 'plugin_status', result);
|
|
||||||
res.status(200).json(result);
|
res.status(200).json(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/api/plugins/getAll', async (req, res) => {
|
app.post('/api/plugins/getAll', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const plugins = await pluginManager.getStatus();
|
const plugins = await service.get('pluginManager').getStatus();
|
||||||
res.status(200).json(plugins);
|
res.status(200).json(plugins);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error.message });
|
res.status(500).json({ error: error.message });
|
||||||
@@ -134,12 +130,12 @@ module.exports = {
|
|||||||
const { name } = req.params;
|
const { name } = req.params;
|
||||||
try {
|
try {
|
||||||
const { updates } = req.body;
|
const { updates } = req.body;
|
||||||
const result = await pluginManager.update(name, updates);
|
const result = await service.get('pluginManager').update(name, updates);
|
||||||
// result = { ...result, authorized: result.metadata.permissions.some(async permission => { await activeDirectoryManager.getGroup(permission) != null && await activeDirectoryManager.isUserMemberOfRecursive(req.cookies.sAMAccountName, permission)}) }
|
// result = { ...result, authorized: result.metadata.permissions.some(async permission => { await activeDirectoryManager.getGroup(permission) != null && await activeDirectoryManager.isUserMemberOfRecursive(req.cookies.sAMAccountName, permission)}) }
|
||||||
|
|
||||||
service.get('eventManager').writeLog(req.cookies.ObjectGUID, result.levelId, name, result.message);
|
service.get('eventManager').writeLog(req.cookies.ObjectGUID, result.levelId, name, result.message);
|
||||||
// socketManager.broadcast('admin', 'plugin_status', result);
|
// service.get('socketManager').broadcast('admin', 'plugin_status', result);
|
||||||
// socketManager.broadcast('/', 'plugin_status', result);
|
// service.get('socketManager').broadcast('/', 'plugin_status', result);
|
||||||
res.status(200).json(result);
|
res.status(200).json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
service.get('eventManager').write(req.cookies.ObjectGUID, 4, name, `Fehler beim Aktualisieren des Plugins: ${error}`);
|
service.get('eventManager').write(req.cookies.ObjectGUID, 4, name, `Fehler beim Aktualisieren des Plugins: ${error}`);
|
||||||
@@ -153,30 +149,30 @@ module.exports = {
|
|||||||
const result = await service.get('pluginManager').rename(name, newName);
|
const result = await service.get('pluginManager').rename(name, newName);
|
||||||
|
|
||||||
// const result = { levelId: 0, pluginName: name, message: `Plugin erstellt` };
|
// const result = { levelId: 0, pluginName: name, message: `Plugin erstellt` };
|
||||||
// await pluginManager.create(name);
|
// await service.get('pluginManager').create(name);
|
||||||
// res.status(200).json(result);
|
// res.status(200).json(result);
|
||||||
|
|
||||||
eventManager.writeLog(null, result.levelId, name, result.message);
|
service.get('eventManager').writeLog(null, result.levelId, name, result.message);
|
||||||
// socketManager.broadcast('admin', 'plugin_status', result);
|
// service.get('socketManager').broadcast('admin', 'plugin_status', result);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/api/plugins/:name/create', async (req, res) => {
|
app.post('/api/plugins/:name/create', async (req, res) => {
|
||||||
const { name } = req.params;
|
const { name } = req.params;
|
||||||
const result = { levelId: 0, pluginName: name, message: `Plugin erstellt` };
|
const result = { levelId: 0, pluginName: name, message: `Plugin erstellt` };
|
||||||
await pluginManager.create(name);
|
await service.get('pluginManager').create(name);
|
||||||
|
|
||||||
eventManager.writeLog(null, result.levelId, name, result.message);
|
service.get('eventManager').writeLog(null, result.levelId, name, result.message);
|
||||||
res.status(200).json(result);
|
res.status(200).json(result);
|
||||||
// socketManager.broadcast('admin', 'plugin_status', result);
|
// service.get('socketManager').broadcast('admin', 'plugin_status', result);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/admin/plugins/:name/delete', async (req, res) => {
|
app.post('/admin/plugins/:name/delete', async (req, res) => {
|
||||||
const { name } = req.params;
|
const { name } = req.params;
|
||||||
const result = { status: 'delete', pluginName: name, levelId: 0, message: `Plugin ${name} gelöscht` }; //await pluginManager.delete(name);
|
const result = { status: 'delete', pluginName: name, levelId: 0, message: `Plugin ${name} gelöscht` }; //await service.get('pluginManager').delete(name);
|
||||||
res.status(200).json(result);
|
res.status(200).json(result);
|
||||||
|
|
||||||
eventManager.write(null, result.levelId, name, result.message);
|
service.get('eventManager').write(null, result.levelId, name, result.message);
|
||||||
socketManager.broadcast('admin', 'plugin_status', result);
|
service.get('socketManager').broadcast('admin', 'plugin_status', result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ const { doesNotReject } = require('assert');
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
route: function(app, service) {
|
route: function(app, service) {
|
||||||
app.get('/', service.get('authenticationManager').authenticate(), async (req, res) => {
|
app.use(service.get('authenticationManager').authenticate());
|
||||||
console.log(req.cookies.ObjectGUID)
|
|
||||||
|
app.get('/', async (req, res) => {
|
||||||
const startMenuItems = await global.startMenuItems(app, req.cookies.ObjectGUID, false);
|
const startMenuItems = await global.startMenuItems(app, req.cookies.ObjectGUID, false);
|
||||||
res.render('desktop', { layout: 'default', startMenuItems: startMenuItems });
|
res.render('desktop', { layout: 'default', startMenuItems: startMenuItems });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
const { verify } = require("jsonwebtoken");
|
const { verify } = require("jsonwebtoken");
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
route(app, authenticationManager, socketManager, eventManager) {
|
route(app, service) {
|
||||||
app.get(`/login`, (req, res) => {
|
app.get(`/login`, (req, res) => {
|
||||||
res.render(`login`, { layout: 'default' });
|
res.render(`login`, { layout: 'default' });
|
||||||
})
|
})
|
||||||
|
|
||||||
app.post('/login', async (req, res) => {
|
app.post('/login', async (req, res) => {
|
||||||
const { sAMAccountName, password } = req.body;
|
const { sAMAccountName, password } = req.body;
|
||||||
const userModel = await authenticationManager.Authentication.findOne({
|
const userModel = await service.get('authenticationManager').Authentication.findOne({
|
||||||
where: { sAMAccountName: sAMAccountName }, attributes: ['ObjectGUID'],
|
where: { sAMAccountName: sAMAccountName }, attributes: ['ObjectGUID'],
|
||||||
raw: true
|
raw: true
|
||||||
});
|
});
|
||||||
@@ -28,9 +29,9 @@ module.exports = {
|
|||||||
sameSite: 'Strict',
|
sameSite: 'Strict',
|
||||||
maxAge: 1000 * 60 * 60 * 24 * 365
|
maxAge: 1000 * 60 * 60 * 24 * 365
|
||||||
})
|
})
|
||||||
const login = await authenticationManager.login(sAMAccountName, password);
|
const login = await service.get('authenticationManager').login(sAMAccountName, password);
|
||||||
|
|
||||||
eventManager.writeLog(objectGuid, login.levelId, null, login.message);
|
service.get('eventManager').writeLog(objectGuid, login.levelId, null, login.message);
|
||||||
res.status(login.levelId == 0 ? 200 : 401).json(login);
|
res.status(login.levelId == 0 ? 200 : 401).json(login);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(500).json(login);
|
res.status(500).json(login);
|
||||||
@@ -39,7 +40,7 @@ module.exports = {
|
|||||||
|
|
||||||
|
|
||||||
// Geschützte Route
|
// Geschützte Route
|
||||||
app.get('/me', authenticationManager.authenticate(), (req, res) => {
|
app.get('/me', service.get('authenticationManager').authenticate(), (req, res) => {
|
||||||
res.json(JSON.stringify({
|
res.json(JSON.stringify({
|
||||||
user: {
|
user: {
|
||||||
name: req.user
|
name: req.user
|
||||||
@@ -50,28 +51,28 @@ module.exports = {
|
|||||||
app.post('/checkLoginName', async (req, res) => {
|
app.post('/checkLoginName', async (req, res) => {
|
||||||
const { sAMAccountName } = req.body;
|
const { sAMAccountName } = req.body;
|
||||||
|
|
||||||
const userExists = await authenticationManager.Authentication.findOne({ where: { sAMAccountName: sAMAccountName } });
|
const userExists = await service.get('authenticationManager').Authentication.findOne({ where: { sAMAccountName: sAMAccountName } });
|
||||||
const auth = { objectGuid: userExists != null ? userExists.ObjectGUID : sAMAccountName, sAMAccountName: sAMAccountName };
|
const auth = { objectGuid: userExists != null ? userExists.ObjectGUID : sAMAccountName, sAMAccountName: sAMAccountName };
|
||||||
res.status(userExists ? 200 : 404).json({ exists: userExists != null });
|
res.status(userExists ? 200 : 404).json({ exists: userExists != null });
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/verifying', async (req, res, next) => {
|
app.get('/verifying', async (req, res, next) => {
|
||||||
const verify = await authenticationManager.verifyUserToken();
|
const verify = await service.get('authenticationManager').verifyUserToken();
|
||||||
eventManager.write(req.user.objectGuid, verify.levelId, null, verify.message);
|
service.get('eventManager').writeLog(req.user.objectGuid, verify.levelId, null, verify.message);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Logout
|
// Logout
|
||||||
app.post('/logout', authenticationManager.authenticate(), async (req, res) => {
|
app.post('/logout', service.get('authenticationManager').authenticate(), async (req, res) => {
|
||||||
const logout = await 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 } )
|
||||||
eventManager.write(req.user.objectGuid, logout.levelId, null, logout.message);
|
service.get('eventManager').writeLog(req.user.objectGuid, logout.levelId, null, logout.message);
|
||||||
|
|
||||||
res.clearCookie('sAMAccountName');
|
res.clearCookie('sAMAccountName');
|
||||||
res.clearCookie('ObjectGUID');
|
res.clearCookie('ObjectGUID');
|
||||||
|
res.render('login', { layout: false, title: app.locals.configuration.server.name })
|
||||||
setTimeout(() => res.render('login', { layout: false, title: app.locals.configuration.server.name }), 3000);
|
// setTimeout(() => res.render('login', { layout: false, title: app.locals.configuration.server.name }), 3000);
|
||||||
// res.json({ message: 'Logout erfolgreich' });
|
// res.json({ message: 'Logout erfolgreich' });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ async resolvePermissions(objectGuid) {
|
|||||||
sAMAccountName: user.sAMAccountName
|
sAMAccountName: user.sAMAccountName
|
||||||
},
|
},
|
||||||
this.SECRET_KEY,
|
this.SECRET_KEY,
|
||||||
{ expiresIn: '10s' }
|
{ expiresIn: '1y' }
|
||||||
);
|
);
|
||||||
|
|
||||||
user.refreshtoken = token;
|
user.refreshtoken = token;
|
||||||
@@ -197,7 +197,17 @@ async resolvePermissions(objectGuid) {
|
|||||||
|
|
||||||
authenticate() {
|
authenticate() {
|
||||||
return async (req, res, next) => {
|
return async (req, res, next) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// 🔥 SKIP PUBLIC ROUTES
|
||||||
|
if (
|
||||||
|
req.path.startsWith('/login') ||
|
||||||
|
req.path.startsWith('/public')
|
||||||
|
) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
const sAMAccountName = req.cookies?.sAMAccountName;
|
const sAMAccountName = req.cookies?.sAMAccountName;
|
||||||
|
|
||||||
if (!sAMAccountName) {
|
if (!sAMAccountName) {
|
||||||
@@ -206,23 +216,30 @@ async resolvePermissions(objectGuid) {
|
|||||||
|
|
||||||
const user = await this.findUser(sAMAccountName);
|
const user = await this.findUser(sAMAccountName);
|
||||||
|
|
||||||
if (!user || !user.refreshtoken || !user.active) {
|
if (!user || !user.active) {
|
||||||
|
return res.redirect('/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
let payload;
|
||||||
|
|
||||||
|
try {
|
||||||
|
payload = jwt.verify(user.refreshtoken, this.SECRET_KEY);
|
||||||
|
} catch {
|
||||||
return res.redirect('/login');
|
return res.redirect('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
// jwt.verify(user.refreshtoken, this.SECRET_KEY);
|
|
||||||
this.verifyUserToken(sAMAccountName)
|
|
||||||
// 🔥 LIVE RBAC RESOLUTION (bei JEDEM REQUEST)
|
|
||||||
const rbac = await this.resolvePermissions(user.ObjectGUID);
|
const rbac = await this.resolvePermissions(user.ObjectGUID);
|
||||||
|
|
||||||
req.user = {
|
req.user = {
|
||||||
...user.toJSON(),
|
...user.toJSON(),
|
||||||
|
jwt: payload,
|
||||||
groups: rbac.groups,
|
groups: rbac.groups,
|
||||||
roles: rbac.roles,
|
roles: rbac.roles,
|
||||||
permissions: rbac.permissions
|
permissions: rbac.permissions
|
||||||
};
|
};
|
||||||
console.log(req.user)
|
|
||||||
next();
|
next();
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return res.redirect('/login');
|
return res.redirect('/login');
|
||||||
|
|||||||
199
src/services/vaultifyManager.js
Normal file
199
src/services/vaultifyManager.js
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
class VaultifyManager {
|
||||||
|
|
||||||
|
constructor({
|
||||||
|
vaultModel,
|
||||||
|
publicKey
|
||||||
|
}) {
|
||||||
|
this.Vault = vaultModel;
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
|
||||||
|
this.cache = new Map(); // feature cache per customer
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
createMiddleware() {
|
||||||
|
|
||||||
|
return async (req, res, next) => {
|
||||||
|
|
||||||
|
const customerId = req.user?.Customer_ID;
|
||||||
|
|
||||||
|
if (!customerId) {
|
||||||
|
return res.status(403).send('No customer');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.loadCustomer(customerId);
|
||||||
|
|
||||||
|
req.vault = {
|
||||||
|
has: (f) => this.has(customerId, f),
|
||||||
|
get: (f, p) => this.get(customerId, f, p)
|
||||||
|
};
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// LOAD ALL LICENSES FOR CUSTOMER
|
||||||
|
// =========================================================
|
||||||
|
|
||||||
|
async loadCustomer(customerId) {
|
||||||
|
|
||||||
|
const records = await this.Vault.findAll({
|
||||||
|
where: {
|
||||||
|
Customer_ID: customerId,
|
||||||
|
Active: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const resultMap = new Map();
|
||||||
|
|
||||||
|
for (const record of records) {
|
||||||
|
|
||||||
|
const valid = this.verify(record);
|
||||||
|
if (!valid) continue;
|
||||||
|
|
||||||
|
const payload = this.parsePayload(record.Payload);
|
||||||
|
|
||||||
|
resultMap.set(record.Feature, {
|
||||||
|
payload,
|
||||||
|
expiresAt: record.ExpiresAt
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cache.set(customerId, resultMap);
|
||||||
|
|
||||||
|
return {
|
||||||
|
customerId,
|
||||||
|
features: [...resultMap.keys()]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// VERIFY SIGNATURE
|
||||||
|
// =========================================================
|
||||||
|
|
||||||
|
verify(record) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = {
|
||||||
|
Customer_ID: record.Customer_ID,
|
||||||
|
Feature: record.Feature,
|
||||||
|
Payload: this.parsePayload(record.Payload),
|
||||||
|
ExpiresAt: record.ExpiresAt
|
||||||
|
};
|
||||||
|
|
||||||
|
const verifier = crypto.createVerify('RSA-SHA256');
|
||||||
|
|
||||||
|
verifier.update(JSON.stringify(data));
|
||||||
|
verifier.end();
|
||||||
|
|
||||||
|
return verifier.verify(
|
||||||
|
this.publicKey,
|
||||||
|
record.Signature,
|
||||||
|
'base64'
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// SAFE JSON PARSER
|
||||||
|
// =========================================================
|
||||||
|
|
||||||
|
parsePayload(payload) {
|
||||||
|
try {
|
||||||
|
return typeof payload === 'string'
|
||||||
|
? JSON.parse(payload)
|
||||||
|
: payload;
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// FEATURE CHECK
|
||||||
|
// =========================================================
|
||||||
|
|
||||||
|
has(customerId, feature) {
|
||||||
|
|
||||||
|
const customer = this.cache.get(customerId);
|
||||||
|
if (!customer) return false;
|
||||||
|
|
||||||
|
const entry = customer.get(feature);
|
||||||
|
if (!entry) return false;
|
||||||
|
|
||||||
|
if (entry.expiresAt && new Date(entry.expiresAt) < new Date()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// GET FEATURE CONFIG
|
||||||
|
// =========================================================
|
||||||
|
|
||||||
|
get(customerId, feature, path = null) {
|
||||||
|
|
||||||
|
const customer = this.cache.get(customerId);
|
||||||
|
if (!customer) return undefined;
|
||||||
|
|
||||||
|
const entry = customer.get(feature);
|
||||||
|
if (!entry) return undefined;
|
||||||
|
|
||||||
|
if (!path) return entry.payload;
|
||||||
|
|
||||||
|
return path
|
||||||
|
.split('.')
|
||||||
|
.reduce((obj, key) => obj?.[key], entry.payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// REFRESH SINGLE FEATURE
|
||||||
|
// =========================================================
|
||||||
|
|
||||||
|
async refreshFeature(customerId, feature) {
|
||||||
|
|
||||||
|
const record = await this.Vault.findOne({
|
||||||
|
where: {
|
||||||
|
Customer_ID: customerId,
|
||||||
|
Feature: feature,
|
||||||
|
Active: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!record) return false;
|
||||||
|
|
||||||
|
if (!this.verify(record)) return false;
|
||||||
|
|
||||||
|
const customer = this.cache.get(customerId) || new Map();
|
||||||
|
|
||||||
|
customer.set(feature, {
|
||||||
|
payload: this.parsePayload(record.Payload),
|
||||||
|
expiresAt: record.ExpiresAt
|
||||||
|
});
|
||||||
|
|
||||||
|
this.cache.set(customerId, customer);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// STATUS
|
||||||
|
// =========================================================
|
||||||
|
|
||||||
|
status(customerId) {
|
||||||
|
const customer = this.cache.get(customerId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
customerId,
|
||||||
|
features: customer ? [...customer.keys()] : []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = VaultifyManager;
|
||||||
Reference in New Issue
Block a user