laundry.test.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. 'use strict'
  2. const tap = require('tap')
  3. const { getSock, uuid } = require('./utils')
  4. const { SearchResultEntry } = require('@ldapjs/messages')
  5. const Attribute = require('@ldapjs/attribute')
  6. const ldap = require('../lib')
  7. function search (t, options, callback) {
  8. t.context.client.search(t.context.suffix, options, function (err, res) {
  9. t.error(err)
  10. t.ok(res)
  11. let found = false
  12. res.on('searchEntry', function (entry) {
  13. t.ok(entry)
  14. found = true
  15. })
  16. res.on('end', function () {
  17. t.ok(found)
  18. if (callback) return callback()
  19. return t.end()
  20. })
  21. })
  22. }
  23. tap.beforeEach((t) => {
  24. return new Promise((resolve, reject) => {
  25. const suffix = `dc=${uuid()}`
  26. const server = ldap.createServer()
  27. t.context.server = server
  28. t.context.socketPath = getSock()
  29. t.context.suffix = suffix
  30. server.on('error', err => {
  31. server.close(() => reject(err))
  32. })
  33. server.bind('cn=root', function (req, res, next) {
  34. res.end()
  35. return next()
  36. })
  37. server.search(suffix, function (req, res) {
  38. const entry = new SearchResultEntry({
  39. entry: 'cn=foo,' + suffix,
  40. attributes: Attribute.fromObject({
  41. objectclass: ['person', 'top'],
  42. cn: 'Pogo Stick',
  43. sn: 'Stick',
  44. givenname: 'ogo',
  45. mail: uuid() + '@pogostick.org'
  46. })
  47. })
  48. if (req.filter.matches(entry.attributes)) {
  49. res.send(entry)
  50. }
  51. res.end()
  52. })
  53. server.listen(t.context.socketPath, function () {
  54. t.context.client = ldap.createClient({
  55. socketPath: t.context.socketPath
  56. })
  57. t.context.client.on('error', (err) => {
  58. t.context.server.close(() => reject(err))
  59. })
  60. t.context.client.on('connectError', (err) => {
  61. t.context.server.close(() => reject(err))
  62. })
  63. t.context.client.on('connect', (socket) => {
  64. t.context.socket = socket
  65. resolve()
  66. })
  67. })
  68. })
  69. })
  70. tap.afterEach((t) => {
  71. return new Promise((resolve, reject) => {
  72. if (!t.context.client) return resolve()
  73. t.context.client.unbind(() => {
  74. t.context.server.close((err) => {
  75. if (err) return reject(err)
  76. resolve()
  77. })
  78. })
  79. })
  80. })
  81. tap.test('Evolution search filter (GH-3)', function (t) {
  82. // This is what Evolution sends, when searching for a contact 'ogo'. Wow.
  83. const filter =
  84. '(|(cn=ogo*)(givenname=ogo*)(sn=ogo*)(mail=ogo*)(member=ogo*)' +
  85. '(primaryphone=ogo*)(telephonenumber=ogo*)(homephone=ogo*)(mobile=ogo*)' +
  86. '(carphone=ogo*)(facsimiletelephonenumber=ogo*)' +
  87. '(homefacsimiletelephonenumber=ogo*)(otherphone=ogo*)' +
  88. '(otherfacsimiletelephonenumber=ogo*)(internationalisdnnumber=ogo*)' +
  89. '(pager=ogo*)(radio=ogo*)(telex=ogo*)(assistantphone=ogo*)' +
  90. '(companyphone=ogo*)(callbackphone=ogo*)(tty=ogo*)(o=ogo*)(ou=ogo*)' +
  91. '(roomnumber=ogo*)(title=ogo*)(businessrole=ogo*)(managername=ogo*)' +
  92. '(assistantname=ogo*)(postaladdress=ogo*)(l=ogo*)(st=ogo*)' +
  93. '(postofficebox=ogo*)(postalcode=ogo*)(c=ogo*)(homepostaladdress=ogo*)' +
  94. '(mozillahomelocalityname=ogo*)(mozillahomestate=ogo*)' +
  95. '(mozillahomepostalcode=ogo*)(mozillahomecountryname=ogo*)' +
  96. '(otherpostaladdress=ogo*)(jpegphoto=ogo*)(usercertificate=ogo*)' +
  97. '(labeleduri=ogo*)(displayname=ogo*)(spousename=ogo*)(note=ogo*)' +
  98. '(anniversary=ogo*)(birthdate=ogo*)(mailer=ogo*)(fileas=ogo*)' +
  99. '(category=ogo*)(calcaluri=ogo*)(calfburl=ogo*)(icscalendar=ogo*))'
  100. return search(t, filter)
  101. })
  102. tap.test('GH-49 Client errors on bad attributes', function (t) {
  103. const searchOpts = {
  104. filter: 'cn=*ogo*',
  105. scope: 'one',
  106. attributes: 'dn'
  107. }
  108. return search(t, searchOpts)
  109. })
  110. tap.test('GH-55 Client emits connect multiple times', function (t) {
  111. const c = ldap.createClient({
  112. socketPath: t.context.socketPath
  113. })
  114. let count = 0
  115. c.on('connect', function (socket) {
  116. t.ok(socket)
  117. count++
  118. c.bind('cn=root', 'secret', function (err) {
  119. t.error(err)
  120. c.unbind(function () {
  121. t.equal(count, 1)
  122. t.end()
  123. })
  124. })
  125. })
  126. })