From a433489e982bcbfcd0c6f8d7ed985ef236569284 Mon Sep 17 00:00:00 2001 From: its-sami Date: Fri, 10 Nov 2023 12:12:57 +0000 Subject: [PATCH] Add integration test for PasswordPolicyControl (#949) --- .github/workflows/integration.yml | 2 +- docker-compose.yml | 2 +- package.json | 4 +- test-integration/client/issue-946.test.js | 87 +++++++++++++++++++++++ 4 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 test-integration/client/issue-946.test.js diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 2a3a14e..71e1bf5 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -20,7 +20,7 @@ jobs: services: openldap: - image: ghcr.io/ldapjs/docker-test-openldap/openldap:2023-08-15 + image: ghcr.io/ldapjs/docker-test-openldap/openldap:2023-10-30 ports: - 389:389 - 636:636 diff --git a/docker-compose.yml b/docker-compose.yml index 0a7e335..19c4b5f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: openldap: - image: ghcr.io/ldapjs/docker-test-openldap/openldap:2023-08-15 + image: ghcr.io/ldapjs/docker-test-openldap/openldap:2023-10-30 ports: - 389:389 - 636:636 diff --git a/package.json b/package.json index 883ad0d..2faa9cf 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,10 @@ "@ldapjs/asn1": "^2.0.0", "@ldapjs/attribute": "^1.0.0", "@ldapjs/change": "^1.0.0", - "@ldapjs/controls": "^2.0.0", + "@ldapjs/controls": "^2.1.0", "@ldapjs/dn": "^1.1.0", "@ldapjs/filter": "^2.1.1", - "@ldapjs/messages": "^1.2.1", + "@ldapjs/messages": "^1.3.0", "@ldapjs/protocol": "^1.2.1", "abstract-logging": "^2.0.1", "assert-plus": "^1.0.0", diff --git a/test-integration/client/issue-946.test.js b/test-integration/client/issue-946.test.js new file mode 100644 index 0000000..230c0d6 --- /dev/null +++ b/test-integration/client/issue-946.test.js @@ -0,0 +1,87 @@ +'use strict' + +const tap = require('tap') +const ldapjs = require('../../lib') + +const SCHEME = process.env.SCHEME || 'ldap' +const HOST = process.env.HOST || '127.0.0.1' +const PORT = process.env.PORT || 389 +const baseURL = `${SCHEME}://${HOST}:${PORT}` + +tap.test('can use password policy response', t => { + const client = ldapjs.createClient({ url: baseURL }) + const targetDN = 'cn=Bender Bending Rodríguez,ou=people,dc=planetexpress,dc=com' + + client.bind('cn=admin,dc=planetexpress,dc=com', 'GoodNewsEveryone', (err, res) => { + t.error(err) + t.ok(res) + t.equal(res.status, 0) + + const newPassword = 'bender2' + changePassword(client, newPassword, () => { + client.unbind() + bindNewClient(newPassword, { error: 2 }, (client) => { + const newPassword = 'bender' + changePassword(client, newPassword, () => { + client.unbind() + bindNewClient(newPassword, { timeBeforeExpiration: 1000 }, (client) => { + client.unbind(t.end) + }) + }) + }) + }) + }) + + function bindNewClient (pwd, expected, callback) { + const client = ldapjs.createClient({ url: baseURL }) + const control = new ldapjs.PasswordPolicyControl() + + client.bind(targetDN, pwd, control, (err, res) => { + t.error(err) + t.ok(res) + t.equal(res.status, 0) + + let error = null + let timeBeforeExpiration = null + let graceAuthNsRemaining = null + + res.controls.forEach(control => { + if (control.type === ldapjs.PasswordPolicyControl.OID) { + error = control.value.error ?? error + timeBeforeExpiration = control.value.timeBeforeExpiration ?? timeBeforeExpiration + graceAuthNsRemaining = control.value.graceAuthNsRemaining ?? graceAuthNsRemaining + } + }) + + if (expected.error !== undefined) { + t.equal(error, expected.error) + } + if (expected.timeBeforeExpiration !== undefined) { + t.equal(timeBeforeExpiration, expected.timeBeforeExpiration) + } + if (expected.graceAuthNsRemaining !== undefined) { + t.equal(graceAuthNsRemaining, expected.graceAuthNsRemaining) + } + + callback(client) + }) + } + + function changePassword (client, newPwd, callback) { + const change = new ldapjs.Change({ + operation: 'replace', + modification: new ldapjs.Attribute({ + type: 'userPassword', + values: newPwd + }) + }) + + client.modify(targetDN, change, (err, res) => { + t.error(err) + t.ok(res) + t.equal(res.status, 0) + + callback() + }) + } +})