issue-845.test.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. 'use strict'
  2. const tap = require('tap')
  3. const { SearchResultEntry, SearchRequest } = require('@ldapjs/messages')
  4. const ldapjs = require('../')
  5. const server = ldapjs.createServer()
  6. const SUFFIX = ''
  7. const directory = {
  8. 'dc=example,dc=com': {
  9. objectclass: 'example',
  10. dc: 'example',
  11. cn: 'example'
  12. }
  13. }
  14. server.bind(SUFFIX, (req, res, done) => {
  15. res.end()
  16. return done()
  17. })
  18. server.search(SUFFIX, (req, res, done) => {
  19. const dn = req.dn.toString().toLowerCase()
  20. if (Object.hasOwn(directory, dn) === false) {
  21. return done(Error('not in directory'))
  22. }
  23. switch (req.scope) {
  24. case SearchRequest.SCOPE_BASE:
  25. case SearchRequest.SCOPE_SUBTREE: {
  26. res.send(new SearchResultEntry({ objectName: `dc=${req.scopeName}` }))
  27. break
  28. }
  29. }
  30. res.end()
  31. done()
  32. })
  33. tap.beforeEach(t => {
  34. return new Promise((resolve, reject) => {
  35. server.listen(0, '127.0.0.1', (err) => {
  36. if (err) return reject(err)
  37. t.context.url = server.url
  38. t.context.client = ldapjs.createClient({ url: [server.url] })
  39. t.context.searchOpts = {
  40. filter: '(&(objectClass=*))',
  41. scope: 'sub',
  42. attributes: ['dn', 'cn']
  43. }
  44. resolve()
  45. })
  46. })
  47. })
  48. tap.afterEach(t => {
  49. return new Promise((resolve, reject) => {
  50. t.context.client.destroy()
  51. server.close((err) => {
  52. if (err) return reject(err)
  53. resolve()
  54. })
  55. })
  56. })
  57. tap.test('rejects if search not in directory', t => {
  58. const { client, searchOpts } = t.context
  59. client.search('dc=nope', searchOpts, (err, res) => {
  60. t.error(err)
  61. res.on('error', err => {
  62. // TODO: plain error messages should not be lost
  63. // This should be fixed in a revamp of the server code.
  64. // ~ jsumners 2023-03-08
  65. t.equal(err.lde_message, 'Operations Error')
  66. t.end()
  67. })
  68. })
  69. })
  70. tap.test('base scope matches', t => {
  71. const { client, searchOpts } = t.context
  72. searchOpts.scope = 'base'
  73. client.search('dc=example,dc=com', searchOpts, (err, res) => {
  74. t.error(err)
  75. res.on('error', (err) => {
  76. t.error(err)
  77. t.end()
  78. })
  79. res.on('searchEntry', entry => {
  80. t.equal(entry.objectName.toString(), 'dc=base')
  81. t.end()
  82. })
  83. })
  84. })
  85. tap.test('sub scope matches', t => {
  86. const { client, searchOpts } = t.context
  87. client.search('dc=example,dc=com', searchOpts, (err, res) => {
  88. t.error(err)
  89. res.on('error', (err) => {
  90. t.error(err)
  91. t.end()
  92. })
  93. res.on('searchEntry', entry => {
  94. t.equal(entry.objectName.toString(), 'dc=subtree')
  95. t.end()
  96. })
  97. })
  98. })