Updated frontend

This commit is contained in:
2026-07-01 11:10:09 -04:00
parent ee21bdbf22
commit 5644bfa5ec
8104 changed files with 14976 additions and 386337 deletions
+120 -185
View File
@@ -1,281 +1,216 @@
'use strict';
const { Client, Attribute, Change } = require('ldapts');
const conf = require('../app').conf.ldap;
const { LRUCache } = require('lru-cache');
const conf = require('@simpleworkjs/conf').ldap;
const client = new Client({
url: conf.url,
});
function makeClient() {
return new Client({ url: conf.url });
}
async function withClient(fn) {
const client = makeClient();
try {
await client.bind(conf.bindDN, conf.bindPassword);
return await fn(client);
} finally {
await client.unbind().catch(() => {});
}
}
async function getGroups(client, member){
try{
let memberFilter = member ? `(member=${member})`: ''
let memberFilter = member ? `(member=${member})`: ''
let groups = (await client.search(conf.groupBase, {
scope: 'sub',
filter: `(&(objectClass=groupOfNames)${memberFilter})`,
attributes: ['cn', 'description', 'member', 'owner', 'createTimestamp', 'modifyTimestamp'],
})).searchEntries;
let groups = (await client.search(conf.groupBase, {
scope: 'sub',
filter: `(&(objectClass=groupOfNames)${memberFilter})`,
attributes: ['*', 'createTimestamp', 'modifyTimestamp'],
})).searchEntries;
return groups.map(function(group){
if(!Array.isArray(group.member)) group.member = [group.member];
if(!Array.isArray(group.owner)) group.owner = [group.owner];
return group
});
}catch(error){
throw error;
}
return groups.map(function(group){
if(!Array.isArray(group.member)) group.member = [group.member];
if(!Array.isArray(group.owner)) group.owner = [group.owner];
return group
});
}
async function addGroup(client, data){
try{
await client.add(`cn=${data.name},${conf.groupBase}`, {
cn: data.name,
member: data.owner,
description: data.description,
owner: data.owner,
objectclass: [ 'groupOfNames', 'top' ]
});
await client.add(`cn=${data.name},${conf.groupBase}`, {
cn: data.name,
member: data.owner,
description: data.description,
owner: data.owner,
objectclass: [ 'groupOfNames', 'top' ]
});
return data;
}catch(error){
throw error;
}
return data;
}
async function addMember(client, group, user){
try{
await client.modify(group.dn, [
new Change({
operation: 'add',
modification: new Attribute({
type: 'member',
values: [user.dn]
})
}),
]);
}catch(error){
// if(error = "TypeOrValueExistsError"){
// console.error('addMember error skipped', error)
// return ;
// }
throw error;
}
await client.modify(group.dn, [
new Change({
operation: 'add',
modification: new Attribute({
type: 'member',
values: [user.dn]
})
}),
]);
}
async function removeMember(client, group, user){
try{
await client.modify(group.dn, [
new Change({
operation: 'delete',
modification: new Attribute({
type: 'member',
values: [user.dn]
values: [user.dn]
})}),
]);
}catch(error){
if(error = "TypeOrValueExistsError")return ;
throw error;
}
]);
}
async function addOwner(client, group, user){
try{
await client.modify(group.dn, [
new Change({
operation: 'add',
modification: new Attribute({
type: 'owner',
values: [user.dn]
})
}),
]);
}catch(error){
// if(error = "TypeOrValueExistsError"){
// console.error('addMember error skipped', error)
// return ;
// }
throw error;
}
await client.modify(group.dn, [
new Change({
operation: 'add',
modification: new Attribute({
type: 'owner',
values: [user.dn]
})
}),
]);
}
async function removeOwner(client, group, user){
try{
await client.modify(group.dn, [
new Change({
operation: 'delete',
modification: new Attribute({
type: 'owner',
values: [user.dn]
values: [user.dn]
})}),
]);
}catch(error){
if(error = "TypeOrValueExistsError")return ;
throw error;
}
]);
}
const cache = new LRUCache({ max: 1, ttl: 1000 * 60 * 5, ttlAutopurge: true });
async function cachedListDetail() {
const hit = cache.get('all');
if (hit) return hit;
const promise = withClient(async (client) => {
const groups = await getGroups(client);
return groups.map(g => ({...g}));
}).then(plain => {
cache.set('all', plain);
return plain;
}).catch(err => {
cache.delete('all');
throw err;
});
// Store promise immediately to prevent stampede on concurrent requests
cache.set('all', promise);
return promise;
}
var Group = {};
Group.list = async function(member){
try{
await client.bind(conf.bindDN, conf.bindPassword);
let groups = await getGroups(client, member)
await client.unbind();
return groups.map(group => group.cn);
}catch(error){
throw error;
if (member) {
return withClient(async (client) => {
const groups = await getGroups(client, member);
return groups.map(group => group.cn);
});
}
return (await cachedListDetail()).map(group => group.cn);
}
Group.listDetail = async function(member){
try{
await client.bind(conf.bindDN, conf.bindPassword);
let groups = await getGroups(client, member)
await client.unbind();
return groups;
}catch(error){
throw error;
if (member) {
return withClient(async (client) => getGroups(client, member));
}
return cachedListDetail();
}
Group.get = async function(data){
try{
if(typeof data !== 'object'){
let name = data;
data = {};
data.name = name;
}
await client.bind(conf.bindDN, conf.bindPassword);
if(typeof data !== 'object'){
let name = data;
data = {};
data.name = name;
}
return withClient(async (client) => {
let group = (await client.search(conf.groupBase, {
scope: 'sub',
filter: `(&(objectClass=groupOfNames)(cn=${data.name}))`,
attributes: ['*', 'createTimestamp', 'modifyTimestamp'],
attributes: ['cn', 'description', 'member', 'owner', 'createTimestamp', 'modifyTimestamp'],
})).searchEntries[0];
await client.unbind();
if(!Array.isArray(group.member)) group.member = [group.member];
if(!Array.isArray(group.owner)) group.owner = [group.owner];
if(group){
if(!Array.isArray(group.member)) group.member = [group.member];
if(!Array.isArray(group.owner)) group.owner = [group.owner];
let obj = Object.create(this);
Object.assign(obj, group);
return obj;
}else{
let error = new Error('GroupNotFound');
error.name = 'GroupNotFound';
error.message = `LDAP:${data.cn} does not exists`;
error.message = `LDAP:${data.name} does not exists`;
error.status = 404;
throw error;
}
}catch(error){
throw error;
}
});
}
Group.add = async function(data){
try{
await client.bind(conf.bindDN, conf.bindPassword);
return withClient(async (client) => {
await addGroup(client, data);
await client.unbind();
cache.clear();
return this.get(data);
}catch(error){
throw error;
}
});
}
Group.addMember = async function(user){
try{
await client.bind(conf.bindDN, conf.bindPassword);
await addMember(client, this, user);
await client.unbind();
return this;
}catch(error){
throw error;
}
await withClient(async (client) => addMember(client, this, user));
this.member = [].concat(this.member || []).concat([user.dn]);
cache.clear();
return this;
};
Group.removeMember = async function(user){
try{
await client.bind(conf.bindDN, conf.bindPassword);
await removeMember(client, this, user);
await client.unbind();
return this;
await withClient(async (client) => removeMember(client, this, user));
}catch(error){
if(error.name === "NoSuchAttributeError") return this;
throw error;
}
this.member = [].concat(this.member || []).filter(dn => dn !== user.dn);
cache.clear();
return this;
};
Group.addOwner = async function(user){
try{
await client.bind(conf.bindDN, conf.bindPassword);
await addOwner(client, this, user);
await client.unbind();
return this;
}catch(error){
throw error;
}
await withClient(async (client) => addOwner(client, this, user));
this.owner = [].concat(this.owner || []).concat([user.dn]);
cache.clear();
return this;
};
Group.removeOwner = async function(user){
try{
await client.bind(conf.bindDN, conf.bindPassword);
await removeOwner(client, this, user);
await client.unbind();
return this;
await withClient(async (client) => removeOwner(client, this, user));
}catch(error){
if(error.name === "NoSuchAttributeError") return this;
throw error;
}
this.owner = [].concat(this.owner || []).filter(dn => dn !== user.dn);
cache.clear();
return this;
};
Group.remove = async function(){
try{
await client.bind(conf.bindDN, conf.bindPassword);
await client.del(this.dn);
await client.unbind();
return true;
}catch(error){
throw error;
}
await withClient(async (client) => client.del(this.dn));
cache.clear();
return true;
}
module.exports = {Group};