improve ldap wrapper return values

This commit is contained in:
Arthur Lu 2023-12-01 23:06:15 +00:00
parent 3ce798aced
commit 87a42299e6

View File

@ -17,9 +17,10 @@ export default class LDAP {
} }
async addUser (bind, uid, attrs) { async addUser (bind, uid, attrs) {
const bindResult = await this.#client.bind(bind.dn, bind.password); const logger = new LDAP_MULTIOP_LOGGER(`add ${uid}`);
if (!bindResult.ok) { await this.#client.bind(bind.dn, bind.password, logger);
return bindResult; if (!logger.ok) {
return logger;
} }
const userDN = `uid=${uid},${this.#peopledn}`; const userDN = `uid=${uid},${this.#peopledn}`;
const entry = { const entry = {
@ -29,8 +30,8 @@ export default class LDAP {
uid, uid,
userPassword: attrs.userPassword userPassword: attrs.userPassword
}; };
const addResult = await this.#client.add(userDN, entry); await this.#client.add(userDN, entry, logger);
return { op: `add ${uid}`, ok: addResult.ok, error: addResult.error }; return logger;
} }
async getUser (bind, uid) { async getUser (bind, uid) {
@ -42,11 +43,11 @@ export default class LDAP {
} }
async modUser (bind, uid, newAttrs) { async modUser (bind, uid, newAttrs) {
const bindResult = await this.#client.bind(bind.dn, bind.password); const logger = new LDAP_MULTIOP_LOGGER(`modify ${uid}`);
if (!bindResult.ok) { await this.#client.bind(bind.dn, bind.password, logger);
return bindResult; if (!logger.ok) {
return logger;
} }
const subops = [bindResult];
for (const attr of ["cn", "sn", "userPassword"]) { for (const attr of ["cn", "sn", "userPassword"]) {
if (attr in newAttrs) { if (attr in newAttrs) {
const change = new ldap.Change({ const change = new ldap.Change({
@ -56,27 +57,27 @@ export default class LDAP {
values: [newAttrs[attr]] values: [newAttrs[attr]]
} }
}); });
subops.push(await this.#client.modify(`uid=${uid},${this.#peopledn}`, change)); await this.#client.modify(`uid=${uid},${this.#peopledn}`, change, logger);
} }
} }
return { op: `modify ${uid}`, ok: !subops.some((e) => !e.ok), error: subops.find((e) => !e.ok) || null, subops }; return logger;
} }
async delUser (bind, uid) { async delUser (bind, uid) {
const bindResult = await this.#client.bind(bind.dn, bind.password); const logger = new LDAP_MULTIOP_LOGGER(`del ${uid}`);
if (!bindResult.ok) { await this.#client.bind(bind.dn, bind.password, logger);
return bindResult; if (!logger.ok) {
return logger;
} }
const userDN = `uid=${uid},${this.#peopledn}`; const userDN = `uid=${uid},${this.#peopledn}`;
const delResult = await this.#client.del(userDN); await this.#client.del(userDN, logger);
const groups = await this.#client.search(this.#groupsdn, { const groups = await this.#client.search(this.#groupsdn, {
scope: "one", scope: "one",
filter: `(member=uid=${uid},${this.#peopledn})` filter: `(member=uid=${uid},${this.#peopledn})`
}); }, logger);
if (!groups.ok) { if (!logger.ok) {
return { op: `del ${uid}`, ok: groups.ok, error: groups.error, subops: [bindResult, delResult, groups]} return logger;
} }
const groupsubops = [];
for (const element of groups.entries) { for (const element of groups.entries) {
let change = null; let change = null;
if (element.attributes.member.length === 1) { if (element.attributes.member.length === 1) {
@ -97,16 +98,16 @@ export default class LDAP {
} }
}); });
} }
const delResult = await this.#client.modify(element.dn, change); await this.#client.modify(element.dn, change, logger);
groupsubops.push(delResult);
} }
return { op: `del ${uid}`, ok: delResult.ok, error: delResult.error, subops: [bindResult, delResult, groups].concat(groupsubops) }; return logger;
} }
async addGroup (bind, gid, attrs) { async addGroup (bind, gid, attrs) {
const bindResult = await this.#client.bind(bind.dn, bind.password); const logger = new LDAP_MULTIOP_LOGGER(`add ${gid}`);
if (!bindResult.ok) { await this.#client.bind(bind.dn, bind.password, logger);
return bindResult; if (!logger.ok) {
return logger;
} }
const groupDN = `cn=${gid},${this.#groupsdn}`; const groupDN = `cn=${gid},${this.#groupsdn}`;
const entry = { const entry = {
@ -114,8 +115,8 @@ export default class LDAP {
member: attrs && attrs.member ? attrs.member : "", member: attrs && attrs.member ? attrs.member : "",
cn: gid cn: gid
}; };
const addResult = await this.#client.add(groupDN, entry); await this.#client.add(groupDN, entry, logger);
return { op: `add ${gid}`, ok: addResult.ok, error: addResult.error, subops: [bindResult, addResult] }; return logger;
} }
async getGroup (bind, gid) { async getGroup (bind, gid) {
@ -127,22 +128,24 @@ export default class LDAP {
} }
async delGroup (bind, gid) { async delGroup (bind, gid) {
const bindResult = await this.#client.bind(bind.dn, bind.password); const logger = new LDAP_MULTIOP_LOGGER(`del ${gid}`);
if (!bindResult.ok) { await this.#client.bind(bind.dn, bind.password, logger);
return bindResult; if (!logger.ok) {
return logger;
} }
const groupDN = `cn=${gid},${this.#groupsdn}`; const groupDN = `cn=${gid},${this.#groupsdn}`;
const delResult = await this.#client.del(groupDN); await this.#client.del(groupDN, logger);
return { op: `del ${gid}`, ok: delResult.ok, error: delResult.error, subops: [bindResult, delResult] }; return logger;
} }
async addUserToGroup (bind, uid, gid) { async addUserToGroup (bind, uid, gid) {
const bindResult = await this.#client.bind(bind.dn, bind.password); const logger = new LDAP_MULTIOP_LOGGER(`add ${uid} to ${gid}`);
if (!bindResult.ok) { await this.#client.bind(bind.dn, bind.password, logger);
return bindResult; if (!logger.ok) {
return logger;
} }
const checkGroupEntry = await this.#client.search(`cn=${gid},${this.#groupsdn}`, {}); const checkGroupEntry = await this.#client.search(`cn=${gid},${this.#groupsdn}`, {}, logger);
if (checkGroupEntry.ok) { if (logger.ok) {
// add the user // add the user
const change = new ldap.Change({ const change = new ldap.Change({
operation: "add", operation: "add",
@ -151,9 +154,9 @@ export default class LDAP {
values: [`uid=${uid},${this.#peopledn}`] values: [`uid=${uid},${this.#peopledn}`]
} }
}); });
const addResult = await this.#client.modify(`cn=${gid},${this.#groupsdn}`, change); await this.#client.modify(`cn=${gid},${this.#groupsdn}`, change, logger);
if (!addResult.ok) { if (!logger.ok) {
return addResult; return logger;
} }
// check if there is a blank entry in the group // check if there is a blank entry in the group
const groupEntry = checkGroupEntry.entries[0]; const groupEntry = checkGroupEntry.entries[0];
@ -166,20 +169,20 @@ export default class LDAP {
values: [""] values: [""]
} }
}); });
const fixResult = await this.#client.modify(`cn=${gid},${this.#groupsdn}`, change); await this.#client.modify(`cn=${gid},${this.#groupsdn}`, change, logger);
return { op: `add ${uid} to ${gid}`, ok: addResult.ok && fixResult.ok, error: addResult.error ? addResult.error : fixResult.error, subops: [bindResult, addResult, fixResult] };
} }
return { op: `add ${uid} to ${gid}`, ok: true, error: null, subops: [bindResult, addResult] }; return logger;
} }
else { else {
return { op: `add ${uid} to ${gid}`, ok: false, error: `${gid} does not exist`, subops: [bindResult] }; return logger;
} }
} }
async delUserFromGroup (bind, uid, gid) { async delUserFromGroup (bind, uid, gid) {
const bindResult = await this.#client.bind(bind.dn, bind.password); const logger = new LDAP_MULTIOP_LOGGER(`del ${uid} from ${gid}`);
if (!bindResult.ok) { await this.#client.bind(bind.dn, bind.password, logger);
return bindResult; if (!logger.ok) {
return logger;
} }
const change = new ldap.Change({ const change = new ldap.Change({
operation: "delete", operation: "delete",
@ -188,12 +191,30 @@ export default class LDAP {
values: [`uid=${uid},${this.#peopledn}`] values: [`uid=${uid},${this.#peopledn}`]
} }
}); });
const delResult = await this.#client.modify(`cn=${gid},${this.#groupsdn}`, change); await this.#client.modify(`cn=${gid},${this.#groupsdn}`, change, logger);
return { op: `del ${uid} from ${gid}`, ok: delResult.ok, error: delResult.error, subops: [bindResult, delResult] }; return logger;
} }
async search (base, opts) { async search (branch, opts) {
return await this.#client.search(base, opts); return await this.#client.search(`${branch},${this.#basedn}`, opts);
}
}
class LDAP_MULTIOP_LOGGER {
op = null;
ok = true;
error = [];
subops = [];
constructor (op) {
this.op = op;
}
push (op) {
if (!op.ok) {
this.ok = false;
this.error.push(op.error);
}
this.subops.push(op);
} }
} }
@ -209,86 +230,95 @@ class LDAPJS_CLIENT_ASYNC_WRAPPER {
}); });
} }
bind (dn, password) { #parseError (err) {
if (err) {
return {code: err.code, name: err.name, message: err.message};
}
else {
return null;
}
}
bind (dn, password, logger = null) {
return new Promise((resolve) => { return new Promise((resolve) => {
this.#client.bind(dn, password, (err) => { this.#client.bind(dn, password, (err) => {
if (err) { const result = { op: `bind ${dn}`, ok: err === null, error: this.#parseError(err) };
resolve({ op: `bind ${dn}`, ok: false, error: err }); if (logger) {
} logger.push(result);
else {
resolve({ op: `bind ${dn}`, ok: true, error: null });
} }
resolve(result);
}); });
}); });
} }
add (dn, entry) { add (dn, entry, logger = null) {
return new Promise((resolve) => { return new Promise((resolve) => {
this.#client.add(dn, entry, (err) => { this.#client.add(dn, entry, (err) => {
if (err) { const result = { op: `add ${dn}`, ok: err === null, error: this.#parseError(err) };
resolve({ op: `add ${dn}`, ok: false, error: err }); if (logger) {
} logger.push(result);
else {
resolve({ op: `add ${dn}`, ok: true, error: null });
} }
resolve(result);
}); });
}); });
} }
search (base, options) { search (base, options, logger = null) {
return new Promise((resolve) => { return new Promise((resolve) => {
this.#client.search(base, options, (err, res) => { this.#client.search(base, options, (err, res) => {
if (err) { if (err) {
return resolve({ op: `search ${base}`, ok: false, error: err }); return resolve({ op: `search ${base}`, ok: false, error: err });
} }
const results = { op: `search ${base}`, ok: false, error: null, status: 1, message: "", entries: [] }; const result = { op: `search ${base}`, ok: false, error: null, entries: [] };
res.on("searchRequest", (searchRequest) => { }); res.on("searchRequest", (searchRequest) => { });
res.on("searchEntry", (entry) => { res.on("searchEntry", (entry) => {
const attributes = {}; const attributes = {};
for (const element of entry.pojo.attributes) { for (const element of entry.pojo.attributes) {
attributes[element.type] = element.values; attributes[element.type] = element.values;
} }
results.entries.push({ dn: entry.pojo.objectName, attributes }); result.entries.push({ dn: entry.pojo.objectName, attributes });
}); });
res.on("searchReference", (referral) => { }); res.on("searchReference", (referral) => { });
res.on("error", (error) => { res.on("error", (err) => {
results.ok = error.status === 0; result.ok = false;
results.status = error.status; result.error = this.#parseError(err);
results.message = error.message; if (logger) {
resolve(results); logger.push(result);
}
resolve(result);
}); });
res.on("end", (result) => { res.on("end", (res) => {
results.ok = result.status === 0; result.ok = true;
results.status = result.status; result.error = null;
results.message = result.message; if (logger) {
resolve(results); logger.push(result);
}
resolve(result);
}); });
}); });
}); });
} }
modify (name, changes) { modify (name, changes, logger = null) {
return new Promise((resolve) => { return new Promise((resolve) => {
this.#client.modify(name, changes, (err) => { this.#client.modify(name, changes, (err) => {
if (err) { const result = { op: `modify ${name} ${changes.operation} ${changes.modification.type}`, ok: err === null, error: this.#parseError(err) };
resolve({ op: `modify ${name} ${changes.operation} ${changes.modification.type}`, ok: false, error: err }); if (logger) {
} logger.push(result);
else {
resolve({ op: `modify ${name} ${changes.operation} ${changes.modification.type}`, ok: true, error: null });
} }
resolve(result);
}); });
}); });
} }
del (dn) { del (dn, logger = null) {
return new Promise((resolve) => { return new Promise((resolve) => {
this.#client.del(dn, (err) => { this.#client.del(dn, (err) => {
if (err) { const result = { op: `del ${dn}`, ok: err === null, error: this.#parseError(err) };
resolve({ op: `del ${dn}`, ok: false, error: err }); if (logger) {
} logger.push(result);
else {
resolve({ op: `del ${dn}`, ok: true, error: null });
} }
resolve(result);
}); });
}); });
} }