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,596 @@
1
+ # Authorization Plugin: authzPerBranch
2
+
3
+ Branch-level authorization plugin that restricts LDAP access based on user and group permissions.
4
+
5
+ ## Overview
6
+
7
+ The `authzPerBranch` plugin provides fine-grained access control by restricting which LDAP branches users can access. It supports:
8
+
9
+ - **Default permissions** - Applied when no specific rules match
10
+ - **User-based permissions** - Per-user branch access rules
11
+ - **Group-based permissions** - Permissions inherited from group memberships
12
+ - **Separate rights** - Read, write, and delete permissions
13
+ - **Sub-branch inheritance** - Permissions apply recursively to sub-branches
14
+ - **Group caching** - Configurable TTL for group membership resolution
15
+
16
+ ## Configuration
17
+
18
+ ```bash
19
+ --plugin core/auth/authzPerBranch \
20
+ --authz-per-branch-config '{
21
+ "default": {
22
+ "read": true,
23
+ "write": false,
24
+ "delete": false
25
+ },
26
+ "users": {
27
+ "admin": {
28
+ "ou=users,dc=example,dc=com": {
29
+ "read": true,
30
+ "write": true,
31
+ "delete": true
32
+ }
33
+ }
34
+ },
35
+ "groups": {
36
+ "cn=managers,ou=groups,dc=example,dc=com": {
37
+ "ou=organization,dc=example,dc=com": {
38
+ "read": true,
39
+ "write": true,
40
+ "delete": false
41
+ }
42
+ }
43
+ }
44
+ }' \
45
+ --authz-per-branch-cache-ttl 60
46
+ ```
47
+
48
+ **Environment Variables:**
49
+
50
+ ```bash
51
+ DM_AUTHZ_PER_BRANCH_CONFIG='{"default":{"read":true,"write":false,"delete":false},...}'
52
+ DM_AUTHZ_PER_BRANCH_CACHE_TTL=60
53
+ ```
54
+
55
+ ## Configuration Structure
56
+
57
+ ### Default Permissions
58
+
59
+ Applied when no user or group-specific rules match:
60
+
61
+ ```json
62
+ {
63
+ "default": {
64
+ "read": true,
65
+ "write": false,
66
+ "delete": false
67
+ }
68
+ }
69
+ ```
70
+
71
+ ### User Permissions
72
+
73
+ Branch-specific permissions for individual users:
74
+
75
+ ```json
76
+ {
77
+ "users": {
78
+ "username": {
79
+ "ou=branch,dc=example,dc=com": {
80
+ "read": true,
81
+ "write": true,
82
+ "delete": false
83
+ }
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ ### Group Permissions
90
+
91
+ Permissions applied to all group members:
92
+
93
+ ```json
94
+ {
95
+ "groups": {
96
+ "cn=groupname,ou=groups,dc=example,dc=com": {
97
+ "ou=branch,dc=example,dc=com": {
98
+ "read": true,
99
+ "write": true,
100
+ "delete": false
101
+ }
102
+ }
103
+ }
104
+ }
105
+ ```
106
+
107
+ ## Permission Resolution
108
+
109
+ Permissions are resolved in this order:
110
+
111
+ 1. **User-specific permissions** - If user has direct branch permissions, use them
112
+ 2. **Group permissions** - Check all groups user belongs to
113
+ 3. **Default permissions** - Fall back to defaults if no specific rules match
114
+
115
+ For each permission type (read/write/delete), the **most permissive** rule wins.
116
+
117
+ ## How It Works
118
+
119
+ ### LDAP Search Hook
120
+
121
+ Intercepts all LDAP search operations:
122
+
123
+ 1. Checks if request has authenticated user (`req.user`)
124
+ 2. Resolves user's permissions for the requested branch
125
+ 3. Verifies user has `read` permission
126
+ 4. Throws error if access denied
127
+
128
+ ### LDAP Add Hook
129
+
130
+ Intercepts all LDAP add operations:
131
+
132
+ 1. Checks if request has authenticated user
133
+ 2. Resolves user's permissions for the target branch
134
+ 3. Verifies user has `write` permission
135
+ 4. Throws error if access denied
136
+
137
+ ### LDAP Modify Hook
138
+
139
+ Intercepts all LDAP modify operations:
140
+
141
+ 1. For regular modifications: checks `write` permission on the entry's branch
142
+ 2. For **move operations** (changing organization link):
143
+ - Verifies user has `read` permission on source branch
144
+ - Verifies user has `write` permission on destination branch
145
+ - Throws error if either permission is missing
146
+
147
+ ### LDAP Delete Hook
148
+
149
+ Intercepts all LDAP delete operations:
150
+
151
+ 1. Checks if request has authenticated user
152
+ 2. Resolves user's permissions for the entry's branch
153
+ 3. Verifies user has `delete` permission
154
+ 4. Throws error if access denied
155
+
156
+ ### LDAP Rename Hook
157
+
158
+ Intercepts all LDAP rename/modifyDN operations (for organization moves):
159
+
160
+ 1. Extracts source and destination branches from DNs
161
+ 2. Verifies user has `read` permission on source branch
162
+ 3. Verifies user has `write` permission on destination branch
163
+ 4. Throws error if either permission is missing
164
+
165
+ ### Organization Top Hook
166
+
167
+ Modifies the organization tree API:
168
+
169
+ 1. Returns only branches the user can read
170
+ 2. Replaces default top organization with authorized branches
171
+ 3. Enables UI to show only accessible parts of the tree
172
+
173
+ ### Group Resolution
174
+
175
+ Groups are resolved dynamically:
176
+
177
+ 1. Searches for all groups where user is a member
178
+ 2. Uses wildcard DN pattern: `(member=uid={user},*)`
179
+ 3. Caches results for configured TTL (default: 60 seconds)
180
+ 4. Cache prevents repeated LDAP queries for same user
181
+
182
+ ## Sub-branch Inheritance
183
+
184
+ Permissions apply recursively to all sub-branches:
185
+
186
+ ```json
187
+ {
188
+ "users": {
189
+ "manager": {
190
+ "ou=organization,dc=example,dc=com": {
191
+ "read": true
192
+ }
193
+ }
194
+ }
195
+ }
196
+ ```
197
+
198
+ With this config, user `manager` can read:
199
+
200
+ - `ou=organization,dc=example,dc=com`
201
+ - `ou=dept1,ou=organization,dc=example,dc=com`
202
+ - `ou=team1,ou=dept1,ou=organization,dc=example,dc=com`
203
+ - ... all descendants
204
+
205
+ ## Examples
206
+
207
+ ### Example 1: Department-Based Access
208
+
209
+ Allow users to access only their department:
210
+
211
+ ```json
212
+ {
213
+ "default": {
214
+ "read": false,
215
+ "write": false,
216
+ "delete": false
217
+ },
218
+ "users": {
219
+ "hr_user": {
220
+ "ou=HR,ou=organization,dc=example,dc=com": {
221
+ "read": true,
222
+ "write": true,
223
+ "delete": false
224
+ }
225
+ },
226
+ "it_user": {
227
+ "ou=IT,ou=organization,dc=example,dc=com": {
228
+ "read": true,
229
+ "write": true,
230
+ "delete": false
231
+ }
232
+ }
233
+ }
234
+ }
235
+ ```
236
+
237
+ ### Example 2: Group-Based Access
238
+
239
+ Use groups for team permissions:
240
+
241
+ ```json
242
+ {
243
+ "default": {
244
+ "read": true,
245
+ "write": false,
246
+ "delete": false
247
+ },
248
+ "groups": {
249
+ "cn=editors,ou=groups,dc=example,dc=com": {
250
+ "ou=content,dc=example,dc=com": {
251
+ "read": true,
252
+ "write": true,
253
+ "delete": false
254
+ }
255
+ },
256
+ "cn=admins,ou=groups,dc=example,dc=com": {
257
+ "dc=example,dc=com": {
258
+ "read": true,
259
+ "write": true,
260
+ "delete": true
261
+ }
262
+ }
263
+ }
264
+ }
265
+ ```
266
+
267
+ ### Example 3: Read-Only by Default
268
+
269
+ Restrict write access to specific users:
270
+
271
+ ```json
272
+ {
273
+ "default": {
274
+ "read": true,
275
+ "write": false,
276
+ "delete": false
277
+ },
278
+ "users": {
279
+ "admin": {
280
+ "dc=example,dc=com": {
281
+ "read": true,
282
+ "write": true,
283
+ "delete": true
284
+ }
285
+ }
286
+ }
287
+ }
288
+ ```
289
+
290
+ ### Example 4: Multiple Branches per User
291
+
292
+ Grant access to multiple branches:
293
+
294
+ ```json
295
+ {
296
+ "users": {
297
+ "coordinator": {
298
+ "ou=HR,ou=organization,dc=example,dc=com": {
299
+ "read": true,
300
+ "write": true,
301
+ "delete": false
302
+ },
303
+ "ou=Finance,ou=organization,dc=example,dc=com": {
304
+ "read": true,
305
+ "write": false,
306
+ "delete": false
307
+ }
308
+ }
309
+ }
310
+ }
311
+ ```
312
+
313
+ ### Example 5: Move Operations Authorization
314
+
315
+ For move operations (groups or organizations), the user needs **both** read permission on the source and write permission on the destination:
316
+
317
+ ```json
318
+ {
319
+ "users": {
320
+ "manager": {
321
+ "ou=DeptA,ou=organization,dc=example,dc=com": {
322
+ "read": true,
323
+ "write": false,
324
+ "delete": false
325
+ },
326
+ "ou=DeptB,ou=organization,dc=example,dc=com": {
327
+ "read": true,
328
+ "write": true,
329
+ "delete": false
330
+ }
331
+ }
332
+ }
333
+ }
334
+ ```
335
+
336
+ With this configuration:
337
+
338
+ - ✅ User `manager` **CAN** move items from DeptA to DeptB (has read on source, write on destination)
339
+ - ❌ User `manager` **CANNOT** move items from DeptB to DeptA (has write on source but no write on destination)
340
+ - ❌ User `manager` **CANNOT** move items from DeptC to DeptB (no read permission on source)
341
+
342
+ ## API Integration
343
+
344
+ ### Organization Tree API
345
+
346
+ The plugin automatically filters the organization tree API (`/api/v1/ldap/organizations/top`):
347
+
348
+ **Without authzPerBranch:**
349
+
350
+ ```json
351
+ {
352
+ "dn": "ou=organization,dc=example,dc=com",
353
+ "ou": "organization"
354
+ }
355
+ ```
356
+
357
+ **With authzPerBranch (user has access to specific branches):**
358
+
359
+ ```json
360
+ [
361
+ {
362
+ "dn": "ou=HR,ou=organization,dc=example,dc=com",
363
+ "ou": "HR"
364
+ },
365
+ {
366
+ "dn": "ou=IT,ou=organization,dc=example,dc=com",
367
+ "ou": "IT"
368
+ }
369
+ ]
370
+ ```
371
+
372
+ ## Performance
373
+
374
+ ### Group Caching
375
+
376
+ Group memberships are cached to reduce LDAP queries:
377
+
378
+ - **Default TTL**: 60 seconds
379
+ - **Configurable**: `--authz-per-branch-cache-ttl`
380
+ - **Per-user cache**: Each user's groups cached separately
381
+ - **Automatic expiry**: Cache entries expire after TTL
382
+
383
+ Cache hit/miss logging:
384
+
385
+ ```
386
+ [debug] Group cache hit for user: jdoe
387
+ [debug] Group cache miss for user: jsmith - querying LDAP
388
+ ```
389
+
390
+ ### Optimization Tips
391
+
392
+ 1. **Increase cache TTL** for stable group memberships
393
+ 2. **Use group permissions** instead of per-user rules
394
+ 3. **Keep permission config small** - avoid hundreds of rules
395
+ 4. **Structure LDAP efficiently** - shallow hierarchies perform better
396
+
397
+ ## Security Considerations
398
+
399
+ ### Permission Inheritance
400
+
401
+ - Sub-branch permissions inherit from parent branches
402
+ - Cannot grant more restrictive permissions on sub-branches
403
+ - Plan branch structure carefully
404
+
405
+ ### Default Permissions
406
+
407
+ - **Secure by default**: Set `read: false` for sensitive directories
408
+ - **Open by default**: Set `read: true` for general access
409
+ - Choose based on your security posture
410
+
411
+ ### Group-Based Security
412
+
413
+ - Group DNs must be fully qualified
414
+ - Group resolution uses LDAP search - ensure proper indexing
415
+ - Cache can delay permission revocation (up to TTL duration)
416
+
417
+ ### Authentication Required
418
+
419
+ This plugin only handles **authorization**. Combine with an authentication plugin:
420
+
421
+ ```bash
422
+ --plugin core/auth/token \
423
+ --plugin core/auth/authzPerBranch \
424
+ --auth-token "secret-token"
425
+ ```
426
+
427
+ ## Troubleshooting
428
+
429
+ ### Problem: Access Denied
430
+
431
+ **Symptoms:**
432
+
433
+ ```json
434
+ {
435
+ "error": "User jdoe does not have read permission for branch ou=users,dc=example,dc=com"
436
+ }
437
+ ```
438
+
439
+ **Solutions:**
440
+
441
+ 1. Check user has permission for requested branch:
442
+
443
+ ```json
444
+ {
445
+ "users": {
446
+ "jdoe": {
447
+ "ou=users,dc=example,dc=com": {
448
+ "read": true
449
+ }
450
+ }
451
+ }
452
+ }
453
+ ```
454
+
455
+ 2. Verify user is authenticated (check `req.user`)
456
+
457
+ 3. Check default permissions allow access
458
+
459
+ 4. Verify group membership if using group permissions
460
+
461
+ ### Problem: Move Operation Failed
462
+
463
+ **Symptoms:**
464
+
465
+ ```json
466
+ {
467
+ "error": "check logs"
468
+ }
469
+ ```
470
+
471
+ With logs showing:
472
+
473
+ ```
474
+ User jdoe does not have read permission for source branch ou=DeptA,dc=example,dc=com
475
+ ```
476
+
477
+ or
478
+
479
+ ```
480
+ User jdoe does not have write permission for destination branch ou=DeptB,dc=example,dc=com
481
+ ```
482
+
483
+ **Solutions:**
484
+
485
+ 1. Verify user has **read** permission on the source branch
486
+ 2. Verify user has **write** permission on the destination branch
487
+ 3. Move operations require **both** permissions - having write on source is not sufficient
488
+
489
+ Example fix:
490
+
491
+ ```json
492
+ {
493
+ "users": {
494
+ "jdoe": {
495
+ "ou=DeptA,dc=example,dc=com": {
496
+ "read": true,
497
+ "write": false
498
+ },
499
+ "ou=DeptB,dc=example,dc=com": {
500
+ "read": true,
501
+ "write": true
502
+ }
503
+ }
504
+ }
505
+ }
506
+ ```
507
+
508
+ ### Problem: No Branches Returned
509
+
510
+ **Symptoms:**
511
+ Organization tree API returns empty array or no data.
512
+
513
+ **Solutions:**
514
+
515
+ 1. Check user has `read` permission for at least one branch
516
+ 2. Verify DN syntax matches exactly (including spaces, case)
517
+ 3. Check LDAP base configuration matches permission DNs
518
+
519
+ ### Problem: Permissions Not Updating
520
+
521
+ **Symptoms:**
522
+ Changed permissions don't take effect immediately.
523
+
524
+ **Solutions:**
525
+
526
+ 1. Wait for group cache TTL to expire
527
+ 2. Restart server to clear all caches
528
+ 3. Reduce `--authz-per-branch-cache-ttl` for testing
529
+
530
+ ### Problem: Group Permissions Not Working
531
+
532
+ **Symptoms:**
533
+ User should inherit group permissions but doesn't.
534
+
535
+ **Solutions:**
536
+
537
+ 1. Verify user is member of group:
538
+
539
+ ```bash
540
+ ldapsearch -x -b "ou=groups,dc=example,dc=com" "(member=uid=jdoe,*)"
541
+ ```
542
+
543
+ 2. Check group DN in config matches LDAP exactly
544
+
545
+ 3. Ensure group membership uses correct attribute (default: `member`)
546
+
547
+ 4. Configure custom member attribute if needed:
548
+ ```bash
549
+ --ldap-group-member-attribute uniqueMember
550
+ ```
551
+
552
+ ## Integration Examples
553
+
554
+ ### With Token Authentication
555
+
556
+ ```bash
557
+ --plugin core/auth/token \
558
+ --plugin core/auth/authzPerBranch \
559
+ --auth-token "admin-token" \
560
+ --authz-per-branch-config '{
561
+ "default": {"read": false, "write": false, "delete": false}
562
+ }'
563
+ ```
564
+
565
+ ### With OpenID Connect
566
+
567
+ ```bash
568
+ --plugin core/auth/openidconnect \
569
+ --plugin core/auth/authzPerBranch \
570
+ --oidc-server "https://auth.example.com" \
571
+ --oidc-client-id "ldap-rest" \
572
+ --oidc-client-secret "secret" \
573
+ --base-url "https://api.example.com" \
574
+ --authz-per-branch-config '{
575
+ "users": {
576
+ "user@example.com": {
577
+ "ou=organization,dc=example,dc=com": {"read": true, "write": true}
578
+ }
579
+ }
580
+ }'
581
+ ```
582
+
583
+ ### With LemonLDAP::NG
584
+
585
+ ```bash
586
+ --plugin core/auth/llng \
587
+ --plugin core/auth/authzPerBranch \
588
+ --llng-ini /etc/lemonldap-ng/lemonldap-ng.ini \
589
+ --authz-per-branch-config '{"default": {"read": true}}'
590
+ ```
591
+
592
+ ## See Also
593
+
594
+ - [Authentication Plugins](authentication.md) - Setup authentication
595
+ - [LDAP Organizations](ldapOrganizations.md) - Organization tree management
596
+ - [LDAP Groups](ldapGroups.md) - Group management