initial files

This commit is contained in:
2026-04-22 11:55:23 +02:00
commit 92444ff38c
85 changed files with 16324 additions and 0 deletions

View File

@@ -0,0 +1,258 @@
const ActiveDirectory = require('activedirectory2');
class ActiveDirectoryManager {
constructor({
url,
baseDN,
username,
password,
userAttributes,
groupAttributes,
computerAttributes
}) {
this.ad = new ActiveDirectory({
url,
baseDN,
username,
password,
attributes: {
user: userAttributes,
group: groupAttributes,
computer: computerAttributes
}
});
this.userAttributes = userAttributes;
this.groupAttributes = groupAttributes;
this.computerAttributes = computerAttributes;
}
/**
* -----------------------------------------------------
* INTERNAL GENERIC LDAP SEARCH
* -----------------------------------------------------
*/
async ldapSearch(options) {
return new Promise((resolve, reject) => {
this.ad.find(options, (err, result) => {
if (err) return reject(err);
resolve(result || {});
});
});
}
/**
* -----------------------------------------------------
* USER FUNCTIONS
* -----------------------------------------------------
*/
async getUser(username, attributes = this.userAttributes) {
return new Promise((resolve, reject) => {
this.ad.findUser({ attributes }, username, (err, user) => {
if (err) return reject(err);
resolve(user || null);
});
});
}
async getUserDN(username) {
const user = await this.getUser(username);
return user?.dn || null;
}
async findUsers(query, attributes = this.userAttributes) {
return new Promise((resolve, reject) => {
const filter = `(&(objectClass=user)(|(cn=${query})(sAMAccountName=${query})(mail=${query})(displayName=${query})))`;
this.ad.findUsers({ filter, attributes }, (err, users) => {
if (err) return reject(err);
resolve(users || []);
});
});
}
/**
* -----------------------------------------------------
* GROUP FUNCTIONS
* -----------------------------------------------------
*/
async getGroup(groupName, attributes = this.groupAttributes) {
return new Promise((resolve, reject) => {
this.ad.findGroup({ attributes }, groupName, (err, group) => {
if (err) return reject(err);
resolve(group || null);
});
});
}
async findGroups(query, attributes = this.groupAttributes) {
return new Promise((resolve, reject) => {
const filter = `(&(objectClass=group)(cn=${query}))`;
this.ad.findGroups({ filter, attributes }, (err, groups) => {
if (err) return reject(err);
resolve(groups || []);
});
});
}
/**
* -----------------------------------------------------
* COMPUTER / OU FUNCTIONS 🖥️
* -----------------------------------------------------
*/
/**
* Einzelnen Computer holen
*/
async getComputer(name, attributes = this.computerAttributes) {
return new Promise((resolve, reject) => {
const filter = `(&(objectClass=computer)(|(cn=${name})(dNSHostName=${name})))`;
this.ad.find({ filter, attributes }, (err, result) => {
if (err) return reject(err);
resolve(result?.other?.[0] || null);
});
});
}
/**
* Alle Computer
*/
async getComputers(attributes = this.computerAttributes) {
const options = {
baseDN: this.ad.baseDN,
filter: '(objectClass=computer)',
attributes
};
const result = await this.ldapSearch(options);
return result.other || [];
}
/**
* Alle Computer aus einer OU holen
*/
async getComputersFromOU(ouDn, attributes = this.computerAttributes) {
const options = {
baseDN: ouDn,
filter: '(objectClass=computer)',
attributes
};
const result = await this.ldapSearch(options);
return result.other || [];
}
/**
* Computer suchen (Wildcard möglich)
* Beispiele: "PC-*", "*LAPTOP*", "SRV01"
*/
async findComputers(query, attributes = this.computerAttributes) {
const filter = `(&(objectClass=computer)(|(cn=${query})(dNSHostName=${query})))`;
const result = await this.ldapSearch({
filter,
attributes
});
return result.other || [];
}
/**
* -----------------------------------------------------
* GROUP MEMBERSHIP (DIRECT & RECURSIVE)
* -----------------------------------------------------
*/
async isUserMemberOfDirect(username, groupName) {
return new Promise((resolve, reject) => {
this.ad.isUserMemberOf(username, groupName, (err, isMember) => {
if (err) return reject(err);
resolve(isMember);
});
});
}
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);
if (!group || !Array.isArray(group.member)) return false;
for (const dn of group.member) {
const match = dn.match(/CN=([^,]+)/i);
if (!match) continue;
const subGroupName = match[1];
const found = await this.isUserMemberOfRecursive(username, subGroupName, 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);
if (!group || !Array.isArray(group.member)) return [];
const results = [];
for (const memberDN of group.member) {
const match = memberDN.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 (!Array.isArray(group.member)) return result;
for (const memberDN of group.member) {
const match = memberDN.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;