diff --git a/README.md b/README.md index 2ae4b36..c108d78 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # epfl-ldap -Simple wrapper to query the epfl ldap +Simple wrapper to query the EPFL LDAP. ## Usage ```javascript @@ -43,17 +43,23 @@ customLdapContext.options.modelsMapper = customModelsMapper; customLdapContext.users.getUserBySciper(169419, function (err, data) { console.log(JSON.stringify(data, null, 2)); }); -``` -## Notes -⚠ Carefull with the results formats (Object or Array) +/* + * Custom Options + */ +var publicLdapContext = require('epfl-ldap')({ + searchBase:'ou=si-idev,ou=si,o=epfl,c=ch', + poolSize: 4 + }); +publicLdapContext.users.getUserBySciper(169419, function(err, data) { + console.log(JSON.stringify(data, null, 2)); +}); +``` -⚠ this library *"try"* to use ES2015 (or ES6) capabilities, don't use it with nodejs under 4.x? +## Notes -## TODO +⚠ Carefull with the results formats (Object or Array) -- [ ] add tests -- [ ] add samples -- [ ] implement query validation with the package `epfl-exceptions` +⚠ this library *"try"* to use ES2015 (or ES6) capabilities, don't use it with nodejs under 5.x? diff --git a/client.js b/client.js index 8d1fa77..d7bef65 100644 --- a/client.js +++ b/client.js @@ -1,82 +1,78 @@ 'use strict'; -module.exports = function ldapClient(context) { - - let ldap = require('ldapjs'); - let client = ldap.createClient({ - url: 'ldap://ldap.epfl.ch', - timeLimit: 1, - sizeLimit: 10 - }); - - function cacheQuery(ldapQuery, objectFactory, modelMapper, isResultUniq, next) { - let opts = { - filter: ldapQuery, - scope: 'sub' - }; - - client.search(context.options.searchBase, opts, function (err, ldapRes) { - let groupedObject = {}; +const _executeQueryPromise = require('./ldapjs-promise'); +const ConnectionPool = require('./connection-pool.js'); - ldapRes.on('searchEntry', function (entry) { - if (typeof entry.json != 'undefined') { - let objectIdentifier = entry.object.uniqueIdentifier; - if (groupedObject[objectIdentifier] === undefined) { - groupedObject[objectIdentifier] = Array(); - } - groupedObject[objectIdentifier].push(entry.object); - } else { - next(null, groupedObject); +function _executeQueryInPool(pool, searchBase, ldapQuery, next) { + pool.add(function(client) { + _executeQueryPromise(client, searchBase, ldapQuery) + .then( + (data) => { + next(null, data); } - }); - ldapRes.on('searchReference', function (referral) { - //console.log('referral: ' + referral.uris.join()); - }); - ldapRes.on('error', function (err) { - console.error('error: ' + err.message); - next(err, null); - }); - ldapRes.on('timeout', function (err) { - console.error('error: ' + err.message); - next(err, null); - }); - ldapRes.on('end', function () { - let objectsGroup = Array(); - - for (let userEntry in groupedObject) { - if (groupedObject.hasOwnProperty(userEntry)) { - if (isResultUniq) { - objectsGroup = modelMapper(objectFactory(groupedObject[userEntry])); - } else { - objectsGroup.push(modelMapper(objectFactory(groupedObject[userEntry]))); - } - } + ) + .catch( + (err) => { + next(err, null); } - next(null, objectsGroup); - }); + ) }); - } +} + +function createPool(clientFactory, opts) { + const pool = new ConnectionPool( + opts.poolSize, + clientFactory, + (client) => client.unbind() + ); + return pool; +} - client.executeQuery = function(ldapQuery, objectFactory, modelMapper, isResultUniq, next) { - context.memoryCache.get(ldapQuery, function (err, data) { - if (!err) { - if (data == undefined) { - cacheQuery(ldapQuery, objectFactory, modelMapper, isResultUniq, function(err, data) { - context.memoryCache.set(ldapQuery, data, function (err, success) { - if (!err && success) { - next(null, data); +module.exports = function ldapClient(context) { + + let ldap = require('ldapjs'); + let pool = createPool(() => ldap.createClient({ + url: 'ldap://ldap.epfl.ch', + timeLimit: 1, + sizeLimit: 10 + }), + { poolSize : context.poolSize } + ); + + const client = { + executeQuery: function(ldapQuery, objectFactory, modelMapper, isResultUniq, next) { + let objectsGroup = context.memoryCache.get(ldapQuery+isResultUniq) + if (objectsGroup == undefined) { + let searchBase = context.options.searchBase; + let opts = { + filter: ldapQuery, + scope: 'sub' + }; + _executeQueryInPool(pool, searchBase, opts, function(err, data) { + + let objectsGroup = Array(); + + for (let userEntry in data) { + if (data.hasOwnProperty(userEntry)) { + if (isResultUniq) { + objectsGroup = modelMapper(objectFactory(data[userEntry])); } else { - next({ Error: "aararrggghhh!" }, null); + objectsGroup.push(modelMapper(objectFactory(data[userEntry]))); } - }); - }); - } else { - next(null, data); - } + } + } + + let success = context.memoryCache.set(ldapQuery+isResultUniq, objectsGroup); + if (success) { + next(null, objectsGroup); + } else { + next({ Error: "Error setting cache" }, null); + } + }); } else { - next({ Error: "aararrggghhh!" }, null); + next(null, objectsGroup); } - }); + } }; return client; diff --git a/connection-pool.js b/connection-pool.js new file mode 100644 index 0000000..5169971 --- /dev/null +++ b/connection-pool.js @@ -0,0 +1,60 @@ +const debug = require('debug')('connection-pool'); +const PSemaphore = require('promise-semaphore'); + +module.exports = class ConnectionPool { + + constructor(n, create, destroy) { + this.roomsLength = n; + this.pSemaphore = new PSemaphore({rooms: this.roomsLength}); + this.create = create; + this.destroy = destroy; + this.rooms = [ + //{ free: false, client: null} + ]; + } + + add(f) { + return this.pSemaphore.add(async () => { + debug("GET"); + let client = this._get(); + try { + return await f(client); + } finally { + debug("PUT"); + this._put(client); + } + }); + } + + _get() { + for(let i=0; i < this.roomsLength; i++) { + if (!this.rooms[i]) { + this.rooms[i] = { + free: true, + client: this.create() + } + } + // Room is furnished + if (this.rooms[i].free) { + this.rooms[i].free = false; + return this.rooms[i].client; + } else { + // continue + } + } + } + + _put(client) { + this.rooms.forEach(room => { + if (room.client === client) { + room.free = true; + } + }) + } + + close() { + this.rooms.forEach(room => { + this.destroy(room.client); + }) + } +} \ No newline at end of file diff --git a/context.js b/context.js index 3034992..2117cc3 100644 --- a/context.js +++ b/context.js @@ -1,17 +1,25 @@ 'use strict'; +let NodeCache = require("node-cache"); module.exports = function ldapContext(options) { - let NodeCache = require("node-cache"); let context = {}; + // Define the pool size + if (options == undefined || options.poolSize == undefined ) { + context.poolSize = 3; + } else { + context.poolSize = options.poolSize; + } + context.options = require('./options')(options); context.client = require('./client')(context); - context.options = require('./options')(); context.users = require('./repositories/users')(context); context.units = require('./repositories/units')(context); context.viewModelsMappers = require('./viewModels/mappers')(); - if (options == undefined || options.memoryCache == undefined ) { - context.memoryCache = new NodeCache({ stdTTL: 14400 }); // 4 hour of cache - } else { - context.memoryCache = new NodeCache(options.memoryCache); + if (context.memoryCache == undefined) { + if (options == undefined || options.memoryCache == undefined ) { + context.memoryCache = new NodeCache({ stdTTL: 14400 }); // 4 hour of cache + } else { + context.memoryCache = new NodeCache(options.memoryCache); + } } return context; }; \ No newline at end of file diff --git a/ldapjs-promise.js b/ldapjs-promise.js new file mode 100644 index 0000000..b02772e --- /dev/null +++ b/ldapjs-promise.js @@ -0,0 +1,32 @@ +module.exports = function _executeQueryPromise(client, searchBase, opts) { + return new Promise((resolve, reject) => { + client.search(searchBase, opts, function (err, ldapRes) { + let groupedObject = {}; + ldapRes.on('searchEntry', function (entry) { + if (typeof entry.json != 'undefined') { + let objectIdentifier = entry.object.uniqueIdentifier; + if (groupedObject[objectIdentifier] === undefined) { + groupedObject[objectIdentifier] = Array(); + } + groupedObject[objectIdentifier].push(entry.object); + } else { + resolve(groupedObject); + } + }); + ldapRes.on('searchReference', function (referral) { + //console.log('referral: ' + referral.uris.join()); + }); + ldapRes.on('error', function (err) { + console.error('error: ' + err.message); + reject(err); + }); + ldapRes.on('timeout', function (err) { + console.error('error: ' + err.message); + reject(err); + }); + ldapRes.on('end', function () { + resolve(groupedObject); + }); + }); + }); +} \ No newline at end of file diff --git a/models/user.js b/models/user.js index 4047b75..2236a9e 100644 --- a/models/user.js +++ b/models/user.js @@ -10,9 +10,8 @@ module.exports = function User(ldapUserArray) { userModel.accreds = Array(); userModel.memberOf = Array(); userModel.photoUrl = 'http://people.epfl.ch/cgi-bin/people/getPhoto?id=' + userModel.sciper; - + if (ldapUserArray[0].memberOf !== undefined) { - // Note: if only one group, typeof string // if groups, typeof object. // Username banla have only one group @@ -25,13 +24,12 @@ module.exports = function User(ldapUserArray) { userModel.memberOf = ldapUserArray[0].memberOf; } } - + ldapUserArray.map(function (userEntry) { if (userEntry.mail != undefined) { if (userEntry.mail instanceof Array) { - userEntry.mail.map(function(mail) { - userModel.emails.push(mail); - }); + // This remove duplicated entries and allow more than one email + userModel.emails = [...new Set(userEntry.mail)]; } else { userModel.emails.push(userEntry.mail); } @@ -49,8 +47,8 @@ module.exports = function User(ldapUserArray) { } ); }); - - //All ldap properties + + // All ldap properties userModel.optionalProperties = ldapUserArray; return userModel; diff --git a/options.js b/options.js index ec909a4..ffcd9b2 100644 --- a/options.js +++ b/options.js @@ -1,7 +1,12 @@ 'use strict'; -module.exports = function () { +module.exports = function (options) { let ldapOptions = {}; - ldapOptions.searchBase = 'c=ch'; + // Define the searchBase + if (options == undefined || options.searchBase == undefined ) { + ldapOptions.searchBase = 'c=ch'; + } else { + ldapOptions.searchBase = options.searchBase; + } ldapOptions.modelsMapper = require('./viewModels/public/modelsMapper')(); return ldapOptions; }; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b1037f6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1509 @@ +{ + "name": "epfl-ldap", + "version": "1.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "epfl-ldap", + "version": "1.0.1", + "license": "ISC", + "dependencies": { + "debug": "^4.1.1", + "ldapjs": "^1.0.2", + "node-cache": "^5.1.0", + "o-mapper": "^1.0.0", + "promise-semaphore": "^0.2.8" + }, + "devDependencies": { + "jshint": "^2.11.0", + "mocha": "*" + } + }, + "node_modules/ansi-colors": { + "version": "3.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asn1": { + "version": "0.2.3", + "license": "MIT" + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/backoff": { + "version": "2.5.0", + "license": "MIT", + "dependencies": { + "precond": "0.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "devOptional": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "devOptional": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "dev": true, + "license": "ISC" + }, + "node_modules/bunyan": { + "version": "1.8.12", + "engines": [ + "node >=0.10.0" + ], + "license": "MIT", + "bin": { + "bunyan": "bin/bunyan" + }, + "optionalDependencies": { + "dtrace-provider": "~0.8", + "moment": "^2.10.6", + "mv": "~2", + "safe-json-stringify": "~1" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.1" + } + }, + "node_modules/cli": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "engines": { + "node": ">=0.2.5" + } + }, + "node_modules/cli/node_modules/glob": { + "version": "7.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "devOptional": true, + "license": "MIT" + }, + "node_modules/console-browserify": { + "version": "1.1.0", + "dev": true, + "dependencies": { + "date-now": "^0.1.4" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/date-now": { + "version": "0.1.4", + "dev": true + }, + "node_modules/debug": { + "version": "4.1.1", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/diff": { + "version": "3.5.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-serializer": { + "version": "0.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.0.1", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.0.0", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "2.3.0", + "dev": true, + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/domutils": { + "version": "1.5.1", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/dtrace-provider": { + "version": "0.8.8", + "hasInstallScript": true, + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "nan": "^2.14.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "1.0.0", + "dev": true, + "license": "BSD-like" + }, + "node_modules/es-abstract": { + "version": "1.17.4", + "dev": true, + "license": "MIT", + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/extsprintf": { + "version": "1.2.0", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/flat": { + "version": "4.1.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "6.0.4", + "license": "ISC", + "optional": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/growl": { + "version": "1.10.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.x" + } + }, + "node_modules/has": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/he": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/htmlparser2": { + "version": "3.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "devOptional": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "devOptional": true, + "license": "ISC" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-buffer": { + "version": "2.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.1.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-regex": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jshint": { + "version": "2.11.0", + "dev": true, + "license": "(MIT AND JSON)", + "dependencies": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.11", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" + }, + "bin": { + "jshint": "bin/jshint" + } + }, + "node_modules/ldap-filter": { + "version": "0.2.2", + "license": "MIT", + "dependencies": { + "assert-plus": "0.1.5" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ldap-filter/node_modules/assert-plus": { + "version": "0.1.5", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ldapjs": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "asn1": "0.2.3", + "assert-plus": "^1.0.0", + "backoff": "^2.5.0", + "bunyan": "^1.8.3", + "dashdash": "^1.14.0", + "ldap-filter": "0.2.2", + "once": "^1.4.0", + "vasync": "^1.6.4", + "verror": "^1.8.1" + }, + "bin": { + "ldapjs-add": "bin/ldapjs-add", + "ldapjs-compare": "bin/ldapjs-compare", + "ldapjs-delete": "bin/ldapjs-delete", + "ldapjs-modify": "bin/ldapjs-modify", + "ldapjs-search": "bin/ldapjs-search" + }, + "engines": { + "node": ">=0.10" + }, + "optionalDependencies": { + "dtrace-provider": "~0.8" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.15", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "devOptional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "0.0.8", + "devOptional": true, + "license": "MIT" + }, + "node_modules/mkdirp": { + "version": "0.5.1", + "devOptional": true, + "license": "MIT", + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.0", + "yargs-parser": "13.1.1", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "3.2.6", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/strip-json-comments": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/moment": { + "version": "2.24.0", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.1", + "license": "MIT" + }, + "node_modules/mv": { + "version": "2.1.1", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/nan": { + "version": "2.14.0", + "license": "MIT", + "optional": true + }, + "node_modules/ncp": { + "version": "2.0.0", + "license": "MIT", + "optional": true, + "bin": { + "ncp": "bin/ncp" + } + }, + "node_modules/node-cache": { + "version": "5.1.0", + "license": "MIT", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 0.4.6" + } + }, + "node_modules/node-environment-flags": { + "version": "1.0.6", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/o-mapper": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=6.4.0" + } + }, + "node_modules/object-inspect": { + "version": "1.7.0", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "2.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picomatch": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/precond": { + "version": "0.2.3", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/promise-semaphore": { + "version": "0.2.8", + "license": "MIT", + "dependencies": { + "bluebird": "^3.3.1" + } + }, + "node_modules/promise-semaphore/node_modules/bluebird": { + "version": "3.3.1", + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "1.1.14", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/readdirp": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/rimraf": { + "version": "2.4.5", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^6.0.1" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/safe-json-stringify": { + "version": "1.2.0", + "license": "MIT", + "optional": true + }, + "node_modules/semver": { + "version": "5.7.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/shelljs": { + "version": "0.3.0", + "dev": true, + "license": "BSD*", + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.trimleft": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimright": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "bin": { + "strip-json-comments": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/supports-color": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/vasync": { + "version": "1.6.4", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "verror": "1.6.0" + } + }, + "node_modules/vasync/node_modules/verror": { + "version": "1.6.0", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "extsprintf": "1.2.0" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/wide-align": { + "version": "1.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/y18n": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "13.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/yargs-unparser": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + } + } +} diff --git a/package.json b/package.json index 1f66a9a..8b7641a 100644 --- a/package.json +++ b/package.json @@ -1,29 +1,30 @@ { "name": "epfl-ldap", - "version": "0.5.0", + "version": "1.0.1", "description": "epfl-ldap", "main": "context.js", - "homepage": "https://github.com/stefanonepa/epfl-ldap", - "author": "stefanonepa", + "homepage": "https://github.com/epfl-si/epfl-ldap-js", + "author": "stefanonepa, idev-fsd", "dependencies": { - "epfl-exceptions": "^0.0.3", - "ldapjs": "^1.0.0", - "node-cache": "^3.0.0", - "o-mapper": "^0.1.2" + "debug": "^4.1.1", + "ldapjs": "^1.0.2", + "node-cache": "^5.1.0", + "o-mapper": "^1.0.0", + "promise-semaphore": "^0.2.8" }, "devDependencies": { - "jshint": "^2.8.0", + "jshint": "^2.11.0", "mocha": "*" }, "bugs": { - "url": "https://github.com/stefanonepa/epfl-ldap/issues" + "url": "https://github.com/epfl-si/epfl-ldap-js/issues" }, "directories": { "test": "test" }, "repository": { "type": "git", - "url": "git+https://github.com/stefanonepa/epfl-ldap.git" + "url": "git+https://github.com/epfl-si/epfl-ldap-js.git" }, "keywords": [ "epfl", @@ -31,6 +32,9 @@ ], "license": "ISC", "scripts": { - "test": "mocha" + "test": "mocha --exit", + "sample-unit": "node samples/sample-getUnit.js", + "sample-sciper": "node samples/sample-getUserBySciper.js", + "sample-connection-pool": "DEBUG=connection-pool node samples/sample-connectionPool.js" } } diff --git a/repositories/units.js b/repositories/units.js index 8256725..44233a6 100644 --- a/repositories/units.js +++ b/repositories/units.js @@ -1,21 +1,30 @@ 'use strict'; module.exports = function (context) { let unitFactory = require('../models/unit'); - + let unitsRepo = {}; let client = context.client; - + + /* DEPRECATED: please use specific methods */ unitsRepo.getUnitById = function (accountingNumber, next) { - client.executeQuery('(&(objectClass=organizationalunit)(|(accountingNumber=' + accountingNumber + ')))', unitFactory, context.options.modelsMapper.unit, true, next); + unitsRepo.getUnitByAccountingNumber(accountingNumber, next); }; - + + unitsRepo.getUnitByAccountingNumber = function (accountingNumber, next) { + client.executeQuery('(&(objectClass=organizationalunit)(accountingNumber=' + accountingNumber + '))', unitFactory, context.options.modelsMapper.unit, true, next); + }; + + unitsRepo.getUnitByUniqueIdentifier = function (unitId, next) { + client.executeQuery('(&(objectClass=organizationalunit)(uniqueIdentifier=' + unitId + '))', unitFactory, context.options.modelsMapper.unit, true, next); + }; + unitsRepo.getUnitByName = function (unit, next) { - client.executeQuery('(&(objectClass=organizationalunit)(|(ou=' + unit + ')))', unitFactory, context.options.modelsMapper.unit, true, next); + client.executeQuery('(&(objectClass=organizationalunit)(ou=' + unit + '))', unitFactory, context.options.modelsMapper.unit, true, next); }; unitsRepo.searchUnitByName = function (unit, next) { - client.executeQuery('(&(objectClass=organizationalunit)(|(ou=' + unit + '*)))', unitFactory, context.options.modelsMapper.unit, false, next); + client.executeQuery('(&(objectClass=organizationalunit)(ou=*' + unit + '*))', unitFactory, context.options.modelsMapper.unit, false, next); }; - + return unitsRepo; }; \ No newline at end of file diff --git a/repositories/users.js b/repositories/users.js index 74167c9..c61f51e 100644 --- a/repositories/users.js +++ b/repositories/users.js @@ -4,45 +4,57 @@ module.exports = function (context) { let userFactory = require('../models/user'); let usersRepo = {}; let client = context.client; - + usersRepo.getUserBySciper = function (sciper, next) { - client.executeQuery('(&(objectClass=posixAccount)(|(uniqueIdentifier=' + sciper + ')))', userFactory, context.options.modelsMapper.user, true, next); + client.executeQuery('(&(objectClass=posixAccount)(uniqueIdentifier=' + sciper + '))', userFactory, context.options.modelsMapper.user, true, next); }; - + usersRepo.getUserByName = function (name, next) { - client.executeQuery('(&(objectClass=posixAccount)(|(cn=' + name + ')))', userFactory, context.options.modelsMapper.user, false, next); + client.executeQuery('(&(objectClass=posixAccount)(cn=' + name + '))', userFactory, context.options.modelsMapper.user, true, next); }; - + + usersRepo.getUserByPhone = function (phone, next) { + client.executeQuery('(&(objectClass=posixAccount)(|(telephoneNumber=' + phone + ')(telephoneNumber=+41 21 69' + phone + ')))', userFactory, context.options.modelsMapper.user, true, next); + }; + + usersRepo.getUserByMail = function (mail, next) { + client.executeQuery('(&(objectClass=posixAccount)(mail=' + mail + '))', userFactory, context.options.modelsMapper.user, true, next); + }; + usersRepo.searchUserByName = function (name, next) { - client.executeQuery('(&(objectClass=posixAccount)(|(cn=' + name + '*)))', userFactory, context.options.modelsMapper.user, false, next); + client.executeQuery('(&(objectClass=posixAccount)(cn=' + name + '*))', userFactory, context.options.modelsMapper.user, false, next); }; - + usersRepo.searchUserByPhone = function (phone, next) { - client.executeQuery('(&(objectClass=posixAccount)(|(telephoneNumber=*' + phone + '*)))', userFactory, context.options.modelsMapper.user, false, next); + client.executeQuery('(&(objectClass=posixAccount)(telephoneNumber=*' + phone + '*))', userFactory, context.options.modelsMapper.user, false, next); }; - + usersRepo.searchUserByUnitAcronym = function (unitAcronym, next) { - client.executeQuery('(&(objectClass=posixAccount)(|(ou=' + unitAcronym + ')))', userFactory, context.options.modelsMapper.user, false, next); + client.executeQuery('(&(objectClass=posixAccount)(ou=*' + unitAcronym + '*))', userFactory, context.options.modelsMapper.user, false, next); }; /* The plural forms always return a list, regarding of whether the search * criterion is unique. */ usersRepo.getUsersBySciper = function (sciper, next) { - client.executeQuery('(&(objectClass=posixAccount)(|(uniqueIdentifier=' + sciper + ')))', userFactory, context.options.modelsMapper.user, false, next); + client.executeQuery('(&(objectClass=posixAccount)(uniqueIdentifier=' + sciper + '))', userFactory, context.options.modelsMapper.user, false, next); }; usersRepo.getUsersByName = function (name, next) { - client.executeQuery('(&(objectClass=posixAccount)(|(cn=' + name + ')))', userFactory, context.options.modelsMapper.user, false, next); + client.executeQuery('(&(objectClass=posixAccount)(cn=' + name + '))', userFactory, context.options.modelsMapper.user, false, next); }; usersRepo.getUsersByPhone = function (phone, next) { - client.executeQuery('(&(objectClass=posixAccount)(|(telephoneNumber=*' + phone + '*)))', userFactory, context.options.modelsMapper.user, false, next); + client.executeQuery('(&(objectClass=posixAccount)(|(telephoneNumber=' + phone + ')(telephoneNumber=+41 21 69' + phone + ')))', userFactory, context.options.modelsMapper.user, false, next); + }; + + usersRepo.getUsersByMail = function (mail, next) { + client.executeQuery('(&(objectClass=posixAccount)(mail=' + mail + '))', userFactory, context.options.modelsMapper.user, false, next); }; usersRepo.getUsersByUnitAcronym = function (unitAcronym, next) { - client.executeQuery('(&(objectClass=posixAccount)(|(ou=' + unitAcronym + ')))', userFactory, context.options.modelsMapper.user, false, next); + client.executeQuery('(&(objectClass=posixAccount)(ou=' + unitAcronym + '))', userFactory, context.options.modelsMapper.user, false, next); }; - + return usersRepo; }; \ No newline at end of file diff --git a/samples/sample-connectionPool.js b/samples/sample-connectionPool.js new file mode 100644 index 0000000..c125b98 --- /dev/null +++ b/samples/sample-connectionPool.js @@ -0,0 +1,62 @@ +const debug = require('debug')('connection-pool'); + +const ConnectionPool = require('../connection-pool.js'); +const ldap = require('ldapjs'); +const executeQueryPromise = require('../ldapjs-promise'); + + +const pool = new ConnectionPool( + 3, + () =>ldap.createClient({ + url: 'ldap://ldap.epfl.ch', + timeLimit: 1, + sizeLimit: 10 + }), + (client) => client.unbind() +); + +sleep = (secondes) => { + return new Promise((resolve,reject) => { + setTimeout(() => resolve(), secondes*1000); + }) +} + +doSomething = async(client, mail) => +{ + let opts = { + filter: `(&(mail=${mail}@epfl.ch))`, + scope: 'sub', + }; + await sleep(4); + debug("Slept..."); + let result = await executeQueryPromise(client, "o=epfl,c=ch", opts); + console.log(result); +} + +pool.add(function(client) { + return doSomething(client, "gregory.charmier"); +}).then(function(){ console.log("job 1 done")}) + +pool.add(function(client) { + return doSomething(client, "dominique.quatravaux"); +}).then(function(){ console.log("job 2 done")}) + +pool.add(function(client) { + return doSomething(client, "nicolas.borboen"); +}).then(function(){ console.log("job 3 done")}) + +pool.add(function(client) { + return doSomething(client, "julien.delasoie"); +}).then(function(){ console.log("job 4 done")}) + +pool.add(function(client) { + return doSomething(client, "christian.zufferey"); +}).then(function(){ console.log("job 5 done")}) + +pool.add(function(client) { + return doSomething(client, "nicolas.reymond"); +}).then(function(){ console.log("job 6 done")}) + +pool.add(function() { + return pool.close(); +}).then(function(){ console.log("Close all LDAP connections")}) diff --git a/samples/sample-getUnit.js b/samples/sample-getUnit.js index 3dafe66..31a4049 100644 --- a/samples/sample-getUnit.js +++ b/samples/sample-getUnit.js @@ -4,11 +4,18 @@ * Public */ let publicLdapContext = require('../context')(); - publicLdapContext.units.getUnitByName('enac-it', function(err, data) { console.log(JSON.stringify(data, null, 2)); }); +publicLdapContext.units.getUnitById('0184', function(err, data) { + console.log(JSON.stringify(data, null, 2)); +}); + +publicLdapContext.units.getUnitByUniqueIdentifier(10208, function(err, data) { + console.log(JSON.stringify(data, null, 2)); +}); + /* * Full @@ -16,7 +23,6 @@ publicLdapContext.units.getUnitByName('enac-it', function(err, data) { let fullLdapContext = require('../context')(); fullLdapContext.options.modelsMapper = fullLdapContext.viewModelsMappers.full; - console.time("first"); fullLdapContext.units.searchUnitByName('enac', function(err, data) { //console.log(JSON.stringify(data, null, 2)); diff --git a/samples/sample-getUserBySciper.js b/samples/sample-getUserBySciper.js index c512386..b330b9a 100644 --- a/samples/sample-getUserBySciper.js +++ b/samples/sample-getUserBySciper.js @@ -44,4 +44,4 @@ customLdapContext.users.getUserBySciper(169419, function (err, data) { */ publicLdapContext.users.getUsersByUnitAcronym('ENAC-IT', function (err, data) { console.log(JSON.stringify(data, null, 2)); -}); \ No newline at end of file +}); diff --git a/test/init.js b/test/init.js new file mode 100644 index 0000000..e2331b7 --- /dev/null +++ b/test/init.js @@ -0,0 +1,13 @@ +before(function() { + // console.log('before test in every file'); + var fullLdapContext = require('../context')(); + fullLdapContext.options.modelsMapper = fullLdapContext.viewModelsMappers.full; + // create a context for all the test, allowing to create/remove cache + this.fullLdapContext = fullLdapContext; +}); + +beforeEach(function() { + // Be sure to clear the cache before the tests... + // console.log('clearing cache...'); + this.fullLdapContext.memoryCache.flushAll(); +}); diff --git a/test/sciperTest.js b/test/sciperTest.js deleted file mode 100644 index 3120711..0000000 --- a/test/sciperTest.js +++ /dev/null @@ -1,28 +0,0 @@ -var assert = require('assert'); -var fullLdapContext = require('../context')(); -fullLdapContext.options.modelsMapper = fullLdapContext.viewModelsMappers.full; - -describe('Scipers', function () { - - it('Kermit La Grenouille', function (done) { - fullLdapContext.users.getUserBySciper(133134, function (err, data) { - assert.equal(data.displayName, "Kermit La Grenouille"); - done(); - }); - }); - - it('have two email', function(done) { - fullLdapContext.users.getUserBySciper(162314, function (err, data) { - assert.ok(data.emails.length === 2, "User have 2 email"); - done(); - }); - }); - - it('29 chars email', function (done) { - fullLdapContext.users.getUserBySciper(214370, function (err, data) { - assert.ok(data.emails[0].length === 29, "email adresse is long"); - done(); - }); - }); - -}); diff --git a/test/unitTest.js b/test/unitTest.js new file mode 100644 index 0000000..4f05088 --- /dev/null +++ b/test/unitTest.js @@ -0,0 +1,44 @@ +var assert = require('assert'); + +describe('Units::get', function () { + + it('get unit by id', function(done) { + this.fullLdapContext.units.getUnitById('1906', function (err, data) { + assert.ok(data.name === "Full-Stack Development", "Unit name"); + done(); + }); + }); + + it('get unit by accounting number', function (done) { + this.fullLdapContext.units.getUnitByAccountingNumber('1906', function (err, data) { + assert.ok(data.name === "Full-Stack Development", "Unit name"); + done(); + }); + }); + + it('get unit by unique identifier', function (done) { + this.fullLdapContext.units.getUnitByUniqueIdentifier(13030, function (err, data) { + assert.ok(data.name === "Full-Stack Development", "Unit name"); + done(); + }); + }); + + it('get unit by name', function (done) { + this.fullLdapContext.units.getUnitByName("Full-Stack Development", function (err, data) { + assert.ok(data.uniqueIdentifier === '13030', "Unit unique identifier"); + done(); + }); + }); + +}); + +describe('Units::search', function () { + + it('search unit by name', function (done) { + this.fullLdapContext.units.searchUnitByName("Full-Stack Development", function (err, data) { + assert.ok(data[0].uniqueIdentifier === '13030', "Unit unique identifier"); + done(); + }); + }); + +}); \ No newline at end of file diff --git a/test/userTest.js b/test/userTest.js new file mode 100644 index 0000000..0506a33 --- /dev/null +++ b/test/userTest.js @@ -0,0 +1,125 @@ +var assert = require('assert'); + +describe('User::get', function () { + + it('getUserBySciper should get Kermi La Grenouille', function (done) { + this.fullLdapContext.users.getUserBySciper(133134, function (err, data) { + assert.equal(data.displayName, "Kermi La Grenouille"); + done(); + }); + }); + + it('getUserBySciper should handle users with two emails', function(done) { + this.fullLdapContext.users.getUserBySciper(133134, function (err, data) { + assert.ok(data.emails.length === 2, "User have 2 emails"); + done(); + }); + }); + + it('getUserBySciper should return correct email length', function (done) { + this.fullLdapContext.users.getUserBySciper(169419, function (err, data) { + assert.ok(data.emails[0].length === 23, "Email adresse has the correct length"); + done(); + }); + }); + + it('getUserByName should find Kermi La Grenouille', function (done) { + this.fullLdapContext.users.getUserByName('Kermi La Grenouille', function (err, data) { + assert.equal(data.displayName, 'Kermi La Grenouille'); + done(); + }); + }); + + it('getUserByPhone should find 169419', function (done) { + this.fullLdapContext.users.getUserByPhone('+41 21 6935455', function (err, data) { + assert.equal(data.sciper, '169419'); + done(); + }); + }); + + it('getUserByPhone should find 169419', function (done) { + this.fullLdapContext.users.getUserByPhone('35455', function (err, data) { + assert.equal(data.sciper, '169419'); + done(); + }); + }); + + // Watch out: user with guest account on their EPFL email can appear first. + it('getUserByMail should find 169419', function (done) { + this.fullLdapContext.users.getUserByMail('nicolas.borboen@epfl.ch', function (err, data) { + assert.equal(data.sciper, '169419'); + done(); + }); + }); + +}); + +describe('User::search', function () { + + it('searchUserByName should search Kermi La Grenouille', function (done) { + this.fullLdapContext.users.searchUserByName('Kermi', function (err, data) { + assert.equal(data[0].displayName, 'Kermi La Grenouille'); + done(); + }); + }); + + it('searchUserByPhone should return 169419', function (done) { + this.fullLdapContext.users.searchUserByPhone('35455', function (err, data) { + assert.equal(data[0].sciper, '169419'); + done(); + }); + }); + + it('searchUserByUnitAcronym should search all members of ISAS-G*, including Kermi', function (done) { + this.fullLdapContext.users.searchUserByUnitAcronym('ISAS-G', function (err, data) { + let k = data.filter(obj => { + return obj.displayName === 'Kermi La Grenouille'; + }) + assert.equal(k[0].displayName, 'Kermi La Grenouille'); + done(); + }); + }); + +}); + +describe('Users::get', function () { + + it('getUsersBySciper should get Kermi La Grenouille', function (done) { + this.fullLdapContext.users.getUsersBySciper(133134, function (err, data) { + assert.equal(data[0].displayName, 'Kermi La Grenouille'); + done(); + }); + }); + + it('getUsersByName should get Kermi La Grenouille', function (done) { + this.fullLdapContext.users.getUsersByName('Kermi La Grenouille', function (err, data) { + assert.equal(data[0].displayName, 'Kermi La Grenouille'); + done(); + }); + }); + + it('getUsersByPhone should get 169419', function (done) { + this.fullLdapContext.users.getUsersByPhone('35455', function (err, data) { + assert.equal(data[0].sciper, '169419'); + done(); + }); + }); + + it('getUsersByMail should find 169419', function (done) { + this.fullLdapContext.users.getUsersByMail('nicolas.borboen@epfl.ch', function (err, data) { + assert.equal(data[0].sciper, '169419'); + done(); + }); + }); + + it('getUsersByUnitAcronym should search all members of ISAS-GE, including Kermi', function (done) { + this.fullLdapContext.users.getUsersByUnitAcronym('ISAS-GE', function (err, data) { + let k = data.filter(obj => { + return obj.displayName === 'Kermi La Grenouille'; + }) + assert.equal(k[0].displayName, 'Kermi La Grenouille'); + done(); + }); + }); + +}); diff --git a/viewModels/custom/modelsMapper.js b/viewModels/custom/modelsMapper.js index 513e0fe..cbdc7be 100644 --- a/viewModels/custom/modelsMapper.js +++ b/viewModels/custom/modelsMapper.js @@ -20,6 +20,6 @@ module.exports = function () { throw new Error("No schema for unit"); } } - + return mapper; } \ No newline at end of file diff --git a/viewModels/full/modelsMapper.js b/viewModels/full/modelsMapper.js index 2a24b6f..c19f163 100644 --- a/viewModels/full/modelsMapper.js +++ b/viewModels/full/modelsMapper.js @@ -2,14 +2,14 @@ module.exports = function () { let mapper = {}; - + mapper.user = function (inputModel) { return inputModel; } - + mapper.unit = function (inputModel) { return inputModel; } - + return mapper; } \ No newline at end of file diff --git a/viewModels/public/modelsMapper.js b/viewModels/public/modelsMapper.js index dd424bc..7a78531 100644 --- a/viewModels/public/modelsMapper.js +++ b/viewModels/public/modelsMapper.js @@ -3,7 +3,7 @@ module.exports = function () { let omapper = require('o-mapper'); let mapper = {}; - + mapper.user = function(inputModel) { let schema = { displayName: { @@ -22,10 +22,10 @@ module.exports = function () { key: 'accreds' } }; - + return omapper(inputModel, schema); } - + mapper.unit = function (inputModel) { let schema = { cn: { @@ -47,7 +47,7 @@ module.exports = function () { key: 'address' } }; - + return omapper(inputModel, schema); }