ldap-rest 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +48 -0
  3. package/bin/cleanup-external-users.mjs +219 -0
  4. package/bin/index.mjs +54 -0
  5. package/bin/sync-james.mjs +190 -0
  6. package/dist/abstract/ldapFlat.js +1 -0
  7. package/dist/abstract/plugin.js +1 -0
  8. package/dist/abstract/twakePlugin.js +1 -0
  9. package/dist/bin/index.js +1 -0
  10. package/dist/config/args.js +1 -0
  11. package/dist/lib/auth/base.js +1 -0
  12. package/dist/lib/authz/base.js +1 -0
  13. package/dist/lib/expressFormatedResponses.js +1 -0
  14. package/dist/lib/ldapActions.js +1 -0
  15. package/dist/lib/parseConfig.js +1 -0
  16. package/dist/lib/utils.js +1 -0
  17. package/dist/logger/winston.js +1 -0
  18. package/dist/plugins/auth/authzLinid1.js +1 -0
  19. package/dist/plugins/auth/authzPerBranch.js +1 -0
  20. package/dist/plugins/auth/crowdsec.js +1 -0
  21. package/dist/plugins/auth/llng.js +1 -0
  22. package/dist/plugins/auth/openidconnect.js +1 -0
  23. package/dist/plugins/auth/rateLimit.js +1 -0
  24. package/dist/plugins/auth/token.js +1 -0
  25. package/dist/plugins/configApi.js +1 -0
  26. package/dist/plugins/demo/helloworld.js +1 -0
  27. package/dist/plugins/ldap/bulkImport.js +1 -0
  28. package/dist/plugins/ldap/departmentSync.js +1 -0
  29. package/dist/plugins/ldap/externalUsersInGroups.js +1 -0
  30. package/dist/plugins/ldap/flatGeneric.js +1 -0
  31. package/dist/plugins/ldap/groups.js +1 -0
  32. package/dist/plugins/ldap/onChange.js +1 -0
  33. package/dist/plugins/ldap/organization.js +1 -0
  34. package/dist/plugins/ldap/trash.js +1 -0
  35. package/dist/plugins/priority.json.js +1 -0
  36. package/dist/plugins/static.js +1 -0
  37. package/dist/plugins/twake/calendarResources.js +1 -0
  38. package/dist/plugins/twake/james.js +1 -0
  39. package/dist/plugins/weblogs.js +1 -0
  40. package/dist/src/abstract/ldapFlat.d.ts +94 -0
  41. package/dist/src/abstract/plugin.d.ts +43 -0
  42. package/dist/src/abstract/twakePlugin.d.ts +90 -0
  43. package/dist/src/bin/index.d.ts +43 -0
  44. package/dist/src/browser/ldap-group-editor/LdapGroupEditor.d.ts +31 -0
  45. package/dist/src/browser/ldap-group-editor/api/GroupApiClient.d.ts +23 -0
  46. package/dist/src/browser/ldap-group-editor/components/CreateGroupModal.d.ts +19 -0
  47. package/dist/src/browser/ldap-group-editor/components/GroupPropertyEditor.d.ts +30 -0
  48. package/dist/src/browser/ldap-group-editor/components/GroupTree.d.ts +17 -0
  49. package/dist/src/browser/ldap-group-editor/components/MoveGroupModal.d.ts +20 -0
  50. package/dist/src/browser/ldap-group-editor/index.d.ts +6 -0
  51. package/dist/src/browser/ldap-group-editor/types.d.ts +58 -0
  52. package/dist/src/browser/ldap-resource-editor/api/ResourceApiClient.d.ts +53 -0
  53. package/dist/src/browser/ldap-resource-editor/cache/CacheManager.d.ts +65 -0
  54. package/dist/src/browser/ldap-resource-editor/index.d.ts +6 -0
  55. package/dist/src/browser/ldap-resource-editor/types.d.ts +78 -0
  56. package/dist/src/browser/ldap-tree-viewer/LdapTreeViewer.d.ts +26 -0
  57. package/dist/src/browser/ldap-tree-viewer/api/LdapApiClient.d.ts +30 -0
  58. package/dist/src/browser/ldap-tree-viewer/components/TreeNode.d.ts +17 -0
  59. package/dist/src/browser/ldap-tree-viewer/components/TreeRoot.d.ts +14 -0
  60. package/dist/src/browser/ldap-tree-viewer/index.d.ts +7 -0
  61. package/dist/src/browser/ldap-tree-viewer/store/Store.d.ts +18 -0
  62. package/dist/src/browser/ldap-tree-viewer/store/actions.d.ts +28 -0
  63. package/dist/src/browser/ldap-tree-viewer/store/reducers.d.ts +7 -0
  64. package/dist/src/browser/ldap-tree-viewer/types.d.ts +34 -0
  65. package/dist/src/browser/ldap-unit-editor/LdapUnitEditor.d.ts +27 -0
  66. package/dist/src/browser/ldap-unit-editor/api/UnitApiClient.d.ts +24 -0
  67. package/dist/src/browser/ldap-unit-editor/components/MoveUnitModal.d.ts +28 -0
  68. package/dist/src/browser/ldap-unit-editor/components/UnitPropertyEditor.d.ts +28 -0
  69. package/dist/src/browser/ldap-unit-editor/components/UnitTree.d.ts +18 -0
  70. package/dist/src/browser/ldap-unit-editor/index.d.ts +6 -0
  71. package/dist/src/browser/ldap-unit-editor/types.d.ts +55 -0
  72. package/dist/src/browser/ldap-user-editor/LdapUserEditor.d.ts +32 -0
  73. package/dist/src/browser/ldap-user-editor/api/UserApiClient.d.ts +55 -0
  74. package/dist/src/browser/ldap-user-editor/cache/CacheManager.d.ts +65 -0
  75. package/dist/src/browser/ldap-user-editor/components/MoveUserModal.d.ts +28 -0
  76. package/dist/src/browser/ldap-user-editor/components/PointerField.d.ts +22 -0
  77. package/dist/src/browser/ldap-user-editor/components/UserEditor.d.ts +46 -0
  78. package/dist/src/browser/ldap-user-editor/components/UserList.d.ts +24 -0
  79. package/dist/src/browser/ldap-user-editor/components/UserTree.d.ts +24 -0
  80. package/dist/src/browser/ldap-user-editor/index.d.ts +7 -0
  81. package/dist/src/browser/ldap-user-editor/types.d.ts +67 -0
  82. package/dist/src/browser/shared/components/Modal.d.ts +38 -0
  83. package/dist/src/browser/shared/components/StatusMessage.d.ts +48 -0
  84. package/dist/src/browser/shared/index.d.ts +10 -0
  85. package/dist/src/browser/shared/types/index.d.ts +65 -0
  86. package/dist/src/browser/shared/utils/dom.d.ts +33 -0
  87. package/dist/src/browser/shared/utils/form.d.ts +28 -0
  88. package/dist/src/browser/shared/utils/schema.d.ts +29 -0
  89. package/dist/src/config/args.d.ts +128 -0
  90. package/dist/src/config/schema.d.ts +18 -0
  91. package/dist/src/hooks.d.ts +76 -0
  92. package/dist/src/lib/auth/base.d.ts +9 -0
  93. package/dist/src/lib/authz/base.d.ts +63 -0
  94. package/dist/src/lib/expressFormatedResponses.d.ts +26 -0
  95. package/dist/src/lib/ldapActions.d.ts +91 -0
  96. package/dist/src/lib/parseConfig.d.ts +23 -0
  97. package/dist/src/lib/utils.d.ts +73 -0
  98. package/dist/src/logger/winston.d.ts +3 -0
  99. package/dist/src/plugins/auth/authzLinid1.d.ts +46 -0
  100. package/dist/src/plugins/auth/authzPerBranch.d.ts +59 -0
  101. package/dist/src/plugins/auth/crowdsec.d.ts +29 -0
  102. package/dist/src/plugins/auth/llng.d.ts +8 -0
  103. package/dist/src/plugins/auth/openidconnect.d.ts +11 -0
  104. package/dist/src/plugins/auth/rateLimit.d.ts +24 -0
  105. package/dist/src/plugins/auth/token.d.ts +17 -0
  106. package/dist/src/plugins/configApi.d.ts +24 -0
  107. package/dist/src/plugins/demo/helloworld.d.ts +12 -0
  108. package/dist/src/plugins/ldap/bulkImport.d.ts +48 -0
  109. package/dist/src/plugins/ldap/departmentSync.d.ts +35 -0
  110. package/dist/src/plugins/ldap/externalUsersInGroups.d.ts +21 -0
  111. package/dist/src/plugins/ldap/flatGeneric.d.ts +31 -0
  112. package/dist/src/plugins/ldap/groups.d.ts +95 -0
  113. package/dist/src/plugins/ldap/onChange.d.ts +32 -0
  114. package/dist/src/plugins/ldap/organization.d.ts +65 -0
  115. package/dist/src/plugins/ldap/trash.d.ts +52 -0
  116. package/dist/src/plugins/static.d.ts +7 -0
  117. package/dist/src/plugins/twake/calendarResources.d.ts +31 -0
  118. package/dist/src/plugins/twake/james.d.ts +83 -0
  119. package/dist/src/plugins/weblogs.d.ts +8 -0
  120. package/docs/DEVELOPER_GUIDE.md +298 -0
  121. package/docs/OPENAPI.md +440 -0
  122. package/docs/PLUGIN_DEPENDENCIES.md +612 -0
  123. package/docs/README.md +466 -0
  124. package/docs/api/REFERENCE.md +983 -0
  125. package/docs/api/REST_API.md +1237 -0
  126. package/docs/authentication.md +469 -0
  127. package/docs/authzLinid1.md +521 -0
  128. package/docs/authzPerBranch.md +596 -0
  129. package/docs/browser/LIBRARIES.md +1196 -0
  130. package/docs/examples/EXAMPLES.md +1659 -0
  131. package/docs/examples/twake-mailbox-type-nomenclature.ldif +37 -0
  132. package/docs/examples/twake-mailbox-type-schema-amendment.ldif +30 -0
  133. package/docs/jamesTeamMailboxes.md +343 -0
  134. package/docs/ldapBulkImport.md +722 -0
  135. package/docs/ldapExternalUsersInGroups.md +325 -0
  136. package/docs/ldapFlatGeneric.md +444 -0
  137. package/docs/ldapGroups.md +589 -0
  138. package/docs/ldapOrganizations.md +659 -0
  139. package/docs/ldapTrash.md +260 -0
  140. package/docs/linagora.png +0 -0
  141. package/docs/onChange.md +318 -0
  142. package/docs/plugins/DEVELOPMENT.md +1219 -0
  143. package/docs/presenterm-fr.md +721 -0
  144. package/docs/presenterm.md +721 -0
  145. package/docs/schemas/SCHEMAS.md +1212 -0
  146. package/docs/static.md +410 -0
  147. package/docs/twakeCalendarResources.md +148 -0
  148. package/docs/twakeJames.md +661 -0
  149. package/docs/weblogs.md +399 -0
  150. package/examples/web/ldap-group-editor.html +113 -0
  151. package/examples/web/ldap-tree-viewer.html +368 -0
  152. package/examples/web/ldap-unit-editor.html +108 -0
  153. package/examples/web/ldap-user-editor.html +412 -0
  154. package/package.json +458 -0
  155. package/static/browser/common-demo.css +450 -0
  156. package/static/browser/ldap-group-editor/LdapGroupEditor.js +207 -0
  157. package/static/browser/ldap-group-editor/LdapGroupEditor.js.map +1 -0
  158. package/static/browser/ldap-group-editor/api/GroupApiClient.js +112 -0
  159. package/static/browser/ldap-group-editor/api/GroupApiClient.js.map +1 -0
  160. package/static/browser/ldap-group-editor/components/CreateGroupModal.js +212 -0
  161. package/static/browser/ldap-group-editor/components/CreateGroupModal.js.map +1 -0
  162. package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js +497 -0
  163. package/static/browser/ldap-group-editor/components/GroupPropertyEditor.js.map +1 -0
  164. package/static/browser/ldap-group-editor/components/GroupTree.js +153 -0
  165. package/static/browser/ldap-group-editor/components/GroupTree.js.map +1 -0
  166. package/static/browser/ldap-group-editor/components/MoveGroupModal.js +235 -0
  167. package/static/browser/ldap-group-editor/components/MoveGroupModal.js.map +1 -0
  168. package/static/browser/ldap-group-editor/index.js +2 -0
  169. package/static/browser/ldap-group-editor/index.js.map +1 -0
  170. package/static/browser/ldap-group-editor/types.js +2 -0
  171. package/static/browser/ldap-group-editor/types.js.map +1 -0
  172. package/static/browser/ldap-group-editor.esm.js +1399 -0
  173. package/static/browser/ldap-group-editor.esm.js.map +1 -0
  174. package/static/browser/ldap-group-editor.js +1407 -0
  175. package/static/browser/ldap-group-editor.js.map +1 -0
  176. package/static/browser/ldap-group-editor.min.js +2 -0
  177. package/static/browser/ldap-group-editor.min.js.map +1 -0
  178. package/static/browser/ldap-resource-editor/api/ResourceApiClient.js +226 -0
  179. package/static/browser/ldap-resource-editor/api/ResourceApiClient.js.map +1 -0
  180. package/static/browser/ldap-resource-editor/cache/CacheManager.js +123 -0
  181. package/static/browser/ldap-resource-editor/cache/CacheManager.js.map +1 -0
  182. package/static/browser/ldap-resource-editor/index.js +2 -0
  183. package/static/browser/ldap-resource-editor/index.js.map +1 -0
  184. package/static/browser/ldap-resource-editor/types.js +2 -0
  185. package/static/browser/ldap-resource-editor/types.js.map +1 -0
  186. package/static/browser/ldap-tree-viewer/LdapTreeViewer.js +187 -0
  187. package/static/browser/ldap-tree-viewer/LdapTreeViewer.js.map +1 -0
  188. package/static/browser/ldap-tree-viewer/api/LdapApiClient.js +50 -0
  189. package/static/browser/ldap-tree-viewer/api/LdapApiClient.js.map +1 -0
  190. package/static/browser/ldap-tree-viewer/components/TreeNode.js +140 -0
  191. package/static/browser/ldap-tree-viewer/components/TreeNode.js.map +1 -0
  192. package/static/browser/ldap-tree-viewer/components/TreeRoot.js +98 -0
  193. package/static/browser/ldap-tree-viewer/components/TreeRoot.js.map +1 -0
  194. package/static/browser/ldap-tree-viewer/index.js +2 -0
  195. package/static/browser/ldap-tree-viewer/index.js.map +1 -0
  196. package/static/browser/ldap-tree-viewer/store/Store.js +29 -0
  197. package/static/browser/ldap-tree-viewer/store/Store.js.map +1 -0
  198. package/static/browser/ldap-tree-viewer/store/actions.js +53 -0
  199. package/static/browser/ldap-tree-viewer/store/actions.js.map +1 -0
  200. package/static/browser/ldap-tree-viewer/store/reducers.js +79 -0
  201. package/static/browser/ldap-tree-viewer/store/reducers.js.map +1 -0
  202. package/static/browser/ldap-tree-viewer/types.js +2 -0
  203. package/static/browser/ldap-tree-viewer/types.js.map +1 -0
  204. package/static/browser/ldap-tree-viewer.css +2 -0
  205. package/static/browser/ldap-tree-viewer.css.map +1 -0
  206. package/static/browser/ldap-tree-viewer.esm.js +606 -0
  207. package/static/browser/ldap-tree-viewer.esm.js.map +1 -0
  208. package/static/browser/ldap-tree-viewer.js +614 -0
  209. package/static/browser/ldap-tree-viewer.js.map +1 -0
  210. package/static/browser/ldap-tree-viewer.min.js +2 -0
  211. package/static/browser/ldap-tree-viewer.min.js.map +1 -0
  212. package/static/browser/ldap-unit-editor/LdapUnitEditor.js +119 -0
  213. package/static/browser/ldap-unit-editor/LdapUnitEditor.js.map +1 -0
  214. package/static/browser/ldap-unit-editor/api/UnitApiClient.js +95 -0
  215. package/static/browser/ldap-unit-editor/api/UnitApiClient.js.map +1 -0
  216. package/static/browser/ldap-unit-editor/components/MoveUnitModal.js +295 -0
  217. package/static/browser/ldap-unit-editor/components/MoveUnitModal.js.map +1 -0
  218. package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js +321 -0
  219. package/static/browser/ldap-unit-editor/components/UnitPropertyEditor.js.map +1 -0
  220. package/static/browser/ldap-unit-editor/components/UnitTree.js +197 -0
  221. package/static/browser/ldap-unit-editor/components/UnitTree.js.map +1 -0
  222. package/static/browser/ldap-unit-editor/index.js +2 -0
  223. package/static/browser/ldap-unit-editor/index.js.map +1 -0
  224. package/static/browser/ldap-unit-editor/types.js +2 -0
  225. package/static/browser/ldap-unit-editor/types.js.map +1 -0
  226. package/static/browser/ldap-unit-editor.esm.js +1013 -0
  227. package/static/browser/ldap-unit-editor.esm.js.map +1 -0
  228. package/static/browser/ldap-unit-editor.js +1021 -0
  229. package/static/browser/ldap-unit-editor.js.map +1 -0
  230. package/static/browser/ldap-unit-editor.min.js +2 -0
  231. package/static/browser/ldap-unit-editor.min.js.map +1 -0
  232. package/static/browser/ldap-user-editor/LdapUserEditor.js +184 -0
  233. package/static/browser/ldap-user-editor/LdapUserEditor.js.map +1 -0
  234. package/static/browser/ldap-user-editor/api/UserApiClient.js +209 -0
  235. package/static/browser/ldap-user-editor/api/UserApiClient.js.map +1 -0
  236. package/static/browser/ldap-user-editor/cache/CacheManager.js +123 -0
  237. package/static/browser/ldap-user-editor/cache/CacheManager.js.map +1 -0
  238. package/static/browser/ldap-user-editor/components/MoveUserModal.js +302 -0
  239. package/static/browser/ldap-user-editor/components/MoveUserModal.js.map +1 -0
  240. package/static/browser/ldap-user-editor/components/PointerField.js +152 -0
  241. package/static/browser/ldap-user-editor/components/PointerField.js.map +1 -0
  242. package/static/browser/ldap-user-editor/components/UserEditor.js +608 -0
  243. package/static/browser/ldap-user-editor/components/UserEditor.js.map +1 -0
  244. package/static/browser/ldap-user-editor/components/UserList.js +181 -0
  245. package/static/browser/ldap-user-editor/components/UserList.js.map +1 -0
  246. package/static/browser/ldap-user-editor/components/UserTree.js +164 -0
  247. package/static/browser/ldap-user-editor/components/UserTree.js.map +1 -0
  248. package/static/browser/ldap-user-editor/index.js +2 -0
  249. package/static/browser/ldap-user-editor/index.js.map +1 -0
  250. package/static/browser/ldap-user-editor/types.js +2 -0
  251. package/static/browser/ldap-user-editor/types.js.map +1 -0
  252. package/static/browser/ldap-user-editor.css +2 -0
  253. package/static/browser/ldap-user-editor.css.map +1 -0
  254. package/static/browser/ldap-user-editor.esm.js +1897 -0
  255. package/static/browser/ldap-user-editor.esm.js.map +1 -0
  256. package/static/browser/ldap-user-editor.js +1905 -0
  257. package/static/browser/ldap-user-editor.js.map +1 -0
  258. package/static/browser/ldap-user-editor.min.js +2 -0
  259. package/static/browser/ldap-user-editor.min.js.map +1 -0
  260. package/static/browser/shared/components/Modal.js +121 -0
  261. package/static/browser/shared/components/Modal.js.map +1 -0
  262. package/static/browser/shared/components/StatusMessage.js +119 -0
  263. package/static/browser/shared/components/StatusMessage.js.map +1 -0
  264. package/static/browser/shared/index.js +7 -0
  265. package/static/browser/shared/index.js.map +1 -0
  266. package/static/browser/shared/types/index.js +37 -0
  267. package/static/browser/shared/types/index.js.map +1 -0
  268. package/static/browser/shared/utils/dom.js +78 -0
  269. package/static/browser/shared/utils/dom.js.map +1 -0
  270. package/static/browser/shared/utils/form.js +234 -0
  271. package/static/browser/shared/utils/form.js.map +1 -0
  272. package/static/browser/shared/utils/schema.js +121 -0
  273. package/static/browser/shared/utils/schema.js.map +1 -0
  274. package/static/browser/shared.esm.js +694 -0
  275. package/static/browser/shared.esm.js.map +1 -0
  276. package/static/browser/shared.js +723 -0
  277. package/static/browser/shared.js.map +1 -0
  278. package/static/browser/shared.min.js +2 -0
  279. package/static/browser/shared.min.js.map +1 -0
  280. package/static/schemas/ad/computers.json +92 -0
  281. package/static/schemas/ad/groups.json +55 -0
  282. package/static/schemas/ad/organizations.json +66 -0
  283. package/static/schemas/ad/users.json +116 -0
  284. package/static/schemas/standard/devices.json +72 -0
  285. package/static/schemas/standard/groups.json +54 -0
  286. package/static/schemas/standard/organizations.json +49 -0
  287. package/static/schemas/standard/users.json +86 -0
  288. package/static/schemas/twake/groups.json +75 -0
  289. package/static/schemas/twake/nomenclature/twakeAccountStatus.json +31 -0
  290. package/static/schemas/twake/nomenclature/twakeDeliveryMode.json +31 -0
  291. package/static/schemas/twake/nomenclature/twakeListType.json +31 -0
  292. package/static/schemas/twake/nomenclature/twakeMailboxType.json +31 -0
  293. package/static/schemas/twake/nomenclature/twakeTitle.json +31 -0
  294. package/static/schemas/twake/organizations.json +52 -0
  295. package/static/schemas/twake/positions.json +32 -0
  296. package/static/schemas/twake/users.json +112 -0
