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,521 @@
1
+ # Authorization Plugin: authzLinid1
2
+
3
+ LDAP-based authorization plugin that grants permissions based on the `twakeLocalAdminLink` attribute in organizational units.
4
+
5
+ ## Overview
6
+
7
+ The `authzLinid1` plugin provides dynamic, LDAP-driven access control by reading permissions directly from LDAP organizational units. It supports:
8
+
9
+ - **LDAP-based permissions** - No configuration files needed, permissions stored in LDAP
10
+ - **Organization-centric** - Users listed in `twakeLocalAdminLink` manage the organization
11
+ - **Full CRUD rights** - Local admins get read, write, and delete permissions
12
+ - **Sub-branch inheritance** - Permissions apply recursively to sub-branches
13
+ - **Cross-branch access** - Users/groups can be managed if their `twakeDepartmentLink` points to an authorized organization
14
+ - **Permission caching** - Configurable TTL reduces LDAP queries (default: 5 minutes)
15
+
16
+ ## How It Works
17
+
18
+ ### twakeLocalAdminLink Attribute
19
+
20
+ Organizations in LDAP can have a `twakeLocalAdminLink` attribute listing user DNs who manage that organization:
21
+
22
+ ```ldif
23
+ dn: ou=HR,ou=organization,dc=example,dc=com
24
+ objectClass: organizationalUnit
25
+ ou: HR
26
+ twakeLocalAdminLink: uid=hr-admin,ou=users,dc=example,dc=com
27
+ twakeLocalAdminLink: uid=hr-manager,ou=users,dc=example,dc=com
28
+ ```
29
+
30
+ Users listed in `twakeLocalAdminLink` automatically get full permissions (read, write, delete) for:
31
+
32
+ - The organization itself (`ou=HR,ou=organization,dc=example,dc=com`)
33
+ - All sub-organizations (`ou=Payroll,ou=HR,ou=organization,dc=example,dc=com`)
34
+ - All users/groups with `twakeDepartmentLink` pointing to this organization
35
+
36
+ ### Cross-Branch Access
37
+
38
+ Users and groups can exist in different LDAP branches but belong to specific organizations via `twakeDepartmentLink`:
39
+
40
+ ```ldif
41
+ # User in global users branch
42
+ dn: uid=john,ou=users,dc=example,dc=com
43
+ objectClass: twakeAccount
44
+ uid: john
45
+ cn: John Doe
46
+ twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
47
+ ```
48
+
49
+ The HR admin (listed in `ou=HR`'s `twakeLocalAdminLink`) can manage John even though he's in `ou=users` because his `twakeDepartmentLink` points to the HR organization.
50
+
51
+ ## Configuration
52
+
53
+ No configuration file needed - permissions are read from LDAP. Simply load the plugin:
54
+
55
+ ```bash
56
+ --plugin core/auth/authzLinid1
57
+ ```
58
+
59
+ **Optional Cache Configuration:**
60
+
61
+ The plugin caches permissions for 5 minutes by default. This is hardcoded but can be modified in the source if needed.
62
+
63
+ ## Permission Resolution
64
+
65
+ For each LDAP operation, the plugin:
66
+
67
+ 1. **Resolves user DN** - Converts username to LDAP DN
68
+ 2. **Searches for permissions** - Finds all organizations where user is in `twakeLocalAdminLink`
69
+ 3. **Caches results** - Stores permissions for 5 minutes
70
+ 4. **Checks branch access** - Verifies if requested branch matches authorized organizations
71
+ 5. **Checks link attributes** - For entries with `twakeDepartmentLink`, checks if link points to authorized org
72
+
73
+ ### Permission Inheritance
74
+
75
+ Permissions apply to the organization and all descendants:
76
+
77
+ ```
78
+ ou=organization,dc=example,dc=com
79
+ ├── ou=Main Unit [admin1 has twakeLocalAdminLink here]
80
+ │ ├── ou=Sub Unit 1 [admin1 can access]
81
+ │ │ └── ou=Department1 [admin1 can access]
82
+ │ └── ou=Sub Unit 2 [admin1 can access]
83
+ └── ou=Private [admin1 cannot access]
84
+ ```
85
+
86
+ ### Cross-Branch Examples
87
+
88
+ **Scenario 1: User in authorized branch**
89
+
90
+ ```
91
+ Organization: ou=HR,ou=organization,dc=example,dc=com
92
+ twakeLocalAdminLink: uid=admin,ou=users,dc=example,dc=com
93
+
94
+ User: uid=john,ou=users,ou=HR,ou=organization,dc=example,dc=com
95
+
96
+ Result: admin can manage john (user is in HR branch)
97
+ ```
98
+
99
+ **Scenario 2: User with department link**
100
+
101
+ ```
102
+ Organization: ou=HR,ou=organization,dc=example,dc=com
103
+ twakeLocalAdminLink: uid=admin,ou=users,dc=example,dc=com
104
+
105
+ User: uid=john,ou=users,dc=example,dc=com
106
+ twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
107
+
108
+ Result: admin can manage john (twakeDepartmentLink points to HR)
109
+ ```
110
+
111
+ **Scenario 3: User without link in wrong branch**
112
+
113
+ ```
114
+ Organization: ou=HR,ou=organization,dc=example,dc=com
115
+ twakeLocalAdminLink: uid=admin,ou=users,dc=example,dc=com
116
+
117
+ User: uid=john,ou=users,dc=example,dc=com
118
+ (no twakeDepartmentLink)
119
+
120
+ Result: admin cannot manage john (not in HR branch, no link)
121
+ ```
122
+
123
+ ## Hooks
124
+
125
+ ### ldapaddrequest Hook
126
+
127
+ Intercepts all LDAP add operations:
128
+
129
+ 1. Checks if request has authenticated user
130
+ 2. Resolves user's DN from username
131
+ 3. Determines which branch to check:
132
+ - If entry has `twakeDepartmentLink`, use that organization
133
+ - Otherwise, use parent DN of the entry being added
134
+ 4. Verifies user has write permission for that branch
135
+ 5. Throws error if access denied
136
+
137
+ **Special allowances:**
138
+
139
+ - Unauthenticated requests pass through (for internal operations)
140
+
141
+ ### ldapsearchrequest Hook
142
+
143
+ Intercepts all LDAP search operations:
144
+
145
+ 1. Checks if request has authenticated user
146
+ 2. Resolves user's DN from username
147
+ 3. Allows base scope searches on top organization (for navigation)
148
+ 4. Allows searches for `twakeLocalAdminLink` (for permission refresh)
149
+ 5. Verifies user has read permission for search base
150
+ 6. Throws error if access denied
151
+
152
+ **Special allowances:**
153
+
154
+ - Base scope on `ldap_top_organization` (e.g., for getOrganisationTop API)
155
+ - Filters containing `twakeLocalAdminLink` (permission refresh queries)
156
+
157
+ ### getOrganisationTop Hook
158
+
159
+ Modifies the organization tree API:
160
+
161
+ 1. Returns organizations where user is local admin
162
+ 2. Replaces default top organization with authorized branches
163
+ 3. Enables UI to show only manageable organizations
164
+
165
+ **Behavior:**
166
+
167
+ - If user manages multiple orgs, returns the first one
168
+ - If user manages one org, returns that org
169
+ - If user manages no orgs, returns default top organization
170
+
171
+ ## API Integration
172
+
173
+ ### Organization Tree API
174
+
175
+ The plugin automatically filters the organization tree API:
176
+
177
+ **Global admin (manages top organization):**
178
+
179
+ ```
180
+ GET /api/v1/ldap/organizations/top
181
+ Authorization: Bearer <token>
182
+
183
+ Response:
184
+ {
185
+ "dn": "ou=organization,dc=example,dc=com",
186
+ "ou": "organization"
187
+ }
188
+ ```
189
+
190
+ **Local admin (manages specific organization):**
191
+
192
+ ```
193
+ GET /api/v1/ldap/organizations/top
194
+ Authorization: Bearer <token>
195
+
196
+ Response:
197
+ {
198
+ "dn": "ou=HR,ou=organization,dc=example,dc=com",
199
+ "ou": "HR"
200
+ }
201
+ ```
202
+
203
+ ### Add User Example
204
+
205
+ **Success - User with department link to authorized org:**
206
+
207
+ ```
208
+ POST /api/v1/users
209
+ Authorization: Bearer <hr-admin-token>
210
+
211
+ {
212
+ "uid": "newuser",
213
+ "cn": "New User",
214
+ "twakeDepartmentLink": ["ou=HR,ou=organization,dc=example,dc=com"]
215
+ }
216
+
217
+ Response: 201 Created
218
+ ```
219
+
220
+ **Failure - User with link to unauthorized org:**
221
+
222
+ ```
223
+ POST /api/v1/users
224
+ Authorization: Bearer <hr-admin-token>
225
+
226
+ {
227
+ "uid": "newuser",
228
+ "cn": "New User",
229
+ "twakeDepartmentLink": ["ou=IT,ou=organization,dc=example,dc=com"]
230
+ }
231
+
232
+ Response: 403 Forbidden
233
+ {
234
+ "error": "User hr-admin does not have write permission for branch ou=IT,ou=organization,dc=example,dc=com"
235
+ }
236
+ ```
237
+
238
+ ## Performance
239
+
240
+ ### Permission Caching
241
+
242
+ Permissions are cached to reduce LDAP queries:
243
+
244
+ - **Cache TTL**: 5 minutes (hardcoded)
245
+ - **Per-user cache**: Each user's permissions cached separately
246
+ - **Automatic refresh**: Cache expires after TTL
247
+ - **On-demand refresh**: New permissions fetched on cache miss
248
+
249
+ **Cache structure:**
250
+
251
+ ```javascript
252
+ {
253
+ "uid=admin,ou=users,dc=example,dc=com": {
254
+ branches: Map([
255
+ ["ou=HR,ou=organization,dc=example,dc=com", {read: true, write: true, delete: true}],
256
+ ["ou=Finance,ou=organization,dc=example,dc=com", {read: true, write: true, delete: true}]
257
+ ]),
258
+ timestamp: 1696512000000
259
+ }
260
+ }
261
+ ```
262
+
263
+ ### LDAP Query Optimization
264
+
265
+ The plugin minimizes LDAP queries:
266
+
267
+ 1. **User DN resolution** - Cached implicitly by permission cache
268
+ 2. **Permission search** - Single query for all organizations with user in `twakeLocalAdminLink`
269
+ 3. **No recursive searches** - Uses DN suffix matching for sub-branch checks
270
+
271
+ **Typical query pattern:**
272
+
273
+ ```
274
+ User makes request → Check cache → (if expired) Search LDAP once → Cache for 5 min
275
+ ```
276
+
277
+ ## LDAP Schema Requirements
278
+
279
+ ### Required Attributes
280
+
281
+ **Organizations:**
282
+
283
+ - `twakeLocalAdminLink` (multi-valued) - DNs of local administrators
284
+
285
+ **Users/Groups:**
286
+
287
+ - `twakeDepartmentLink` (single-valued) - DN of parent organization
288
+
289
+ ### Example Schema
290
+
291
+ ```ldif
292
+ # Organization with local admins
293
+ dn: ou=HR,ou=organization,dc=example,dc=com
294
+ objectClass: organizationalUnit
295
+ objectClass: twakeOrganization
296
+ ou: HR
297
+ twakeLocalAdminLink: uid=hr-admin,ou=users,dc=example,dc=com
298
+ twakeLocalAdminLink: uid=hr-manager,ou=users,dc=example,dc=com
299
+
300
+ # User with department link
301
+ dn: uid=employee1,ou=users,dc=example,dc=com
302
+ objectClass: inetOrgPerson
303
+ objectClass: twakeAccount
304
+ uid: employee1
305
+ cn: Employee One
306
+ twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
307
+
308
+ # Group with department link
309
+ dn: cn=hr-staff,ou=groups,dc=example,dc=com
310
+ objectClass: groupOfNames
311
+ objectClass: twakeGroup
312
+ cn: hr-staff
313
+ twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
314
+ member: uid=employee1,ou=users,dc=example,dc=com
315
+ ```
316
+
317
+ ## Security Considerations
318
+
319
+ ### LDAP-Driven Security
320
+
321
+ - **Centralized control** - All permissions in LDAP, no config files to sync
322
+ - **Audit trail** - LDAP modifications can be logged/audited
323
+ - **Consistency** - Single source of truth for permissions
324
+ - **Real-time updates** - Changes effective after cache expiry (5 min max)
325
+
326
+ ### Permission Model
327
+
328
+ - **Local admins get full access** - Read, write, and delete
329
+ - **No granular permissions** - Cannot grant read-only local admin
330
+ - **Inheritance always applies** - Cannot restrict sub-branches
331
+ - **Cross-branch by design** - Department links intentionally allow cross-branch access
332
+
333
+ ### Authentication Required
334
+
335
+ This plugin only handles **authorization**. Combine with an authentication plugin:
336
+
337
+ ```bash
338
+ --plugin core/auth/token \
339
+ --plugin core/auth/authzLinid1 \
340
+ --auth-token "secret-token"
341
+ ```
342
+
343
+ ### Cache Security
344
+
345
+ - **Cache delays permission revocation** - Up to 5 minutes after removing user from `twakeLocalAdminLink`
346
+ - **Cache per user** - Removing one user doesn't invalidate others
347
+ - **No cache persistence** - Cache cleared on server restart
348
+
349
+ ## Troubleshooting
350
+
351
+ ### Problem: Access Denied
352
+
353
+ **Symptoms:**
354
+
355
+ ```json
356
+ {
357
+ "error": "User jdoe does not have write permission for branch ou=HR,ou=organization,dc=example,dc=com"
358
+ }
359
+ ```
360
+
361
+ **Solutions:**
362
+
363
+ 1. Verify user is in organization's `twakeLocalAdminLink`:
364
+
365
+ ```bash
366
+ ldapsearch -x -b "ou=organization,dc=example,dc=com" "(twakeLocalAdminLink=uid=jdoe,*)"
367
+ ```
368
+
369
+ 2. Check user DN matches exactly (spaces, case, order)
370
+
371
+ 3. Wait up to 5 minutes for cache to expire after adding user
372
+
373
+ 4. Check user is authenticated (verify `req.user` is set)
374
+
375
+ ### Problem: Cannot Manage User in Different Branch
376
+
377
+ **Symptoms:**
378
+ User exists in `ou=users,dc=example,dc=com` but local admin cannot manage them.
379
+
380
+ **Solutions:**
381
+
382
+ 1. Add `twakeDepartmentLink` to user:
383
+
384
+ ```ldif
385
+ dn: uid=user,ou=users,dc=example,dc=com
386
+ changetype: modify
387
+ add: twakeDepartmentLink
388
+ twakeDepartmentLink: ou=HR,ou=organization,dc=example,dc=com
389
+ ```
390
+
391
+ 2. Or move user to organization branch:
392
+ ```
393
+ From: uid=user,ou=users,dc=example,dc=com
394
+ To: uid=user,ou=users,ou=HR,ou=organization,dc=example,dc=com
395
+ ```
396
+
397
+ ### Problem: Permissions Not Updating
398
+
399
+ **Symptoms:**
400
+ Added user to `twakeLocalAdminLink` but they still get access denied.
401
+
402
+ **Solutions:**
403
+
404
+ 1. Wait up to 5 minutes for cache to expire
405
+ 2. Restart server to clear all caches immediately
406
+ 3. Verify LDAP modification succeeded:
407
+ ```bash
408
+ ldapsearch -x -b "ou=HR,ou=organization,dc=example,dc=com" "(objectClass=*)" twakeLocalAdminLink
409
+ ```
410
+
411
+ ### Problem: User Not Found
412
+
413
+ **Symptoms:**
414
+
415
+ ```
416
+ User jdoe not found in LDAP
417
+ ```
418
+
419
+ **Solutions:**
420
+
421
+ 1. Verify user exists in LDAP:
422
+
423
+ ```bash
424
+ ldapsearch -x -b "dc=example,dc=com" "(uid=jdoe)"
425
+ ```
426
+
427
+ 2. Check `ldap_user_main_attribute` configuration (default: `uid`)
428
+
429
+ 3. Verify authentication plugin sets `req.user` correctly
430
+
431
+ ### Problem: Cannot Search Top Organization
432
+
433
+ **Symptoms:**
434
+
435
+ ```json
436
+ {
437
+ "error": "User admin does not have read permission for branch ou=organization,dc=example,dc=com"
438
+ }
439
+ ```
440
+
441
+ **Solutions:**
442
+
443
+ This is expected behavior - users can only see organizations they manage. To grant access to top organization:
444
+
445
+ ```bash
446
+ ldapsearch -x -b "ou=organization,dc=example,dc=com" -s base "(objectClass=*)"
447
+ # Modify to add user:
448
+ ldapmodify <<EOF
449
+ dn: ou=organization,dc=example,dc=com
450
+ changetype: modify
451
+ add: twakeLocalAdminLink
452
+ twakeLocalAdminLink: uid=admin,ou=users,dc=example,dc=com
453
+ EOF
454
+ ```
455
+
456
+ ## Integration Examples
457
+
458
+ ### With Token Authentication
459
+
460
+ ```bash
461
+ --plugin core/auth/token \
462
+ --plugin core/auth/authzLinid1 \
463
+ --auth-token "admin-token" \
464
+ --ldap-top-organization "ou=organization,dc=example,dc=com"
465
+ ```
466
+
467
+ ### With OpenID Connect
468
+
469
+ ```bash
470
+ --plugin core/auth/openidconnect \
471
+ --plugin core/auth/authzLinid1 \
472
+ --oidc-server "https://auth.example.com" \
473
+ --oidc-client-id "ldap-rest" \
474
+ --oidc-client-secret "secret" \
475
+ --base-url "https://api.example.com" \
476
+ --ldap-top-organization "ou=organization,dc=example,dc=com"
477
+ ```
478
+
479
+ ### With LemonLDAP::NG
480
+
481
+ ```bash
482
+ --plugin core/auth/llng \
483
+ --plugin core/auth/authzLinid1 \
484
+ --llng-ini /etc/lemonldap-ng/lemonldap-ng.ini \
485
+ --ldap-top-organization "ou=organization,dc=example,dc=com"
486
+ ```
487
+
488
+ ## Comparison with authzPerBranch
489
+
490
+ | Feature | authzLinid1 | authzPerBranch |
491
+ | ----------------- | ---------------------------------- | -------------------------------- |
492
+ | Configuration | LDAP-based | Config file/env |
493
+ | Permission source | `twakeLocalAdminLink` attribute | JSON configuration |
494
+ | Granularity | Organization-level | Per-branch, per-user/group |
495
+ | Read-only access | No (always full access) | Yes (separate read/write/delete) |
496
+ | Cross-branch | Yes (via `twakeDepartmentLink`) | Yes (if configured) |
497
+ | Dynamic updates | Yes (via LDAP) | No (requires restart) |
498
+ | Cache | 5 min (hardcoded) | Configurable TTL |
499
+ | Use case | Organization-based delegated admin | Fine-grained access control |
500
+
501
+ **When to use authzLinid1:**
502
+
503
+ - Organizations manage themselves
504
+ - LDAP is source of truth
505
+ - Full admin access is acceptable
506
+ - Department-based delegation
507
+
508
+ **When to use authzPerBranch:**
509
+
510
+ - Need read-only access
511
+ - Complex permission matrix
512
+ - Config-driven permissions
513
+ - Different rights per branch
514
+
515
+ ## See Also
516
+
517
+ - [authzPerBranch Plugin](authzPerBranch.md) - Configuration-based authorization
518
+ - [Authentication Plugins](authentication.md) - Setup authentication
519
+ - [LDAP Organizations](ldapOrganizations.md) - Organization tree management
520
+ - [LDAP Users](ldapFlatGeneric.md) - User management
521
+ - [LDAP Groups](ldapGroups.md) - Group management