You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
6.1 KiB
183 lines
6.1 KiB
/**
|
|
* @module flitter-auth/ldap/AsyncLdapConnection
|
|
*/
|
|
|
|
const ldap = require('ldap')
|
|
const ssha = require('ssha')
|
|
|
|
/**
|
|
* Asynchronous helper methods for the jdap.js library.
|
|
* @class
|
|
*/
|
|
class AsyncLdapConnection {
|
|
constructor(connection){
|
|
this.connection = connection
|
|
}
|
|
|
|
/**
|
|
* Bind the active connection to the specified DN with the password.
|
|
* @param {string} dn - the fully-qualified bind DN
|
|
* @param {string} password - the password to authenticate against
|
|
* @param {Array<ldap/Control>} controls - collection of controls to pass to ldap.js
|
|
* @returns {Promise<module:flitter-auth/ldap/AsyncLdapConnection~AsyncLdapConnection>} - resolves to this if successful
|
|
*/
|
|
bind(dn, password, controls){
|
|
return new Promise((resolve, reject) => {
|
|
this.connection.bind(dn, password, controls, (err) => {
|
|
if ( err ) reject(err)
|
|
else resolve(this)
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Search for all objects in the specified base, covered by the filter, for the specified attributes.
|
|
* @param {string} base - fully-qualified base to search
|
|
* @param {string} filter - LDAP-compliant string to filter items
|
|
* @param {Array<string>} attributes - object attributes to fetch
|
|
* @returns {Promise<Array<object>>} - collection of matches
|
|
*/
|
|
search(base, filter, attributes){
|
|
return new Promise(((resolve, reject) => {
|
|
this.connection.search(base, {
|
|
scope: 'sub',
|
|
attributes,
|
|
filter,
|
|
}, (err, response) => {
|
|
if ( err ) reject (err)
|
|
else {
|
|
const entries = []
|
|
response.on('searchEntry', (en) => entries.push(en.object))
|
|
response.on('error', (e) => reject(e))
|
|
response.on('end', (r) => resolve(entries))
|
|
}
|
|
})
|
|
}))
|
|
}
|
|
|
|
/**
|
|
* Check if the specified attribute is equal to the value for the object with the fully-qualified object DN.
|
|
* @param {string} object - fully-qualified object DN
|
|
* @param {string} attribute - attribute to compare
|
|
* @param {*} value - value to match
|
|
* @returns {Promise<boolean>} - resolves true if the attribute matches the value
|
|
*/
|
|
compare(object, attribute, value){
|
|
return new Promise(((resolve, reject) => {
|
|
this.connection.compare(object, attribute, value, (err, matched) => {
|
|
if ( err ) reject(err)
|
|
else resolve(!!matched)
|
|
})
|
|
}))
|
|
}
|
|
|
|
/**
|
|
* Check if the specified value can authenticate the user with the fully-qualified DN.
|
|
* @param {string} object - fully-qualified DN of the user to bind
|
|
* @param {string} password - password to check
|
|
* @returns {Promise<boolean>} - true if authentication succeeds
|
|
*/
|
|
password_check(object, password){
|
|
return new Promise(resolve => {
|
|
this.connection.bind(object, password, [], (err) => {
|
|
resolve(!err)
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Reset the userPassword of the specified bind object by SSHA hashing the specified password.
|
|
* @param {string} object - fully-qualified DN of the user to reset
|
|
* @param {string} password - the password to set
|
|
* @returns {Promise<void>}
|
|
*/
|
|
password_reset(object, password){
|
|
const change = new ldap.Change({
|
|
operation: 'replace',
|
|
modification: {
|
|
userPassword: ssha.create(password),
|
|
}
|
|
})
|
|
|
|
return new Promise((resolve, reject) => {
|
|
this.connection.modify(object, change, err => {
|
|
if ( err ) reject(err)
|
|
else resolve()
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Modify the values of the specified object.
|
|
* @param {string} object - fully qualified DN of the object to be modified
|
|
* @param {object} entry - collection of key-value pairs to set on the object
|
|
* @returns {Promise<void>}
|
|
*/
|
|
modify(object, entry){
|
|
const change = new ldap.Change({
|
|
operation: 'replace',
|
|
modification: entry,
|
|
})
|
|
|
|
return new Promise((resolve, reject) => {
|
|
this.connection.modify(object, change, err => {
|
|
if ( err ) reject(err)
|
|
else resolve()
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Similar to modify, add the following attributes to the specified object. If they don't exist,
|
|
* the attributes will be created. If they do, the specified values will be appended to the existing
|
|
* attributes.
|
|
* @param {string} object - fully qualified DN of the object to be modified
|
|
* @param {object} entry - collection of key-value pairs to be set on the object
|
|
* @returns {Promise<void>}
|
|
*/
|
|
add_to(object, entry){
|
|
const change = new ldap.Change({
|
|
operation: 'add',
|
|
modification: entry,
|
|
})
|
|
|
|
return new Promise((resolve, reject) => {
|
|
this.connection.modify(object, change, err => {
|
|
if ( err ) reject(err)
|
|
else resolve()
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Create the object with the specified DN with the specified attributes.
|
|
* @param {string} object - fully-qualified DN of the object to be created
|
|
* @param {object} entry - collection of attribute-value pairs for the object
|
|
* @returns {Promise<void>}
|
|
*/
|
|
add(object, entry){
|
|
return new Promise((resolve, reject) => {
|
|
this.connection.add(object, entry, (err) => {
|
|
if ( err ) reject(err)
|
|
else resolve()
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Delete the object with the specified DN.
|
|
* @param {string} object - fully-qualified DN of the object to be deleted
|
|
* @returns {Promise<void>}
|
|
*/
|
|
delete(object){
|
|
return new Promise((resolve, reject) => {
|
|
this.connection.del(object, (err) => {
|
|
if ( err ) reject(err)
|
|
else resolve()
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
module.exports = exports = AsyncLdapConnection
|