table:vault update
This commit is contained in:
27
dbcreate.sql
27
dbcreate.sql
@@ -50,23 +50,20 @@ GO
|
|||||||
/* =========================================================
|
/* =========================================================
|
||||||
CORE TABLES
|
CORE TABLES
|
||||||
========================================================= */
|
========================================================= */
|
||||||
CREATE TABLE Vault (
|
CREATE TABLE dbo.Vault (
|
||||||
ID UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(),
|
ID int IDENTITY(1,1) NOT NULL,
|
||||||
|
CustomerGUID uniqueidentifier NOT NULL,
|
||||||
Customer_ID NVARCHAR(128) NOT NULL, -- ehem. tenantId
|
Feature nvarchar(128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||||
Feature NVARCHAR(128) NOT NULL, -- z.B. AD_SYNC, DEMO_PLUGIN
|
Payload nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||||
|
Signature nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||||
Payload NVARCHAR(MAX) NOT NULL, -- flexible JSON (config, limits etc.)
|
Active bit DEFAULT 1 NOT NULL,
|
||||||
Signature NVARCHAR(MAX) NOT NULL, -- RSA-Signatur (Base64)
|
ExpiresAt datetime NULL,
|
||||||
|
CreatedAt datetime DEFAULT getdate() NOT NULL,
|
||||||
Active BIT NOT NULL DEFAULT 1,
|
UpdatedAt datetime DEFAULT getdate() NULL,
|
||||||
|
CONSTRAINT PK__Vault__3214EC275180843D PRIMARY KEY (ID)
|
||||||
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,
|
||||||
Name VARCHAR(100) NOT NULL UNIQUE
|
Name VARCHAR(100) NOT NULL UNIQUE
|
||||||
|
|||||||
@@ -121,6 +121,9 @@ const server = https.createServer(httpsOptions, app);
|
|||||||
service.set('fileSystemManager', new FileSystemManager());
|
service.set('fileSystemManager', new FileSystemManager());
|
||||||
|
|
||||||
|
|
||||||
|
databaseModel.set('vault', require(`@models/vaultModel`)(service.get('sqlManager').getInstance('main')));
|
||||||
|
service.set('vaultifyManager', new VaultifyManager(databaseModel.get('vault'), "123"));
|
||||||
|
|
||||||
databaseModel.set('authenticationGroupsModel', require(`@models/authenticationGroupsModel`)(service.get('sqlManager').getInstance('main')));
|
databaseModel.set('authenticationGroupsModel', require(`@models/authenticationGroupsModel`)(service.get('sqlManager').getInstance('main')));
|
||||||
databaseModel.set('authenticationRolesModel', require(`@models/authenticationRolesModel`)(service.get('sqlManager').getInstance('main')));
|
databaseModel.set('authenticationRolesModel', require(`@models/authenticationRolesModel`)(service.get('sqlManager').getInstance('main')));
|
||||||
databaseModel.set('groupClosureModel', require(`@models/groupClosureModel`)(service.get('sqlManager').getInstance('main')));
|
databaseModel.set('groupClosureModel', require(`@models/groupClosureModel`)(service.get('sqlManager').getInstance('main')));
|
||||||
@@ -132,7 +135,6 @@ const server = https.createServer(httpsOptions, app);
|
|||||||
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!
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ module.exports = (sequelize) => {
|
|||||||
const Vault = sequelize.define('Vault', {
|
const Vault = sequelize.define('Vault', {
|
||||||
|
|
||||||
ID: {
|
ID: {
|
||||||
type: DataTypes.UUID,
|
type: DataTypes.INTEGER,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
defaultValue: DataTypes.UUIDV4
|
autoIncrement: true
|
||||||
},
|
},
|
||||||
|
|
||||||
Customer_ID: {
|
Customer_ID: {
|
||||||
type: DataTypes.STRING(128),
|
type: DataTypes.UUIDV4,
|
||||||
allowNull: false
|
allowNull: false
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1,302 +0,0 @@
|
|||||||
const { Op } = require('sequelize');
|
|
||||||
|
|
||||||
class IdentityManager {
|
|
||||||
constructor(adManager, AuthenticationModel) {
|
|
||||||
this.ad = adManager || null;
|
|
||||||
this.Authentication = AuthenticationModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* REQUIRED FIELDS (MANUAL USER)
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
REQUIRED_FIELDS = [
|
|
||||||
'sAMAccountName',
|
|
||||||
'mail',
|
|
||||||
'givenName',
|
|
||||||
'sn',
|
|
||||||
'password'
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* VALIDATE MANUAL USER
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
validateManualUser(user) {
|
|
||||||
const missing = [];
|
|
||||||
|
|
||||||
for (const field of this.REQUIRED_FIELDS) {
|
|
||||||
if (
|
|
||||||
user[field] === undefined ||
|
|
||||||
user[field] === null ||
|
|
||||||
user[field] === ''
|
|
||||||
) {
|
|
||||||
missing.push(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (missing.length) {
|
|
||||||
throw new Error(
|
|
||||||
`Fehlende Pflichtfelder: ${missing.join(', ')}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 🔍 Optional: einfache Zusatzvalidierungen
|
|
||||||
if (user.mail && !user.mail.includes('@')) {
|
|
||||||
throw new Error('Ungültige E-Mail-Adresse');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.password && user.password.length < 6) {
|
|
||||||
throw new Error('Passwort muss mindestens 6 Zeichen lang sein');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* FIXED MAPPING (AD → Authentication)
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
mapAdObject(obj) {
|
|
||||||
if (!obj || !obj.objectGUID) return null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
ObjectGUID: obj.objectGUID,
|
|
||||||
sAMAccountName: obj.sAMAccountName || obj.cn || null,
|
|
||||||
mail: obj.mail || null,
|
|
||||||
givenName: obj.givenName || null,
|
|
||||||
sn: obj.sn || null,
|
|
||||||
employeeID: obj.employeeID || null,
|
|
||||||
title: obj.title || null,
|
|
||||||
department: obj.department || null,
|
|
||||||
streetAddress: obj.streetAddress || null,
|
|
||||||
userAccountControl_ID: obj.userAccountControl || null,
|
|
||||||
authenticationType_ID: 1,
|
|
||||||
telephoneNumber: obj.telephoneNumber || null,
|
|
||||||
physicalDeliveryOfficeName: obj.physicalDeliveryOfficeName || null,
|
|
||||||
distinguishedName: obj.dn || null,
|
|
||||||
password: null,
|
|
||||||
refreshtoken: null,
|
|
||||||
active: true,
|
|
||||||
online: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* DEDUP (wie SQL UNION)
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
deduplicateByGUID(items) {
|
|
||||||
const map = new Map();
|
|
||||||
|
|
||||||
for (const item of items) {
|
|
||||||
if (!item?.ObjectGUID) continue;
|
|
||||||
map.set(item.ObjectGUID, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(map.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* TABLE CHECK / CREATE
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
async ensureTable() {
|
|
||||||
const qi = this.Authentication.sequelize.getQueryInterface();
|
|
||||||
const tables = await qi.showAllTables();
|
|
||||||
|
|
||||||
const exists = tables.includes('Authentication');
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
await this.Authentication.sync();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* CORE SYNC (INTELLIGENT)
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
async syncFromAD() {
|
|
||||||
if (!this.ad) {
|
|
||||||
throw new Error('AD nicht konfiguriert');
|
|
||||||
}
|
|
||||||
|
|
||||||
const [users, groups, computers] = await Promise.all([
|
|
||||||
this.ad.findUsers('*'),
|
|
||||||
this.ad.findGroups('*'),
|
|
||||||
this.ad.getComputers()
|
|
||||||
]);
|
|
||||||
|
|
||||||
const mapped = this.deduplicateByGUID([
|
|
||||||
...users.map(u => this.mapAdObject(u)),
|
|
||||||
...groups.map(g => this.mapAdObject(g)),
|
|
||||||
...computers.map(c => this.mapAdObject(c))
|
|
||||||
].filter(Boolean));
|
|
||||||
|
|
||||||
if (!mapped.length) {
|
|
||||||
return { total: 0, deactivated: 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.Authentication.bulkCreate(mapped, {
|
|
||||||
updateOnDuplicate: [
|
|
||||||
'mail',
|
|
||||||
'givenName',
|
|
||||||
'sn',
|
|
||||||
'employeeID',
|
|
||||||
'title',
|
|
||||||
'department',
|
|
||||||
'streetAddress',
|
|
||||||
'userAccountControl_ID',
|
|
||||||
'telephoneNumber',
|
|
||||||
'physicalDeliveryOfficeName',
|
|
||||||
'distinguishedName',
|
|
||||||
'active'
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const existing = await this.Authentication.findAll({
|
|
||||||
where: { authenticationType_ID: 1 },
|
|
||||||
attributes: ['ObjectGUID']
|
|
||||||
});
|
|
||||||
|
|
||||||
const adGuids = new Set(mapped.map(u => u.ObjectGUID));
|
|
||||||
|
|
||||||
const toDeactivate = existing
|
|
||||||
.filter(e => !adGuids.has(e.ObjectGUID))
|
|
||||||
.map(e => e.ObjectGUID);
|
|
||||||
|
|
||||||
if (toDeactivate.length) {
|
|
||||||
await this.Authentication.update(
|
|
||||||
{ active: false },
|
|
||||||
{
|
|
||||||
where: {
|
|
||||||
ObjectGUID: toDeactivate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
total: mapped.length,
|
|
||||||
deactivated: toDeactivate.length,
|
|
||||||
adGuids: Array.from(adGuids)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* OPTIONAL: HARD DELETE
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
async removeDeletedADObjects(adGuids) {
|
|
||||||
return this.Authentication.destroy({
|
|
||||||
where: {
|
|
||||||
authenticationType_ID: 1,
|
|
||||||
ObjectGUID: {
|
|
||||||
[Op.notIn]: adGuids
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* RECREATE
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
async recreateAuthentications(hardReset = false) {
|
|
||||||
let message = '';
|
|
||||||
|
|
||||||
const exists = await this.ensureTable();
|
|
||||||
|
|
||||||
if (!exists) {
|
|
||||||
message = 'Tabelle wurde neu erstellt ';
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await this.syncFromAD();
|
|
||||||
|
|
||||||
message += `Sync abgeschlossen (${result.total} Objekte)`;
|
|
||||||
|
|
||||||
if (result.deactivated) {
|
|
||||||
message += `, ${result.deactivated} deaktiviert`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hardReset) {
|
|
||||||
const deleted = await this.removeDeletedADObjects(result.adGuids);
|
|
||||||
message += `, ${deleted} gelöscht`;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
message += 'Fehler: ' + err.message;
|
|
||||||
}
|
|
||||||
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* MANUAL USER (MIT VALIDATION)
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
async createManualUser(user) {
|
|
||||||
this.validateManualUser(user);
|
|
||||||
|
|
||||||
return this.Authentication.create({
|
|
||||||
...user,
|
|
||||||
authenticationType_ID: 2,
|
|
||||||
active: true,
|
|
||||||
online: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* MANUAL BULK (MIT VALIDATION)
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
async createManualUsers(users) {
|
|
||||||
const errors = [];
|
|
||||||
|
|
||||||
users.forEach((user, index) => {
|
|
||||||
try {
|
|
||||||
this.validateManualUser(user);
|
|
||||||
} catch (err) {
|
|
||||||
errors.push(`User ${index}: ${err.message}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (errors.length) {
|
|
||||||
throw new Error(errors.join(' | '));
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.Authentication.bulkCreate(
|
|
||||||
users.map(user => ({
|
|
||||||
...user,
|
|
||||||
authenticationType_ID: 2,
|
|
||||||
active: true,
|
|
||||||
online: false
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* -----------------------------------------------------
|
|
||||||
* GET USER
|
|
||||||
* -----------------------------------------------------
|
|
||||||
*/
|
|
||||||
async getUser(username) {
|
|
||||||
return this.Authentication.findOne({
|
|
||||||
where: { sAMAccountName: username }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = IdentityManager;
|
|
||||||
Reference in New Issue
Block a user