@@ -0,0 +1,659 @@
1
+ # LDAP Organizations Plugin
2
+
3
+ The `ldapOrganizations` plugin provides comprehensive management of hierarchical LDAP organizational structures, with automatic validation of organizational links and paths.
4
+
5
+ ## Overview
6
+
7
+ This plugin manages hierarchical organizations stored as `organizationalUnit` (ou) entries in LDAP. Unlike flat entities managed by the ldapFlat plugin, organizations form a tree structure where each organization can contain sub-organizations. It provides:
8
+
9
+ - Organization CRUD operations (Create, Read, Update, Delete)
10
+ - Hierarchical tree navigation
11
+ - Automatic validation of organizational links (for users/groups)
12
+ - Automatic validation of organizational paths
13
+ - Protection against deleting non-empty organizations
14
+ - Hook integration for lifecycle events
15
+
16
+ ## Configuration
17
+
18
+ ### CLI Arguments
19
+
20
+ ```bash
21
+ --plugin core/ldap/organization \
22
+ --ldap-top-organization "dc=example,dc=com" \
23
+ --ldap-organization-class top,organizationalUnit,twakeDepartment \
24
+ --ldap-organization-link-attribute twakeDepartmentLink \
25
+ --ldap-organization-path-attribute twakeDepartmentPath \
26
+ --ldap-organization-path-separator " / "
27
+ ```
28
+
29
+ ### Configuration Options
30
+
31
+ | Argument | Environment Variable | Default | Description |
32
+ | ----------------------------------------------------------- | ------------------------------------- | ------------------------------- | --------------------------------------------------- |
33
+ | `--ldap-top-organization` | `DM_LDAP_TOP_ORGANIZATION` | _Required_ | DN of the top-level organization |
34
+ | `--ldap-organization-class` / `--ldap-organization-classes` | `DM_LDAP_ORGANIZATION_CLASSES` | `["top", "organizationalUnit"]` | Object classes for organizations |
35
+ | `--ldap-organization-link-attribute` | `DM_LDAP_ORGANIZATION_LINK_ATTRIBUTE` | `twakeDepartmentLink` | Attribute for linking users/groups to organizations |
36
+ | `--ldap-organization-path-attribute` | `DM_LDAP_ORGANIZATION_PATH_ATTRIBUTE` | `twakeDepartmentPath` | Attribute for the organizational path |
37
+ | `--ldap-organization-path-separator` | `DM_LDAP_ORGANIZATION_PATH_SEPARATOR` | `" / "` | Separator for path components |
38
+
39
+ ### Important Notes
40
+
41
+ - **Hierarchical Structure**: Organizations are organized hierarchically using LDAP's DN structure (e.g., `ou=SubDept,ou=Dept,dc=example,dc=com`)
42
+ - **Top Organization Required**: You must specify a top-level organization DN
43
+ - **Link vs Hierarchy**: Organizations themselves use LDAP hierarchy (DN), not the link attribute. The link attribute is used by users/groups to reference their parent organization
44
+ - **Path Validation**: Organizational paths are validated to ensure they match the actual LDAP hierarchy
45
+
46
+ ## Organizational Structure
47
+
48
+ ### Organizations
49
+
50
+ Organizations are hierarchical LDAP entries:
51
+
52
+ - Use LDAP DN structure for hierarchy
53
+ - Have a `twakeDepartmentPath` attribute showing their position in the tree
54
+ - Example: `ou=IT,ou=Departments,dc=example,dc=com`
55
+ - Path: `IT / Departments / Top Organization`
56
+
57
+ ### Users and Groups
58
+
59
+ Users and groups reference organizations via:
60
+
61
+ - `twakeDepartmentLink`: DN of the parent organization (required)
62
+ - `twakeDepartmentPath`: Human-readable path (required)
63
+ - Example user:
64
+ ```json
65
+ {
66
+ "uid": "john.doe",
67
+ "twakeDepartmentLink": "ou=IT,ou=Departments,dc=example,dc=com",
68
+ "twakeDepartmentPath": "IT / Departments / Top Organization"
69
+ }
70
+ ```
71
+
72
+ ## REST API
73
+
74
+ ### Get Top Organization
75
+
76
+ ```http
77
+ GET /api/v1/ldap/organizations/top
78
+ ```
79
+
80
+ Returns the top-level organization configured in `--ldap-top-organization`.
81
+
82
+ **Example:**
83
+
84
+ ```bash
85
+ curl "http://localhost:8081/api/v1/ldap/organizations/top"
86
+ ```
87
+
88
+ **Response (200):**
89
+
90
+ ```json
91
+ {
92
+ "dn": "dc=example,dc=com",
93
+ "o": "gov",
94
+ "description": "Government Organization"
95
+ }
96
+ ```
97
+
98
+ ### Get Organization by DN
99
+
100
+ ```http
101
+ GET /api/v1/ldap/organizations/:dn
102
+ ```
103
+
104
+ **Path Parameter:**
105
+
106
+ - `dn`: Organization DN (URL-encoded)
107
+
108
+ **Example:**
109
+
110
+ ```bash
111
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DIT%2Co%3Dgov%2Cc%3Dmu"
112
+ ```
113
+
114
+ **Response (200):**
115
+
116
+ ```json
117
+ {
118
+ "dn": "ou=IT,dc=example,dc=com",
119
+ "ou": "IT",
120
+ "description": "Information Technology Department",
121
+ "twakeDepartmentPath": "IT / Government"
122
+ }
123
+ ```
124
+
125
+ ### Get Organization Subnodes
126
+
127
+ ```http
128
+ GET /api/v1/ldap/organizations/:dn/subnodes?objectClass={class}
129
+ ```
130
+
131
+ Returns all entries (users, groups, or sub-organizations) that reference this organization via their `twakeDepartmentLink` attribute. Results are automatically paginated to handle large numbers of entries.
132
+
133
+ **Path Parameter:**
134
+
135
+ - `dn`: Organization DN (URL-encoded)
136
+
137
+ **Query Parameters:**
138
+
139
+ - `objectClass` (optional): Filter results by LDAP objectClass (e.g., `twakeAccount`, `groupOfNames`, `organizationalUnit`)
140
+
141
+ **Examples:**
142
+
143
+ ```bash
144
+ # Get all subnodes (users, groups, and sub-OUs)
145
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DIT%2Co%3Dgov%2Cc%3Dmu/subnodes"
146
+
147
+ # Get only users
148
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DIT%2Co%3Dgov%2Cc%3Dmu/subnodes?objectClass=twakeAccount"
149
+
150
+ # Get only groups
151
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DIT%2Co%3Dgov%2Cc%3Dmu/subnodes?objectClass=groupOfNames"
152
+
153
+ # Get only sub-organizations
154
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DIT%2Co%3Dgov%2Cc%3Dmu/subnodes?objectClass=organizationalUnit"
155
+ ```
156
+
157
+ **Response (200):**
158
+
159
+ ```json
160
+ [
161
+ {
162
+ "dn": "uid=john.doe,ou=users,dc=example,dc=com",
163
+ "uid": "john.doe",
164
+ "cn": "John Doe",
165
+ "twakeDepartmentLink": "ou=IT,dc=example,dc=com"
166
+ },
167
+ {
168
+ "dn": "cn=it-admins,ou=groups,dc=example,dc=com",
169
+ "cn": "it-admins",
170
+ "twakeDepartmentLink": "ou=IT,dc=example,dc=com"
171
+ }
172
+ ]
173
+ ```
174
+
175
+ ### Create Organization
176
+
177
+ ```http
178
+ POST /api/v1/ldap/organizations
179
+ ```
180
+
181
+ **Request Body:**
182
+
183
+ ```json
184
+ {
185
+ "ou": "IT",
186
+ "parentDn": "dc=example,dc=com",
187
+ "description": "Information Technology Department",
188
+ "twakeDepartmentPath": "IT / Government"
189
+ }
190
+ ```
191
+
192
+ **Notes:**
193
+
194
+ - `ou` is required (organizational unit name)
195
+ - `parentDn` is optional (defaults to top organization)
196
+ - Organizations are created under the specified parent DN
197
+ - The resulting DN will be `ou={ou},{parentDn}`
198
+
199
+ **Response (200):**
200
+
201
+ ```json
202
+ {
203
+ "success": true
204
+ }
205
+ ```
206
+
207
+ ### Modify Organization
208
+
209
+ ```http
210
+ PUT /api/v1/ldap/organizations/:dn
211
+ ```
212
+
213
+ **Path Parameter:**
214
+
215
+ - `dn`: Organization DN (URL-encoded)
216
+
217
+ **Request Body:**
218
+
219
+ ```json
220
+ {
221
+ "replace": {
222
+ "description": "Updated IT Department"
223
+ },
224
+ "add": {
225
+ "telephoneNumber": "+1234567890"
226
+ },
227
+ "delete": ["l"]
228
+ }
229
+ ```
230
+
231
+ **Important:**
232
+
233
+ - Cannot delete `twakeDepartmentPath` attribute
234
+ - Path modifications are validated against LDAP hierarchy
235
+ - Cannot modify `ou` attribute (this would require a rename operation)
236
+
237
+ **Response (200):**
238
+
239
+ ```json
240
+ {
241
+ "success": true
242
+ }
243
+ ```
244
+
245
+ ### Move Organization
246
+
247
+ ```http
248
+ POST /api/v1/ldap/organizations/:dn/move
249
+ ```
250
+
251
+ **Path Parameter:**
252
+
253
+ - `dn`: Organization DN to move (URL-encoded)
254
+
255
+ **Request Body:**
256
+
257
+ ```json
258
+ {
259
+ "targetOrgDn": "ou=NewParent,dc=example,dc=com"
260
+ }
261
+ ```
262
+
263
+ **Notes:**
264
+
265
+ - Moves an organization to a different parent organization
266
+ - The organization will become a child of the target organization
267
+ - All sub-organizations and linked entities (users/groups) move with it
268
+ - Cannot move an organization into itself or its own descendants (circular reference prevention)
269
+ - Cannot move to the same parent (no-op)
270
+ - Target must be a valid organizational unit
271
+
272
+ **Authorization:**
273
+
274
+ When using the `authzPerBranch` plugin, moving an organization requires:
275
+
276
+ - **Read** permission on the source organization (current parent)
277
+ - **Write** permission on the destination organization (new parent)
278
+
279
+ **Example:**
280
+
281
+ ```bash
282
+ curl -X POST "http://localhost:8081/api/v1/ldap/organizations/ou%3DRecruitment%2Cou%3DHR%2Co%3Dgov%2Cc%3Dmu/move" \
283
+ -H "Content-Type: application/json" \
284
+ -d '{
285
+ "targetOrgDn": "ou=Operations,dc=example,dc=com"
286
+ }'
287
+ ```
288
+
289
+ This moves `ou=Recruitment,ou=HR,dc=example,dc=com` to `ou=Recruitment,ou=Operations,dc=example,dc=com`
290
+
291
+ **Response (200):**
292
+
293
+ ```json
294
+ {
295
+ "newDn": "ou=Recruitment,ou=Operations,dc=example,dc=com"
296
+ }
297
+ ```
298
+
299
+ **Error Examples:**
300
+
301
+ - **Circular move (500):** `Cannot move organization into itself or its descendant`
302
+ - **Invalid target (500):** `Target ou=InvalidOU,dc=example,dc=com is not an organizational unit`
303
+ - **Same location (500):** `Organization is already in the target location`
304
+
305
+ ### Delete Organization
306
+
307
+ ```http
308
+ DELETE /api/v1/ldap/organizations/:dn
309
+ ```
310
+
311
+ **Path Parameter:**
312
+
313
+ - `dn`: Organization DN (URL-encoded)
314
+
315
+ **Notes:**
316
+
317
+ - Organization must be empty (no users, groups, or sub-organizations linked to it)
318
+ - Validation happens via hooks before deletion
319
+
320
+ **Response (200):**
321
+
322
+ ```json
323
+ {
324
+ "success": true
325
+ }
326
+ ```
327
+
328
+ **Error (500) - Non-empty:**
329
+
330
+ ```json
331
+ {
332
+ "error": "Organization ou=IT,dc=example,dc=com is not empty"
333
+ }
334
+ ```
335
+
336
+ ## Validation Rules
337
+
338
+ The plugin enforces several validation rules through hooks:
339
+
340
+ ### For Organizations
341
+
342
+ 1. **Path Validation**: The `twakeDepartmentPath` must:
343
+ - Start with the organization's own `ou` name
344
+ - Be followed by the path separator
345
+ - Reference an existing parent organization in the hierarchy
346
+ - Match the actual LDAP DN structure
347
+
348
+ 2. **Deletion Protection**: Organizations can only be deleted if:
349
+ - No users have `twakeDepartmentLink` pointing to it
350
+ - No groups have `twakeDepartmentLink` pointing to it
351
+ - No sub-organizations exist under it
352
+
353
+ 3. **Path Immutability**: The `twakeDepartmentPath` attribute cannot be deleted
354
+
355
+ ### For Users and Groups
356
+
357
+ 1. **Link Validation**: The `twakeDepartmentLink` must:
358
+ - Point to an existing organization DN
359
+ - Be within the top organization branch
360
+ - Not be deleted (link is mandatory)
361
+
362
+ 2. **Path Validation**: The `twakeDepartmentPath` must:
363
+ - Match an existing organizational hierarchy
364
+ - Not be deleted (path is mandatory)
365
+
366
+ ## Hooks
367
+
368
+ The plugin emits and listens to lifecycle hooks:
369
+
370
+ ### Listened Hooks
371
+
372
+ - `ldapaddrequest` - Validates organization link and path before creating any entry
373
+ - `ldapmodifyrequest` - Validates organization link and path modifications
374
+ - `ldapdeleterequest` - Ensures organizations are empty before deletion
375
+ - `ldaprenamerequest` - Passes through rename requests
376
+
377
+ **Hook Behavior:**
378
+
379
+ ```javascript
380
+ // Before adding a user
381
+ hooks: {
382
+ ldapaddrequest: async ([dn, entry]) => {
383
+ // If entry is a user/group (not an organization),
384
+ // validate twakeDepartmentLink points to existing org
385
+ if (!isOrganization(entry)) {
386
+ await checkDeptLink(entry); // Validates link exists
387
+ }
388
+ // If entry is an organization, validate path
389
+ if (isOrganization(entry)) {
390
+ await checkDeptPath(entry); // Validates path matches hierarchy
391
+ }
392
+ return [dn, entry];
393
+ };
394
+ }
395
+ ```
396
+
397
+ ## Examples
398
+
399
+ ### Example 1: Create Top-Level Department
400
+
401
+ ```bash
402
+ curl -X POST http://localhost:8081/api/v1/ldap/organizations \
403
+ -H "Content-Type: application/json" \
404
+ -d '{
405
+ "ou": "HR",
406
+ "description": "Human Resources Department",
407
+ "twakeDepartmentPath": "HR / Government"
408
+ }'
409
+ ```
410
+
411
+ This creates: `ou=HR,dc=example,dc=com`
412
+
413
+ ### Example 2: Create Sub-Department
414
+
415
+ ```bash
416
+ curl -X POST http://localhost:8081/api/v1/ldap/organizations \
417
+ -H "Content-Type: application/json" \
418
+ -d '{
419
+ "ou": "Recruitment",
420
+ "parentDn": "ou=HR,dc=example,dc=com",
421
+ "description": "Recruitment Team",
422
+ "twakeDepartmentPath": "Recruitment / HR / Government"
423
+ }'
424
+ ```
425
+
426
+ This creates: `ou=Recruitment,ou=HR,dc=example,dc=com`
427
+
428
+ ### Example 3: Get Organization Hierarchy
429
+
430
+ ```bash
431
+ # Get top organization
432
+ curl "http://localhost:8081/api/v1/ldap/organizations/top"
433
+
434
+ # Get specific organization
435
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DHR%2Co%3Dgov%2Cc%3Dmu"
436
+
437
+ # Get all users/groups/sub-OUs in HR department
438
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DHR%2Co%3Dgov%2Cc%3Dmu/subnodes"
439
+
440
+ # Get only users in HR department
441
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DHR%2Co%3Dgov%2Cc%3Dmu/subnodes?objectClass=twakeAccount"
442
+ ```
443
+
444
+ ### Example 4: Update Organization Description
445
+
446
+ ```bash
447
+ curl -X PUT "http://localhost:8081/api/v1/ldap/organizations/ou%3DHR%2Co%3Dgov%2Cc%3Dmu" \
448
+ -H "Content-Type: application/json" \
449
+ -d '{
450
+ "replace": {
451
+ "description": "Human Resources & Administration"
452
+ }
453
+ }'
454
+ ```
455
+
456
+ ### Example 5: Move Organization to Different Parent
457
+
458
+ ```bash
459
+ # Move Recruitment from HR to Operations department
460
+ curl -X POST "http://localhost:8081/api/v1/ldap/organizations/ou%3DRecruitment%2Cou%3DHR%2Co%3Dgov%2Cc%3Dmu/move" \
461
+ -H "Content-Type: application/json" \
462
+ -d '{
463
+ "targetOrgDn": "ou=Operations,dc=example,dc=com"
464
+ }'
465
+ ```
466
+
467
+ This changes the DN from `ou=Recruitment,ou=HR,dc=example,dc=com` to `ou=Recruitment,ou=Operations,dc=example,dc=com`.
468
+
469
+ All users, groups, and sub-organizations linked to Recruitment will automatically move with it.
470
+
471
+ ### Example 6: Delete Empty Organization
472
+
473
+ ```bash
474
+ # First verify organization is empty
475
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DRecruitment%2Cou%3DOperations%2Co%3Dgov%2Cc%3Dmu/subnodes"
476
+
477
+ # If empty, delete it
478
+ curl -X DELETE "http://localhost:8081/api/v1/ldap/organizations/ou%3DRecruitment%2Cou%3DOperations%2Co%3Dgov%2Cc%3Dmu"
479
+ ```
480
+
481
+ ## Integration with Other Plugins
482
+
483
+ ### With Users Plugin (via ldapFlat)
484
+
485
+ When a user is created with organization attributes:
486
+
487
+ ```bash
488
+ curl -X POST http://localhost:8081/api/v1/ldap/users \
489
+ -H "Content-Type: application/json" \
490
+ -d '{
491
+ "uid": "john.doe",
492
+ "cn": "John Doe",
493
+ "sn": "Doe",
494
+ "mail": "john.doe@example.com",
495
+ "twakeDepartmentLink": "ou=IT,dc=example,dc=com",
496
+ "twakeDepartmentPath": "IT / Government"
497
+ }'
498
+ ```
499
+
500
+ The organizations plugin automatically validates:
501
+
502
+ - `twakeDepartmentLink` points to existing `ou=IT,dc=example,dc=com`
503
+ - `twakeDepartmentPath` matches the organizational hierarchy
504
+
505
+ ### With Groups Plugin
506
+
507
+ Same validation applies when creating groups:
508
+
509
+ ```bash
510
+ curl -X POST http://localhost:8081/api/v1/ldap/groups \
511
+ -H "Content-Type: application/json" \
512
+ -d '{
513
+ "cn": "it-admins",
514
+ "description": "IT Administrators",
515
+ "twakeDepartmentLink": "ou=IT,dc=example,dc=com",
516
+ "twakeDepartmentPath": "IT / Government",
517
+ "member": ["uid=john.doe,ou=users,dc=example,dc=com"]
518
+ }'
519
+ ```
520
+
521
+ ### Organizational Cleanup
522
+
523
+ When deleting an organization, the plugin ensures it's empty:
524
+
525
+ ```bash
526
+ # This will fail if any users/groups reference the organization
527
+ DELETE /api/v1/ldap/organizations/ou=IT,dc=example,dc=com
528
+ # Error: Organization ou=IT,dc=example,dc=com is not empty
529
+ ```
530
+
531
+ You must first:
532
+
533
+ 1. Move or delete all users with `twakeDepartmentLink` to this org
534
+ 2. Move or delete all groups with `twakeDepartmentLink` to this org
535
+ 3. Delete all sub-organizations
536
+
537
+ ## Path Validation Details
538
+
539
+ ### Path Format
540
+
541
+ The path attribute follows this pattern:
542
+
543
+ ```
544
+ {current_ou} / {parent_ou} / {grandparent_ou} / ... / {top_org}
545
+ ```
546
+
547
+ ### Validation Process
548
+
549
+ 1. **Extract Components**: Split path by separator
550
+ 2. **Verify First Component**: Must match organization's own `ou`
551
+ 3. **Validate Parent Path**: Search for parent organization with matching path
552
+ 4. **Verify Hierarchy**: Ensure path matches actual LDAP DN structure
553
+
554
+ ### Example Path Validation
555
+
556
+ For organization: `ou=Recruitment,ou=HR,dc=example,dc=com`
557
+
558
+ Valid path: `Recruitment / HR / Government`
559
+
560
+ - `Recruitment` matches current ou
561
+ - `HR / Government` must exist as path of `ou=HR,dc=example,dc=com`
562
+
563
+ Invalid path: `Recruitment / IT / Government`
564
+
565
+ - `IT / Government` doesn't match parent's actual path
566
+
567
+ ## Troubleshooting
568
+
569
+ ### Invalid Organization Link
570
+
571
+ **Problem:** `Organization ou=IT,dc=example,dc=com does not exist`
572
+
573
+ **Solution:** Ensure the organization exists before creating users/groups that reference it:
574
+
575
+ ```bash
576
+ # Create organization first
577
+ curl -X POST http://localhost:8081/api/v1/ldap/organizations \
578
+ -H "Content-Type: application/json" \
579
+ -d '{"ou": "IT", "twakeDepartmentPath": "IT / Government"}'
580
+
581
+ # Then create user with link
582
+ curl -X POST http://localhost:8081/api/v1/ldap/users \
583
+ -d '{"uid": "user", "twakeDepartmentLink": "ou=IT,dc=example,dc=com", ...}'
584
+ ```
585
+
586
+ ### Invalid Organization Path
587
+
588
+ **Problem:** `Invalid organization path: IT / Recruitment / Government`
589
+
590
+ **Solutions:**
591
+
592
+ 1. Ensure parent path exists and matches LDAP hierarchy
593
+ 2. Verify separator matches configured separator (default: `" / "`)
594
+ 3. Check that path starts with organization's own `ou` name
595
+
596
+ ### Cannot Delete Organization
597
+
598
+ **Problem:** `Organization ou=IT,dc=example,dc=com is not empty`
599
+
600
+ **Solutions:**
601
+
602
+ 1. List subnodes to see what's linked:
603
+ ```bash
604
+ curl "http://localhost:8081/api/v1/ldap/organizations/ou%3DIT%2Co%3Dgov%2Cc%3Dmu/subnodes"
605
+ ```
606
+ 2. Remove or reassign all users/groups referencing this organization
607
+ 3. Delete all sub-organizations first (bottom-up approach)
608
+
609
+ ### Cannot Delete Path Attribute
610
+
611
+ **Problem:** `An organization path cannot be deleted`
612
+
613
+ **Solution:** The path attribute is required and cannot be deleted. To change it, use `replace` instead:
614
+
615
+ ```bash
616
+ curl -X PUT "http://localhost:8081/api/v1/ldap/organizations/ou%3DIT%2Co%3Dgov%2Cc%3Dmu" \
617
+ -d '{
618
+ "replace": {
619
+ "twakeDepartmentPath": "IT / NewParent / Government"
620
+ }
621
+ }'
622
+ ```
623
+
624
+ ## Schema Support
625
+
626
+ The plugin validates organizations against configured object classes. Example schema:
627
+
628
+ ```json
629
+ {
630
+ "strict": true,
631
+ "attributes": {
632
+ "objectClass": {
633
+ "type": "array",
634
+ "default": ["top", "organizationalUnit", "twakeDepartment"],
635
+ "required": true
636
+ },
637
+ "ou": {
638
+ "type": "string",
639
+ "test": "^[a-zA-Z0-9._-]{1,255}$",
640
+ "required": true
641
+ },
642
+ "twakeDepartmentPath": {
643
+ "type": "string",
644
+ "test": "^[\\w\\s/,]+$",
645
+ "required": true
646
+ },
647
+ "description": {
648
+ "type": "string",
649
+ "required": false
650
+ }
651
+ }
652
+ }
653
+ ```
654
+
655
+ ## See Also
656
+
657
+ - [LDAP Flat Plugin](./ldapFlat.md) - For managing flat LDAP entities (users, positions, nomenclature) through schema-driven approach
658
+ - [LDAP Groups Plugin](./ldapGroups.md) - For managing groups with members, automatic validation and cleanup
659
+ - [Schema Examples](../static/schemas/) - Organization schema examples for Twake, Standard, and Active Directory