Updated frontend
This commit is contained in:
+120
-185
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user