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,412 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>LDAP User Editor Demo</title>
7
+
8
+ <!-- Google Fonts -->
9
+ <link
10
+ href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
11
+ rel="stylesheet"
12
+ />
13
+ <link
14
+ href="https://fonts.googleapis.com/icon?family=Material+Icons"
15
+ rel="stylesheet"
16
+ />
17
+
18
+ <!-- Shared CSS -->
19
+ <link rel="stylesheet" href="/static/browser/common-demo.css" />
20
+
21
+ <!-- Library CSS -->
22
+ <link rel="stylesheet" href="/static/browser/ldap-user-editor.css" />
23
+
24
+ <style>
25
+ :root {
26
+ --primary-color: #6200ee;
27
+ --primary-color-dark: #4a00b8;
28
+ }
29
+
30
+ body {
31
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
32
+ }
33
+
34
+ .demo-header h1 {
35
+ color: #6200ee;
36
+ }
37
+
38
+ .action-button {
39
+ background: var(--primary-color);
40
+ }
41
+
42
+ .action-button:hover {
43
+ background: var(--primary-color-dark);
44
+ }
45
+ </style>
46
+ </head>
47
+ <body>
48
+ <div class="demo-container">
49
+ <div class="demo-header">
50
+ <h1>✏️ LDAP User Editor</h1>
51
+ <p>Browse and edit LDAP users with schema-driven forms</p>
52
+ <div class="action-buttons">
53
+ <button class="action-button" id="create-user-btn" disabled>
54
+ <span class="material-icons">person_add</span>
55
+ Create User
56
+ </button>
57
+ </div>
58
+ </div>
59
+
60
+ <div id="status-container"></div>
61
+
62
+ <div id="ldap-user-editor"></div>
63
+ </div>
64
+
65
+ <!-- Create User Modal -->
66
+ <div class="modal-overlay" id="create-user-modal">
67
+ <div class="modal">
68
+ <div class="modal-header">
69
+ <h2>Create New User</h2>
70
+ <button class="close-button" id="close-modal-btn">
71
+ <span class="material-icons">close</span>
72
+ </button>
73
+ </div>
74
+ <form id="create-user-form">
75
+ <div id="form-fields"></div>
76
+ <div class="modal-footer">
77
+ <button type="button" class="secondary" id="cancel-btn">
78
+ Cancel
79
+ </button>
80
+ <button type="submit" class="primary">Create User</button>
81
+ </div>
82
+ </form>
83
+ </div>
84
+ </div>
85
+
86
+ <!-- Shared utilities -->
87
+ <script src="/static/browser/shared.js"></script>
88
+ <!-- Library JS -->
89
+ <script src="/static/browser/ldap-user-editor.js"></script>
90
+
91
+ <script>
92
+ const { LdapUserEditor } = window.LdapUserEditor;
93
+ const {
94
+ escapeHtml,
95
+ showStatus,
96
+ generateFormField,
97
+ processFormData,
98
+ loadPointerOptions,
99
+ replaceSchemaPlaceholders,
100
+ getOrganizationPath,
101
+ } = window.MiniDmShared;
102
+
103
+ let editor;
104
+ let userSchema;
105
+
106
+ async function generateCreateUserForm() {
107
+ const config = editor.getConfig();
108
+ if (!config || !config.features?.ldapFlatGeneric?.flatResources) {
109
+ throw new Error('Configuration not loaded');
110
+ }
111
+
112
+ // Get selected organization
113
+ const currentOrgDn = editor.getCurrentOrgDn();
114
+ if (!currentOrgDn) {
115
+ throw new Error('No organization selected');
116
+ }
117
+
118
+ // Find users resource
119
+ const usersResource =
120
+ config.features.ldapFlatGeneric.flatResources.find(
121
+ r => r.pluralName === 'users' || r.name === 'users'
122
+ );
123
+
124
+ if (!usersResource) {
125
+ throw new Error('Users resource not found in configuration');
126
+ }
127
+
128
+ // Load schema
129
+ if (usersResource.schemaUrl) {
130
+ const response = await fetch(usersResource.schemaUrl);
131
+ if (!response.ok) throw new Error('Failed to load schema');
132
+ userSchema = await response.json();
133
+ } else if (usersResource.schema) {
134
+ userSchema = usersResource.schema;
135
+ } else {
136
+ throw new Error('No schema available for users');
137
+ }
138
+
139
+ // Get organization path for twakeDepartmentPath
140
+ const orgPath = await getOrganizationPath(
141
+ currentOrgDn,
142
+ window.location.origin
143
+ );
144
+
145
+ // Replace placeholders in schema branches
146
+ const ldapBase = editor.getConfig().ldapBase;
147
+ userSchema = replaceSchemaPlaceholders(userSchema, {
148
+ __LDAP_BASE__: ldapBase,
149
+ __ldap_base__: ldapBase,
150
+ });
151
+
152
+ // Generate form fields from schema
153
+ const formFields = document.getElementById('form-fields');
154
+ let fieldsHtml = '';
155
+
156
+ // Add objectClass as hidden field
157
+ const objectClasses = userSchema.entity.objectClass || [];
158
+ fieldsHtml += objectClasses
159
+ .map(oc => `<input type="hidden" name="objectClass" value="${oc}" />`)
160
+ .join('');
161
+
162
+ // API loader for pointer options
163
+ const pointerLoader = async branch => {
164
+ const api = editor.getApi();
165
+ return await api.getPointerOptions(branch);
166
+ };
167
+
168
+ // Generate fields for all non-fixed attributes
169
+ for (const [fieldName, attribute] of Object.entries(
170
+ userSchema.attributes
171
+ )) {
172
+ if (attribute.fixed) continue; // Skip fixed fields like 'dn'
173
+ if (fieldName === 'objectClass') continue; // Already handled
174
+
175
+ // Auto-fill twakeDepartmentLink and twakeDepartmentPath
176
+ if (fieldName === 'twakeDepartmentLink') {
177
+ fieldsHtml += `
178
+ <input type="hidden" name="twakeDepartmentLink" value="${escapeHtml(currentOrgDn)}" />
179
+ `;
180
+ continue;
181
+ }
182
+
183
+ if (fieldName === 'twakeDepartmentPath') {
184
+ fieldsHtml += `
185
+ <input type="hidden" name="twakeDepartmentPath" value="${escapeHtml(orgPath)}" />
186
+ `;
187
+ continue;
188
+ }
189
+
190
+ fieldsHtml += await generateFormField(fieldName, attribute, {
191
+ pointerOptionsLoader: pointerLoader,
192
+ });
193
+ }
194
+
195
+ formFields.innerHTML = fieldsHtml;
196
+
197
+ // Attach handlers for pointer array fields
198
+ attachPointerArrayHandlers();
199
+ }
200
+
201
+ function attachPointerArrayHandlers() {
202
+ const modal = document.getElementById('create-user-modal');
203
+ const api = editor.getApi();
204
+
205
+ // Add button handlers for pointer arrays
206
+ modal.querySelectorAll('.add-pointer-item').forEach(btn => {
207
+ btn.addEventListener('click', async () => {
208
+ const fieldName = btn.getAttribute('data-field');
209
+ const container = btn.closest('.pointer-array-field');
210
+ const branch = container.getAttribute('data-branch');
211
+
212
+ if (!branch) return;
213
+
214
+ // Load options using shared utility
215
+ const options = await loadPointerOptions(branch, async b => {
216
+ return await api.getPointerOptions(b);
217
+ });
218
+
219
+ // Create new select element
220
+ const itemHtml = `
221
+ <div class="array-item" style="display: flex; gap: 8px; margin-bottom: 8px;">
222
+ <select class="form-select pointer-array-select" data-field="${escapeHtml(fieldName)}" style="flex: 1;">
223
+ <option value="">Select...</option>
224
+ ${options
225
+ .map(
226
+ opt => `
227
+ <option value="${escapeHtml(opt.dn)}">${escapeHtml(opt.label)}</option>
228
+ `
229
+ )
230
+ .join('')}
231
+ </select>
232
+ <button type="button" class="btn btn-secondary btn-icon remove-pointer-item" style="padding: 8px;">
233
+ <span class="material-icons">remove</span>
234
+ </button>
235
+ </div>
236
+ `;
237
+
238
+ // Insert before the add button (XSS-safe: all user data escaped via escapeHtml)
239
+ btn.insertAdjacentHTML('beforebegin', itemHtml);
240
+
241
+ // Reattach handlers
242
+ attachPointerArrayHandlers();
243
+ });
244
+ });
245
+
246
+ // Remove button handlers
247
+ modal.querySelectorAll('.remove-pointer-item').forEach(btn => {
248
+ btn.addEventListener('click', () => {
249
+ btn.closest('.array-item').remove();
250
+ });
251
+ });
252
+ }
253
+
254
+ function openCreateUserModal() {
255
+ const modal = document.getElementById('create-user-modal');
256
+ generateCreateUserForm()
257
+ .then(() => {
258
+ modal.classList.add('active');
259
+ })
260
+ .catch(error => {
261
+ console.error('Failed to generate form:', error);
262
+ showStatus('status-container', `Error: ${error.message}`, 'error');
263
+ });
264
+ }
265
+
266
+ function closeCreateUserModal() {
267
+ const modal = document.getElementById('create-user-modal');
268
+ modal.classList.remove('active');
269
+ document.getElementById('create-user-form').reset();
270
+ }
271
+
272
+ async function handleCreateUser(event) {
273
+ event.preventDefault();
274
+
275
+ const form = event.target;
276
+ const formData = new FormData(form);
277
+
278
+ // Process pointer array fields (manually collect from selects)
279
+ const modal = document.getElementById('create-user-modal');
280
+ modal.querySelectorAll('.pointer-array-field').forEach(container => {
281
+ const fieldName = container.getAttribute('data-field');
282
+ const selects = container.querySelectorAll('.pointer-array-select');
283
+ const values = Array.from(selects)
284
+ .map(select => select.value)
285
+ .filter(val => val); // Remove empty values
286
+
287
+ if (values.length > 0) {
288
+ // Add all values to formData
289
+ values.forEach(val => formData.append(fieldName, val));
290
+ }
291
+ });
292
+
293
+ // Use shared utility to process form data
294
+ const userData = processFormData(formData, userSchema.attributes);
295
+
296
+ console.log('Creating user with data:', userData);
297
+
298
+ try {
299
+ await editor.createUser(userData);
300
+ showStatus(
301
+ 'status-container',
302
+ 'User created successfully!',
303
+ 'success'
304
+ );
305
+ closeCreateUserModal();
306
+ } catch (error) {
307
+ console.error('Failed to create user:', error);
308
+ const errorMessage = error.message || error.toString();
309
+ showStatus('status-container', `Error: ${errorMessage}`, 'error');
310
+ }
311
+ }
312
+
313
+ async function handleDeleteUser() {
314
+ const userDn = editor.getCurrentUserDn();
315
+ if (!userDn) {
316
+ showStatus('status-container', 'No user selected', 'error');
317
+ return;
318
+ }
319
+
320
+ if (
321
+ !confirm(`Are you sure you want to delete this user?\n\n${userDn}`)
322
+ ) {
323
+ return;
324
+ }
325
+
326
+ try {
327
+ await editor.deleteUser(userDn);
328
+ showStatus(
329
+ 'status-container',
330
+ 'User deleted successfully!',
331
+ 'success'
332
+ );
333
+
334
+ // Disable delete button
335
+ document.getElementById('delete-user-btn').disabled = true;
336
+ } catch (error) {
337
+ console.error('Failed to delete user:', error);
338
+ showStatus('status-container', `Error: ${error.message}`, 'error');
339
+ }
340
+ }
341
+
342
+ async function initEditor() {
343
+ try {
344
+ editor = new LdapUserEditor({
345
+ containerId: 'ldap-user-editor',
346
+ apiBaseUrl: window.location.origin,
347
+ onUserSaved: userDn => {
348
+ console.log('User saved:', userDn);
349
+ showStatus(
350
+ 'status-container',
351
+ 'User saved successfully!',
352
+ 'success'
353
+ );
354
+ },
355
+ onError: error => {
356
+ console.error('Editor error:', error);
357
+ showStatus(
358
+ 'status-container',
359
+ `Error: ${error.message}`,
360
+ 'error'
361
+ );
362
+ },
363
+ });
364
+
365
+ await editor.init();
366
+ showStatus(
367
+ 'status-container',
368
+ 'LDAP User Editor loaded successfully!',
369
+ 'success'
370
+ );
371
+
372
+ // Enable/disable buttons based on selection
373
+ setInterval(() => {
374
+ const createBtn = document.getElementById('create-user-btn');
375
+ const currentOrgDn = editor.getCurrentOrgDn();
376
+
377
+ createBtn.disabled = !currentOrgDn;
378
+ }, 500);
379
+ } catch (error) {
380
+ console.error('Failed to initialize editor:', error);
381
+ showStatus('status-container', `Error: ${error.message}`, 'error');
382
+ }
383
+ }
384
+
385
+ // Event listeners
386
+ document
387
+ .getElementById('create-user-btn')
388
+ .addEventListener('click', openCreateUserModal);
389
+ document
390
+ .getElementById('close-modal-btn')
391
+ .addEventListener('click', closeCreateUserModal);
392
+ document
393
+ .getElementById('cancel-btn')
394
+ .addEventListener('click', closeCreateUserModal);
395
+ document
396
+ .getElementById('create-user-form')
397
+ .addEventListener('submit', handleCreateUser);
398
+
399
+ // Close modal when clicking outside
400
+ document
401
+ .getElementById('create-user-modal')
402
+ .addEventListener('click', e => {
403
+ if (e.target.id === 'create-user-modal') {
404
+ closeCreateUserModal();
405
+ }
406
+ });
407
+
408
+ // Initialize on load
409
+ initEditor();
410
+ </script>
411
+ </body>
412
+ </html>