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,661 @@
1
+ # Twake James Mail Server Plugin
2
+
3
+ Synchronize LDAP user changes with Apache James mail server via WebAdmin API.
4
+
5
+ ## Overview
6
+
7
+ The `twake/james` plugin automatically synchronizes email address and quota changes from LDAP to [Apache James](https://james.apache.org/) mail server. It listens to `onChange` hooks and updates James via its WebAdmin REST API.
8
+
9
+ ## Prerequisites
10
+
11
+ 1. **Apache James** mail server with WebAdmin API enabled
12
+ 2. **onChange plugin** loaded to detect LDAP changes
13
+ 3. **Mail and quota attributes** configured in LDAP schema
14
+
15
+ ## Configuration
16
+
17
+ ```bash
18
+ --plugin core/ldap/onChange \
19
+ --plugin core/ldap/flatGeneric \
20
+ --plugin twake/james \
21
+ --ldap-flat-schema ./static/schemas/twake/users.json \
22
+ --mail-attribute mail \
23
+ --quota-attribute mailQuota \
24
+ --james-webadmin-url http://james:8000 \
25
+ --james-webadmin-token "your-admin-token"
26
+ ```
27
+
28
+ **Environment Variables:**
29
+
30
+ ```bash
31
+ DM_JAMES_WEBADMIN_URL="http://james:8000"
32
+ DM_JAMES_WEBADMIN_TOKEN="your-admin-token"
33
+ ```
34
+
35
+ ### Parameters
36
+
37
+ - `--james-webadmin-url`: James WebAdmin API base URL (required)
38
+ - `--james-webadmin-token`: Bearer token for James WebAdmin authentication (optional)
39
+ - `--mail-attribute`: LDAP attribute for email (default: `mail`)
40
+ - `--quota-attribute`: LDAP attribute for quota (default: `mailQuota`)
41
+ - `--alias-attribute`: LDAP attribute for email aliases (default: `mailAlternateAddress`)
42
+ - `--james-mailbox-type-attribute`: LDAP attribute for mailbox type (default: `twakeMailboxType`)
43
+
44
+ ## How It Works
45
+
46
+ ### Mailing Lists
47
+
48
+ When a group with a `mail` attribute is created or modified:
49
+
50
+ 1. **Create mailing list**
51
+
52
+ ```bash
53
+ POST /api/v1/ldap/groups
54
+ {
55
+ "cn": "engineering",
56
+ "mail": "engineering@company.com",
57
+ "member": [
58
+ "uid=alice,ou=users,dc=example,dc=com",
59
+ "uid=bob,ou=users,dc=example,dc=com"
60
+ ]
61
+ }
62
+ ```
63
+
64
+ 2. **James plugin** creates address group and adds all members:
65
+
66
+ ```http
67
+ PUT /address/groups/engineering@company.com/alice@company.com
68
+ PUT /address/groups/engineering@company.com/bob@company.com
69
+ ```
70
+
71
+ 3. **Add/remove members** - when group members change:
72
+
73
+ ```bash
74
+ POST /api/v1/ldap/groups/engineering/members
75
+ {"member": "uid=charlie,ou=users,dc=example,dc=com"}
76
+ ```
77
+
78
+ James plugin automatically syncs:
79
+
80
+ ```http
81
+ PUT /address/groups/engineering@company.com/charlie@company.com
82
+ ```
83
+
84
+ 4. **Delete mailing list** - when group is deleted:
85
+
86
+ ```http
87
+ DELETE /address/groups/engineering@company.com
88
+ ```
89
+
90
+ **Notes:**
91
+
92
+ - Only groups with a `mail` attribute are synchronized to James
93
+ - Groups without `mail` are ignored (regular LDAP groups)
94
+ - James Address Groups are simple distribution lists
95
+ - All group members receive emails sent to the group address
96
+ - List type attributes (open/restricted) are stored in LDAP but not enforced by James
97
+
98
+ ### Mail Address Changes
99
+
100
+ When a user's mail attribute changes:
101
+
102
+ 1. **LDAP modify operation**
103
+
104
+ ```bash
105
+ PUT /api/v1/ldap/users/jdoe
106
+ {
107
+ "replace": {
108
+ "mail": "john.doe@company.com"
109
+ }
110
+ }
111
+ ```
112
+
113
+ 2. **onChange plugin** detects mail change and triggers `onLdapMailChange` hook
114
+
115
+ 3. **James plugin** receives hook and calls James WebAdmin API:
116
+
117
+ ```http
118
+ POST /users/old@company.com/rename/john.doe@company.com?action=rename
119
+ ```
120
+
121
+ 4. **James** renames the mail account and all associated data
122
+
123
+ ### Quota Changes
124
+
125
+ When a user's quota changes:
126
+
127
+ 1. **LDAP modify operation**
128
+
129
+ ```bash
130
+ PUT /api/v1/ldap/users/jdoe
131
+ {
132
+ "replace": {
133
+ "mailQuota": "5000000000"
134
+ }
135
+ }
136
+ ```
137
+
138
+ 2. **onChange plugin** triggers `onLdapQuotaChange` hook
139
+
140
+ 3. **James plugin** updates quota via WebAdmin API:
141
+
142
+ ```http
143
+ PUT /quota/users/jdoe@company.com/size
144
+ Content-Type: text/plain
145
+
146
+ 5000000000
147
+ ```
148
+
149
+ ### Email Aliases Management
150
+
151
+ The plugin automatically manages email aliases stored in LDAP and syncs them to James.
152
+
153
+ #### Creating a User with Aliases
154
+
155
+ When a user is created with aliases:
156
+
157
+ 1. **LDAP add operation**
158
+
159
+ ```bash
160
+ POST /api/v1/ldap/users
161
+ {
162
+ "uid": "jdoe",
163
+ "mail": "john.doe@company.com",
164
+ "mailAlternateAddress": [
165
+ "john@company.com",
166
+ "j.doe@company.com"
167
+ ]
168
+ }
169
+ ```
170
+
171
+ 2. **James plugin** creates all aliases in James:
172
+
173
+ ```http
174
+ PUT /address/aliases/john.doe@company.com/sources/john@company.com
175
+ PUT /address/aliases/john.doe@company.com/sources/j.doe@company.com
176
+ ```
177
+
178
+ Emails sent to any alias address will be delivered to `john.doe@company.com`.
179
+
180
+ #### Modifying Aliases
181
+
182
+ When aliases are added or removed:
183
+
184
+ 1. **LDAP modify operation**
185
+
186
+ ```bash
187
+ PUT /api/v1/ldap/users/jdoe
188
+ {
189
+ "replace": {
190
+ "mailAlternateAddress": [
191
+ "john@company.com",
192
+ "jdoe@company.com"
193
+ ]
194
+ }
195
+ }
196
+ ```
197
+
198
+ 2. **onChange plugin** detects alias changes and triggers `onLdapAliasChange` hook
199
+
200
+ 3. **James plugin** performs diff and updates only changed aliases:
201
+
202
+ ```http
203
+ DELETE /address/aliases/john.doe@company.com/sources/j.doe@company.com
204
+ PUT /address/aliases/john.doe@company.com/sources/jdoe@company.com
205
+ ```
206
+
207
+ #### Aliases and Mail Changes
208
+
209
+ When the primary email address changes, all aliases are automatically updated:
210
+
211
+ 1. **LDAP modify operation**
212
+
213
+ ```bash
214
+ PUT /api/v1/ldap/users/jdoe
215
+ {
216
+ "replace": {
217
+ "mail": "john.smith@company.com"
218
+ }
219
+ }
220
+ ```
221
+
222
+ 2. **James plugin** renames the account and updates alias destinations:
223
+
224
+ ```http
225
+ POST /users/john.doe@company.com/rename/john.smith@company.com?action=rename
226
+ DELETE /address/aliases/john.doe@company.com/sources/john@company.com
227
+ PUT /address/aliases/john.smith@company.com/sources/john@company.com
228
+ DELETE /address/aliases/john.doe@company.com/sources/jdoe@company.com
229
+ PUT /address/aliases/john.smith@company.com/sources/jdoe@company.com
230
+ ```
231
+
232
+ **Note:** James automatically creates an alias from the old address when renaming a user. The plugin attempts to create this alias explicitly, but handles the 409 Conflict response gracefully if it already exists.
233
+
234
+ #### Active Directory Format Support
235
+
236
+ The plugin supports Active Directory's `proxyAddresses` format:
237
+
238
+ ```ldap
239
+ proxyAddresses: smtp:john@company.com
240
+ proxyAddresses: smtp:j.doe@company.com
241
+ proxyAddresses: SMTP:john.doe@company.com
242
+ ```
243
+
244
+ The `smtp:` prefix is automatically stripped. The capitalization (SMTP vs smtp) is ignored - only the email address after the colon is used.
245
+
246
+ ## James WebAdmin API
247
+
248
+ ### Endpoints Used
249
+
250
+ | Operation | Endpoint | Method |
251
+ | ------------------- | ------------------------------------------ | ------ |
252
+ | Rename account | `/users/{old}/rename/{new}?action=rename` | POST |
253
+ | Update quota | `/quota/users/{mail}/size` | PUT |
254
+ | Add delegation | `/users/{mail}/authorizedUsers/{delegate}` | PUT |
255
+ | Remove delegation | `/users/{mail}/authorizedUsers/{delegate}` | DELETE |
256
+ | Add alias | `/address/aliases/{mail}/sources/{alias}` | PUT |
257
+ | Remove alias | `/address/aliases/{mail}/sources/{alias}` | DELETE |
258
+ | Add group member | `/address/groups/{group}/{member}` | PUT |
259
+ | Remove group member | `/address/groups/{group}/{member}` | DELETE |
260
+ | Delete group | `/address/groups/{group}` | DELETE |
261
+
262
+ ### Authentication
263
+
264
+ James WebAdmin API can be secured with bearer token authentication:
265
+
266
+ ```bash
267
+ --james-webadmin-token "your-admin-token"
268
+ ```
269
+
270
+ The plugin automatically adds the `Authorization: Bearer {token}` header to all requests.
271
+
272
+ **Without token:**
273
+
274
+ ```http
275
+ POST /users/old@company.com/rename/new@company.com?action=rename
276
+ ```
277
+
278
+ **With token:**
279
+
280
+ ```http
281
+ POST /users/old@company.com/rename/new@company.com?action=rename
282
+ Authorization: Bearer your-admin-token
283
+ ```
284
+
285
+ **Note:** The `action=rename` query parameter is required by James WebAdmin API.
286
+
287
+ Alternative authentication methods (Basic Auth, JWT) can be configured via reverse proxy.
288
+
289
+ ## Examples
290
+
291
+ ### Example 1: Basic Setup (No Authentication)
292
+
293
+ ```bash
294
+ --plugin core/ldap/onChange \
295
+ --plugin core/ldap/flatGeneric \
296
+ --plugin twake/james \
297
+ --ldap-flat-schema ./schemas/twake/users.json \
298
+ --mail-attribute mail \
299
+ --james-webadmin-url http://localhost:8000
300
+ ```
301
+
302
+ ### Example 1b: With Bearer Token
303
+
304
+ ```bash
305
+ --plugin core/ldap/onChange \
306
+ --plugin core/ldap/flatGeneric \
307
+ --plugin twake/james \
308
+ --ldap-flat-schema ./schemas/twake/users.json \
309
+ --mail-attribute mail \
310
+ --james-webadmin-url http://james:8000 \
311
+ --james-webadmin-token "admin-secret-token"
312
+ ```
313
+
314
+ ### Example 2: With Quota Management
315
+
316
+ ```bash
317
+ --plugin core/ldap/onChange \
318
+ --plugin core/ldap/flatGeneric \
319
+ --plugin twake/james \
320
+ --ldap-flat-schema ./schemas/twake/users.json \
321
+ --mail-attribute mail \
322
+ --quota-attribute mailQuota \
323
+ --james-webadmin-url http://james:8000
324
+ ```
325
+
326
+ ### Example 3: Complete Twake Setup
327
+
328
+ ```bash
329
+ --plugin core/auth/token \
330
+ --plugin core/ldap/onChange \
331
+ --plugin core/ldap/flatGeneric \
332
+ --plugin core/ldap/groups \
333
+ --plugin core/ldap/organization \
334
+ --plugin twake/james \
335
+ --plugin core/static \
336
+ --ldap-flat-schema ./schemas/twake/users.json \
337
+ --ldap-flat-schema ./schemas/twake/positions.json \
338
+ --mail-attribute mail \
339
+ --quota-attribute mailQuota \
340
+ --james-webadmin-url http://james:8000 \
341
+ --james-webadmin-token "james-admin-token" \
342
+ --static-path ./static \
343
+ --auth-token "api-admin-token"
344
+ ```
345
+
346
+ ## Logging
347
+
348
+ The plugin logs all operations:
349
+
350
+ ### Successful Operations
351
+
352
+ ```json
353
+ {
354
+ "level": "info",
355
+ "message": "James operation succeeded",
356
+ "plugin": "james",
357
+ "event": "onLdapMailChange",
358
+ "url": "http://james:8000/users/old@company.com/rename/new@company.com",
359
+ "status": 204,
360
+ "oldmail": "old@company.com",
361
+ "newmail": "new@company.com"
362
+ }
363
+ ```
364
+
365
+ ### Failed Operations
366
+
367
+ ```json
368
+ {
369
+ "level": "error",
370
+ "message": "James operation failed",
371
+ "plugin": "james",
372
+ "event": "onLdapMailChange",
373
+ "url": "http://james:8000/users/old@company.com/rename/new@company.com",
374
+ "status": 404,
375
+ "error": "User not found",
376
+ "oldmail": "old@company.com",
377
+ "newmail": "new@company.com"
378
+ }
379
+ ```
380
+
381
+ ## Error Handling
382
+
383
+ ### Non-Existent User
384
+
385
+ If mail account doesn't exist in James:
386
+
387
+ ```json
388
+ {
389
+ "level": "warn",
390
+ "message": "James user not found (expected for new users)",
391
+ "status": 404
392
+ }
393
+ ```
394
+
395
+ This is normal for new users - create the account in James separately.
396
+
397
+ ### James Server Down
398
+
399
+ If James WebAdmin is unreachable:
400
+
401
+ ```json
402
+ {
403
+ "level": "error",
404
+ "message": "Failed to connect to James",
405
+ "error": "ECONNREFUSED"
406
+ }
407
+ ```
408
+
409
+ The LDAP operation succeeds, but James is not updated. Manual sync may be required.
410
+
411
+ ### Invalid Quota Value
412
+
413
+ If quota value is invalid:
414
+
415
+ ```json
416
+ {
417
+ "level": "error",
418
+ "message": "Invalid quota value",
419
+ "status": 400,
420
+ "error": "Quota must be a positive integer"
421
+ }
422
+ ```
423
+
424
+ ## Integration Testing
425
+
426
+ ### Test Mail Rename
427
+
428
+ ```bash
429
+ # Update mail in LDAP
430
+ curl -X PUT http://localhost:8081/api/v1/ldap/users/jdoe \
431
+ -H "Authorization: Bearer admin-token" \
432
+ -H "Content-Type: application/json" \
433
+ -d '{"replace": {"mail": "john.doe@company.com"}}'
434
+
435
+ # Verify in James
436
+ curl http://james:8000/users/john.doe@company.com
437
+ ```
438
+
439
+ ### Test Quota Update
440
+
441
+ ```bash
442
+ # Update quota in LDAP
443
+ curl -X PUT http://localhost:8081/api/v1/ldap/users/jdoe \
444
+ -H "Authorization: Bearer admin-token" \
445
+ -H "Content-Type: application/json" \
446
+ -d '{"replace": {"mailQuota": "5000000000"}}'
447
+
448
+ # Verify in James
449
+ curl http://james:8000/quota/users/jdoe@company.com/size
450
+ ```
451
+
452
+ ## Quota Format
453
+
454
+ Quota values are in **bytes**:
455
+
456
+ | Size | Bytes | Example |
457
+ | --------- | ----------- | ---------------------------- |
458
+ | 1 GB | 1000000000 | `"mailQuota": "1000000000"` |
459
+ | 5 GB | 5000000000 | `"mailQuota": "5000000000"` |
460
+ | 10 GB | 10000000000 | `"mailQuota": "10000000000"` |
461
+ | Unlimited | -1 | `"mailQuota": "-1"` |
462
+
463
+ ## Synchronization Scenarios
464
+
465
+ ### Scenario 1: User Creation
466
+
467
+ 1. Create user in LDAP with mail attribute
468
+ 2. James plugin does nothing (user doesn't exist in James yet)
469
+ 3. Create mail account in James manually or via provisioning script
470
+ 4. Future mail/quota changes are synced automatically
471
+
472
+ ### Scenario 2: Mail Address Change
473
+
474
+ 1. User changes email in LDAP: `old@company.com` → `new@company.com`
475
+ 2. James plugin renames account in James
476
+ 3. All mail data (inbox, sent, folders) is preserved
477
+ 4. Old address is no longer valid
478
+
479
+ ### Scenario 3: Quota Increase
480
+
481
+ 1. Admin increases user quota in LDAP: `1GB` → `5GB`
482
+ 2. James plugin updates quota in James
483
+ 3. User can now receive more email
484
+
485
+ ### Scenario 4: Quota Decrease
486
+
487
+ 1. Admin decreases user quota in LDAP: `5GB` → `1GB`
488
+ 2. James plugin updates quota in James
489
+ 3. If user is over new quota, James may block incoming mail
490
+ 4. User must delete mail to get under quota
491
+
492
+ ## Mailing List Examples
493
+
494
+ ### Creating a Mailing List
495
+
496
+ ```bash
497
+ # Create a group with mail attribute
498
+ curl -X POST http://localhost:8081/api/v1/ldap/groups \
499
+ -H "Authorization: Bearer admin-token" \
500
+ -H "Content-Type: application/json" \
501
+ -d '{
502
+ "cn": "engineering",
503
+ "mail": "engineering@company.com",
504
+ "member": [
505
+ "uid=alice,ou=users,dc=example,dc=com",
506
+ "uid=bob,ou=users,dc=example,dc=com"
507
+ ],
508
+ "twakeDepartmentLink": "ou=organization,dc=example,dc=com",
509
+ "twakeDepartmentPath": "Engineering"
510
+ }'
511
+ ```
512
+
513
+ The James plugin automatically creates the mailing list and adds all members.
514
+
515
+ ### Adding a Member
516
+
517
+ ```bash
518
+ # Add member to existing group
519
+ curl -X POST http://localhost:8081/api/v1/ldap/groups/engineering/members \
520
+ -H "Authorization: Bearer admin-token" \
521
+ -H "Content-Type: application/json" \
522
+ -d '{"member": "uid=charlie,ou=users,dc=example,dc=com"}'
523
+ ```
524
+
525
+ James is automatically updated to include charlie@company.com in the distribution list.
526
+
527
+ ### Removing a Member
528
+
529
+ ```bash
530
+ # Remove member from group
531
+ curl -X DELETE http://localhost:8081/api/v1/ldap/groups/engineering/members/uid=alice,ou=users,dc=example,dc=com \
532
+ -H "Authorization: Bearer admin-token"
533
+ ```
534
+
535
+ James removes alice@company.com from the mailing list.
536
+
537
+ ### Deleting a Mailing List
538
+
539
+ ```bash
540
+ # Delete the entire group
541
+ curl -X DELETE http://localhost:8081/api/v1/ldap/groups/engineering \
542
+ -H "Authorization: Bearer admin-token"
543
+ ```
544
+
545
+ James deletes the entire address group.
546
+
547
+ ## Limitations
548
+
549
+ 1. **One-way sync**: LDAP → James only. James changes don't sync back to LDAP.
550
+ 2. **No account creation**: Plugin doesn't create James accounts, only updates existing ones.
551
+ 3. **No user deletion**: Plugin doesn't delete James accounts when LDAP users are deleted.
552
+ 4. **Synchronous**: James API calls block LDAP response. Slow James = slow LDAP.
553
+ 5. **No send restrictions**: James doesn't enforce list type restrictions (open/member/owner-only). These are metadata in LDAP only.
554
+
555
+ ## Advanced Configuration
556
+
557
+ ### Custom James Attributes
558
+
559
+ Extend the plugin for custom James operations:
560
+
561
+ ```typescript
562
+ import James from './plugins/twake/james';
563
+
564
+ class CustomJames extends James {
565
+ hooks = {
566
+ ...super.hooks,
567
+ onLdapDepartmentChange: async (dn, oldDept, newDept) => {
568
+ // Custom logic for department changes
569
+ await this._try(
570
+ 'onLdapDepartmentChange',
571
+ `${this.config.james_webadmin_url}/users/${mail}/metadata/department`,
572
+ 'PUT',
573
+ dn,
574
+ newDept,
575
+ { oldDept, newDept }
576
+ );
577
+ },
578
+ };
579
+ }
580
+ ```
581
+
582
+ ### Async Operations
583
+
584
+ For high-latency James servers, consider async operations:
585
+
586
+ ```typescript
587
+ hooks: {
588
+ onLdapMailChange: async (dn, oldMail, newMail) => {
589
+ // Fire and forget - don't block LDAP response
590
+ setImmediate(async () => {
591
+ try {
592
+ await jamesClient.renameUser(oldMail, newMail);
593
+ } catch (err) {
594
+ logger.error('Failed to sync mail change', err);
595
+ }
596
+ });
597
+ };
598
+ }
599
+ ```
600
+
601
+ ## Troubleshooting
602
+
603
+ ### Problem: Changes Not Syncing
604
+
605
+ **Solutions:**
606
+
607
+ 1. Verify onChange plugin is loaded:
608
+
609
+ ```bash
610
+ --plugin core/ldap/onChange
611
+ ```
612
+
613
+ 2. Check mail/quota attributes configured:
614
+
615
+ ```bash
616
+ --mail-attribute mail
617
+ --quota-attribute mailQuota
618
+ ```
619
+
620
+ 3. Enable debug logging:
621
+
622
+ ```bash
623
+ --log-level debug
624
+ ```
625
+
626
+ 4. Verify James URL is correct:
627
+ ```bash
628
+ curl http://james:8000/healthcheck
629
+ ```
630
+
631
+ ### Problem: 404 Errors
632
+
633
+ **Symptoms:**
634
+
635
+ ```json
636
+ { "level": "warn", "message": "James user not found", "status": 404 }
637
+ ```
638
+
639
+ **Solutions:**
640
+
641
+ 1. Create mail account in James first
642
+ 2. Verify mail address matches between LDAP and James
643
+ 3. Check James logs for account existence
644
+
645
+ ### Problem: Slow LDAP Responses
646
+
647
+ **Symptoms:**
648
+ LDAP modify operations take several seconds.
649
+
650
+ **Solutions:**
651
+
652
+ 1. Check James WebAdmin performance
653
+ 2. Implement async operations (fire and forget)
654
+ 3. Use local James instance (avoid network latency)
655
+ 4. Add timeout to James API calls
656
+
657
+ ## See Also
658
+
659
+ - [onChange.md](onChange.md) - LDAP change detection
660
+ - [ldapFlatGeneric.md](ldapFlatGeneric.md) - Schema-driven LDAP management
661
+ - [Apache James Documentation](https://james.apache.org/server/manage-webadmin.html) - WebAdmin API reference