ldap-rest 0.4.7 → 0.6.0

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 (67) hide show
  1. package/bin/sync-james.mjs +6 -2
  2. package/dist/bin/index.js +1 -1
  3. package/dist/config/args.js +1 -1
  4. package/dist/lib/auth/base.js +1 -1
  5. package/dist/lib/ldapSchema.js +1 -0
  6. package/dist/lib/utils.js +1 -1
  7. package/dist/plugins/auth/authzPerRoute.js +1 -1
  8. package/dist/plugins/auth/rateLimit.js +1 -1
  9. package/dist/plugins/ldap/groups.js +1 -1
  10. package/dist/plugins/ldap/organizations.js +1 -1
  11. package/dist/plugins/ldap/raw.js +1 -0
  12. package/dist/plugins/twake/appAccountsApi.js +1 -1
  13. package/dist/plugins/twake/appAccountsConsistency.js +1 -1
  14. package/dist/src/bin/index.d.ts +112 -0
  15. package/dist/src/browser/ldap-browser/LdapBrowser.d.ts +52 -0
  16. package/dist/src/browser/ldap-browser/api/RawApiClient.d.ts +64 -0
  17. package/dist/src/browser/ldap-browser/components/EntryTree.d.ts +75 -0
  18. package/dist/src/browser/ldap-browser/components/EntryView.d.ts +56 -0
  19. package/dist/src/browser/ldap-browser/index.d.ts +9 -0
  20. package/dist/src/browser/ldap-browser/schema.d.ts +62 -0
  21. package/dist/src/browser/ldap-browser/types.d.ts +96 -0
  22. package/dist/src/config/args.d.ts +7 -0
  23. package/dist/src/lib/auth/base.d.ts +82 -1
  24. package/dist/src/lib/ldapSchema.d.ts +159 -0
  25. package/dist/src/lib/utils.d.ts +4 -0
  26. package/dist/src/plugins/ldap/raw.d.ts +251 -0
  27. package/dist/src/plugins/twake/appAccountsConsistency.d.ts +40 -2
  28. package/docs/client-development/browser/libraries.md +142 -1
  29. package/docs/usage/configuration.md +40 -5
  30. package/docs/usage/plugins/README.md +10 -9
  31. package/docs/usage/plugins/auth/README.md +57 -0
  32. package/docs/usage/plugins/auth/rate-limit.md +9 -0
  33. package/docs/usage/plugins/integrations/app-accounts.md +35 -2
  34. package/docs/usage/plugins/ldap/README.md +12 -0
  35. package/docs/usage/plugins/ldap/raw.md +226 -0
  36. package/examples/web/README.md +18 -0
  37. package/examples/web/ldap-browser.html +94 -0
  38. package/package.json +37 -1
  39. package/static/browser/ldap-browser/LdapBrowser.js +199 -0
  40. package/static/browser/ldap-browser/LdapBrowser.js.map +1 -0
  41. package/static/browser/ldap-browser/api/RawApiClient.js +103 -0
  42. package/static/browser/ldap-browser/api/RawApiClient.js.map +1 -0
  43. package/static/browser/ldap-browser/components/EntryTree.js +235 -0
  44. package/static/browser/ldap-browser/components/EntryTree.js.map +1 -0
  45. package/static/browser/ldap-browser/components/EntryView.js +183 -0
  46. package/static/browser/ldap-browser/components/EntryView.js.map +1 -0
  47. package/static/browser/ldap-browser/index.js +4 -0
  48. package/static/browser/ldap-browser/index.js.map +1 -0
  49. package/static/browser/ldap-browser/schema.js +135 -0
  50. package/static/browser/ldap-browser/schema.js.map +1 -0
  51. package/static/browser/ldap-browser/types.js +2 -0
  52. package/static/browser/ldap-browser/types.js.map +1 -0
  53. package/static/browser/ldap-browser.css +2 -0
  54. package/static/browser/ldap-browser.css.map +1 -0
  55. package/static/browser/ldap-browser.esm.js +915 -0
  56. package/static/browser/ldap-browser.esm.js.map +1 -0
  57. package/static/browser/ldap-browser.js +925 -0
  58. package/static/browser/ldap-browser.js.map +1 -0
  59. package/static/browser/ldap-browser.min.js +2 -0
  60. package/static/browser/ldap-browser.min.js.map +1 -0
  61. package/static/browser/ldap-unit-editor/components/UnitTree.js +0 -1
  62. package/static/browser/ldap-unit-editor/components/UnitTree.js.map +1 -1
  63. package/static/browser/ldap-unit-editor.esm.js +0 -1
  64. package/static/browser/ldap-unit-editor.esm.js.map +1 -1
  65. package/static/browser/ldap-unit-editor.js +0 -1
  66. package/static/browser/ldap-unit-editor.js.map +1 -1
  67. package/static/browser/ldap-unit-editor.min.js.map +1 -1
@@ -43,8 +43,36 @@ Instead of using a single primary password to access all services that authentic
43
43
  2. **App accounts consistency plugin** `core/twake/appAccountsConsistency` - **Required**
44
44
  - Automatically creates principal accounts (uid=mail@domain.com)
45
45
  - Ensures automatic cleanup when users are deleted
46
- - Synchronizes mail changes across all app accounts
46
+ - Moves the principal account on a mail change, and drops the app accounts:
47
+ every MUA has to be reconfigured against the new address anyway
47
48
  3. **Applicative accounts base** configured in LDAP (e.g., `ou=applicative,dc=example,dc=com`)
49
+ 4. **Read access on `userPassword`** in that branch, for the bind DN
50
+ (`--ldap-dn`) - **Required for deletion**
51
+
52
+ Revoking an app account means removing _its_ value from the principal
53
+ account, which holds one `userPassword` per device. The server must read the
54
+ stored hash to know which value to remove — a salted hash cannot be
55
+ recomputed. Without that access, `DELETE` returns `500` and keeps the
56
+ account rather than reporting a revocation that did not happen.
57
+
58
+ A typical OpenLDAP ACL, scoped to the applicative branch so that the users'
59
+ primary passwords stay unreadable:
60
+
61
+ ```
62
+ olcAccess: to dn.subtree="ou=applicative,dc=example,dc=com" attrs=userPassword
63
+ by dn.exact="cn=ldap-rest,ou=tech,dc=example,dc=com" read
64
+ by * break
65
+ ```
66
+
67
+ It must precede any broader rule on `userPassword`; OpenLDAP stops at the
68
+ first matching directive, and `by * break` lets other identities fall
69
+ through to the following ones.
70
+
71
+ 5. **Uniqueness constraints must not cover the applicative branch.** The
72
+ principal account and its app accounts intentionally share the same `mail`,
73
+ so a `slapo-unique` overlay on `mail` has to be scoped to the users branch
74
+ (`olcUniqueURI: ldap:///ou=users,dc=example,dc=com?mail?sub?`) or every app
75
+ account creation is rejected.
48
76
 
49
77
  ## Configuration
50
78
 
@@ -181,6 +209,8 @@ Content-Type: application/json
181
209
  - `400 Bad Request` - Max accounts limit reached or user has no mail
182
210
  - `401 Unauthorized` - Missing or invalid token
183
211
  - `404 Not Found` - User not found
212
+ - `500 Internal Server Error` - The password could not be added to the principal
213
+ account; the app account is rolled back and no password is returned
184
214
 
185
215
  ### Delete Applicative Account
186
216
 
@@ -202,6 +232,9 @@ Authorization: Bearer {token}
202
232
  - `200 OK` - Account deleted (or already deleted - idempotent)
203
233
  - `401 Unauthorized` - Missing or invalid token
204
234
  - `403 Forbidden` - UID does not belong to user
235
+ - `500 Internal Server Error` - The account password could not be read, or could
236
+ not be removed from the principal account; the app account is kept so the
237
+ request stays replayable
205
238
 
206
239
  ## Password Generation
207
240
 
@@ -263,7 +296,7 @@ sync-app-accounts --help
263
296
  - Secure random password
264
297
  4. Plugin creates applicative account in LDAP:
265
298
  - `uid=alice_c12345678,ou=applicative,dc=example,dc=com`
266
- - Copies attributes from user (cn, sn, mail, etc.)
299
+ - Copies the allowlisted attributes from the user (`--applicative-account-attribute`)
267
300
  - Sets generated password
268
301
  5. Plugin adds password to principal account:
269
302
  - `uid=alice@example.com,ou=applicative,dc=example,dc=com`
@@ -14,6 +14,7 @@ Plugins for LDAP entity management.
14
14
  | [external-users](external-users.md) | Contacts | Automatic creation |
15
15
  | [on-change](on-change.md) | All | Change detection |
16
16
  | [password-policy](password-policy.md) | Password management | Expiration, Lockout, Unlock |
17
+ | [raw](raw.md) | Whole directory (read) | Root DSE, Schema, Tree, Raw search |
17
18
 
18
19
  ## API Endpoints
19
20
 
@@ -62,6 +63,17 @@ GET /api/v1/password-policy/locked-accounts # List locked accounts
62
63
  POST /api/v1/password/validate # Validate complexity (optional)
63
64
  ```
64
65
 
66
+ ### Low-level browsing (ldapRaw)
67
+
68
+ ```
69
+ GET /api/v1/ldap/raw/bases # Exposed subtrees
70
+ GET /api/v1/ldap/raw/rootdse # Server capabilities
71
+ GET /api/v1/ldap/raw/schema # Parsed directory schema
72
+ GET /api/v1/ldap/raw/entry/{dn} # Read one entry
73
+ GET /api/v1/ldap/raw/children/{dn} # Direct children of an entry
74
+ GET /api/v1/ldap/raw/search # Raw search (base, scope, filter)
75
+ ```
76
+
65
77
  ### Bulk Import (ldapBulkImport)
66
78
 
67
79
  ```
@@ -0,0 +1,226 @@
1
+ # LDAP Raw Plugin (low-level browsing)
2
+
3
+ Read-only, low-level access to the directory itself: root DSE, schema, and entries addressed by their DN. Where the other LDAP plugins expose business objects (users, groups, organizations), this one exposes the tree as it is stored — the server side of a phpLDAPadmin-like interface.
4
+
5
+ The companion browser library is [`ldap-browser`](../../../client-development/browser/libraries.md#ldapbrowser).
6
+
7
+ ## Features
8
+
9
+ - **Root DSE**: naming contexts, supported controls and extensions
10
+ - **Schema**: object classes, attribute types, syntaxes and matching rules, parsed from the subschema entry (RFC 4512) and cached
11
+ - **Entry read**: every attribute, operational ones included, binary values base64-encoded
12
+ - **Tree navigation**: direct children of a DN, with an optional "has children" probe
13
+ - **Raw search**: arbitrary base, scope and LDAP filter
14
+ - **Read-only**: this plugin registers no write route
15
+
16
+ ## Configuration
17
+
18
+ ### Environment Variables
19
+
20
+ - `DM_LDAP_RAW_BASE`: comma-separated subtrees to expose (default: `--ldap-base`)
21
+ - `DM_LDAP_RAW_HIDDEN_ATTRIBUTES`: comma-separated attributes never returned, on top of the credential ones (default: none)
22
+ - `DM_LDAP_RAW_SHOW_SECRETS`: serve credential attributes instead of hiding them (default: `false`)
23
+ - `DM_LDAP_RAW_MAX_RESULTS`: maximum entries returned by a search or a children listing (default: `200`)
24
+ - `DM_LDAP_RAW_SCHEMA_CACHE_TTL`: schema cache lifetime in seconds (default: `3600`)
25
+
26
+ ### Command Line
27
+
28
+ ```bash
29
+ ldap-rest \
30
+ --plugin core/ldap/raw \
31
+ --ldap-raw-base "ou=users,dc=example,dc=com" \
32
+ --ldap-raw-base "ou=groups,dc=example,dc=com" \
33
+ --ldap-raw-hidden-attribute employeeNumber \
34
+ --ldap-raw-max-results 500
35
+ ```
36
+
37
+ With no `--ldap-raw-base`, the plugin exposes `--ldap-base`.
38
+
39
+ ## API Endpoints
40
+
41
+ ```
42
+ GET /api/v1/ldap/raw/bases # Exposed subtrees (roots of the tree)
43
+ GET /api/v1/ldap/raw/rootdse # Server capabilities
44
+ GET /api/v1/ldap/raw/schema # Parsed directory schema
45
+ GET /api/v1/ldap/raw/entry/{dn} # One entry, operational attributes included
46
+ GET /api/v1/ldap/raw/children/{dn} # Direct children of an entry
47
+ GET /api/v1/ldap/raw/search # Arbitrary search
48
+ ```
49
+
50
+ `{dn}` is the URL-encoded fully-qualified DN.
51
+
52
+ ### Entry format
53
+
54
+ Attribute values are always arrays. A `binary` flag tells whether the values are base64-encoded octets rather than text:
55
+
56
+ ```json
57
+ {
58
+ "dn": "uid=alice,ou=users,dc=example,dc=com",
59
+ "attributes": {
60
+ "objectClass": { "values": ["top", "inetOrgPerson"], "binary": false },
61
+ "uid": { "values": ["alice"], "binary": false },
62
+ "cn": { "values": ["Alice Smith"], "binary": false },
63
+ "jpegPhoto": { "values": ["/9j/4AAQSkZJRg…"], "binary": true }
64
+ }
65
+ }
66
+ ```
67
+
68
+ A value is flagged binary when the directory returned octets that are not valid UTF-8, or when the attribute type is binary.
69
+
70
+ Credential attributes are **not** part of the response by default — see [Hidden attributes](#hidden-attributes).
71
+
72
+ ### Children
73
+
74
+ ```bash
75
+ curl "$URL/api/v1/ldap/raw/children/$(urlencode 'dc=example,dc=com')?children=1"
76
+ ```
77
+
78
+ ```json
79
+ {
80
+ "children": [
81
+ {
82
+ "dn": "ou=users,dc=example,dc=com",
83
+ "rdn": "ou=users",
84
+ "objectClass": ["organizationalUnit"],
85
+ "hasChildren": true
86
+ }
87
+ ],
88
+ "truncated": false
89
+ }
90
+ ```
91
+
92
+ `hasChildren` is only computed when the `children` query parameter is set: it costs one extra search per child.
93
+
94
+ At most `--ldap-raw-max-results` children are returned. `truncated` is true when the branch holds more, so a browsing UI can say so instead of silently showing a partial list — a branch of 5000 users must not look like a branch of 200.
95
+
96
+ ### Search
97
+
98
+ | Parameter | Default | Description |
99
+ | ------------ | ------------------------ | ---------------------------------------------- |
100
+ | `base` | first exposed base | Search base, must be inside an exposed subtree |
101
+ | `scope` | `sub` | `base`, `one` or `sub` |
102
+ | `filter` | `(objectClass=*)` | LDAP filter |
103
+ | `attributes` | `*` | Comma-separated attribute list |
104
+ | `limit` | `--ldap-raw-max-results` | Capped by `--ldap-raw-max-results` |
105
+
106
+ ```bash
107
+ curl "$URL/api/v1/ldap/raw/search?base=ou=users,dc=example,dc=com&filter=(mail=*@example.com)&attributes=uid,mail"
108
+ ```
109
+
110
+ ```json
111
+ { "entries": [...], "truncated": false }
112
+ ```
113
+
114
+ `truncated` is true when the limit cut the result set short.
115
+
116
+ The filter is parsed before the search runs, so a malformed one comes back as a 400 naming it rather than as a server error — a search box receives whatever the user typed, and `gov` is a typo, not a server fault:
117
+
118
+ ```json
119
+ {
120
+ "error": "Invalid LDAP filter \"gov\": Invalid expression: gov. A filter must be parenthesised, e.g. (cn=foo) or (|(cn=*foo*)(ou=*foo*))"
121
+ }
122
+ ```
123
+
124
+ ### Schema
125
+
126
+ ```json
127
+ {
128
+ "objectClasses": [
129
+ {
130
+ "oid": "2.5.6.6",
131
+ "names": ["person"],
132
+ "desc": "RFC2256: a person",
133
+ "kind": "STRUCTURAL",
134
+ "sup": ["top"],
135
+ "must": ["sn", "cn"],
136
+ "may": ["userPassword", "telephoneNumber", "seeAlso", "description"],
137
+ "obsolete": false
138
+ }
139
+ ],
140
+ "attributeTypes": [
141
+ {
142
+ "oid": "2.5.4.3",
143
+ "names": ["cn", "commonName"],
144
+ "sup": "name",
145
+ "singleValue": false,
146
+ "noUserModification": false,
147
+ "usage": "userApplications",
148
+ "obsolete": false,
149
+ "collective": false
150
+ }
151
+ ],
152
+ "syntaxes": [...],
153
+ "matchingRules": [...]
154
+ }
155
+ ```
156
+
157
+ Inheritance is **not** flattened: a client resolving the attributes of an entry must walk the `sup` chains. `SchemaView` (browser) and `SchemaIndex` (`src/lib/ldapSchema.ts`, server) do it for you.
158
+
159
+ ## Hidden attributes
160
+
161
+ Attributes holding credential material are stripped from **every** response — entry reads and searches alike — before it leaves the server. Asking for one explicitly (`?attributes=uid,userPassword`) does not get around the filter: the removal happens when the entry is serialised, not when the query is built.
162
+
163
+ The built-in list covers the usual OpenLDAP, Samba, Kerberos and Active Directory spellings:
164
+
165
+ ```
166
+ userPassword, authPassword, pwdHistory, sambaNTPassword, sambaLMPassword,
167
+ sambaPasswordHistory, krbPrincipalKey, krbExtraData, krbPwdHistory,
168
+ unicodePwd, dbcsPwd, lmPwdHistory, ntPwdHistory, supplementalCredentials,
169
+ userPKCS12
170
+ ```
171
+
172
+ A password hash served over HTTP is an offline cracking target, and browsing a directory does not require reading one — hence hidden by default, visible only on request:
173
+
174
+ ```bash
175
+ --ldap-raw-show-secrets true # logs a warning at startup
176
+ ```
177
+
178
+ Site-specific attributes are added with `--ldap-raw-hidden-attribute`, which stacks on top of the built-in list rather than replacing it:
179
+
180
+ ```bash
181
+ --ldap-raw-hidden-attribute twakeApiKey --ldap-raw-hidden-attribute employeeNumber
182
+ ```
183
+
184
+ Note that hiding an attribute here keeps it out of the API, not out of the directory: an account able to bind to LDAP directly still reads it. This is a guard against casual exposure through the browsing UI, not an access control — use [authz-per-branch](../auth/authz-per-branch.md) or directory ACLs for that.
185
+
186
+ ## Security
187
+
188
+ Access is restricted in three independent layers:
189
+
190
+ 1. **Exposed bases** — any DN outside `--ldap-raw-base` is refused with a 403, whatever the caller's rights.
191
+ 2. **Authorization hooks** — every entry read, children listing and search goes through `server.ldap`, so the authorization plugins ([authz-per-branch](../auth/authz-per-branch.md), authz-dynamic, …) apply exactly as on the high-level APIs.
192
+ 3. **Hidden attributes** — credential attributes, plus anything in `--ldap-raw-hidden-attribute`, are removed from every response, including searches. See [Hidden attributes](#hidden-attributes).
193
+
194
+ Two exceptions, both deliberate: the **root DSE** and the **schema** are read with the service account, not with the caller's rights. They are directory metadata and carry no user data; reading them with a restricted account would leave the UI unable to name and type attributes. Do not expose this plugin publicly if your directory publishes sensitive information in its root DSE.
195
+
196
+ Combine with an authentication plugin ([token](../auth/token.md), [oidc](../auth/oidc.md), …) — this plugin adds no authentication of its own.
197
+
198
+ ## How It Works
199
+
200
+ - **Schema fetch**: the root DSE is read for `subschemaSubentry` (falling back to `cn=Subschema`), then the subschema entry is fetched and parsed once per `--ldap-raw-schema-cache-ttl`. Concurrent callers share a single fetch.
201
+ - **Operational attributes**: entries are read with `*` and `+`. When the server rejects `+`, the read is retried with `*` alone.
202
+ - **Missing entries**: the LDAP "no such object" result (code 32) is mapped to a 404.
203
+
204
+ ## Limitations
205
+
206
+ - **Read-only.** Creating, modifying, renaming and deleting entries is not exposed yet.
207
+ - **No LDIF** import or export.
208
+ - **No paging**: searches and children listings are capped by `--ldap-raw-max-results` and flagged as `truncated`; there is no cursor to fetch the rest. Use a narrower search to reach entries beyond the cap.
209
+
210
+ ## Usage Example
211
+
212
+ ```bash
213
+ ldap-rest \
214
+ --plugin core/auth/token --auth-token "$TOKEN" \
215
+ --plugin core/ldap/raw \
216
+ --plugin core/static
217
+ ```
218
+
219
+ The demo page ([`examples/web/ldap-browser.html`](../../../../examples/web/ldap-browser.html)) is then served at
220
+ `/static/examples/web/ldap-browser.html`.
221
+
222
+ ## See Also
223
+
224
+ - [ldap-browser client library](../../../client-development/browser/libraries.md#ldapbrowser)
225
+ - [organizations plugin](organizations.md) — high-level tree of organizational units
226
+ - [authz-per-branch plugin](../auth/authz-per-branch.md) — branch-level access control
@@ -82,6 +82,23 @@ Manage organizational units.
82
82
  - Move units
83
83
  - Create/delete units
84
84
 
85
+ ### 🗂️ LDAP Browser (`ldap-browser.html`)
86
+
87
+ Low-level, read-only view of the directory, in the spirit of phpLDAPadmin.
88
+
89
+ **Features:**
90
+
91
+ - Lazy tree of the whole directory
92
+ - Raw entry content, operational attributes included
93
+ - Schema annotations: mandatory attributes, descriptions, unknown attributes flagged
94
+ - LDAP filter search with scope selection
95
+
96
+ Requires the `core/ldap/raw` plugin:
97
+
98
+ ```bash
99
+ npm start -- --plugin core/ldap/raw
100
+ ```
101
+
85
102
  ## Running Examples
86
103
 
87
104
  1. **Start the server:**
@@ -109,6 +126,7 @@ Manage organizational units.
109
126
  http://localhost:8081/static/examples/web/ldap-user-editor.html
110
127
  http://localhost:8081/static/examples/web/ldap-group-editor.html
111
128
  http://localhost:8081/static/examples/web/ldap-unit-editor.html
129
+ http://localhost:8081/static/examples/web/ldap-browser.html
112
130
  ```
113
131
 
114
132
  ## Using Browser Libraries in Your Application
@@ -0,0 +1,94 @@
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 Browser 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
+ <!-- Library CSS -->
21
+ <link rel="stylesheet" href="/static/browser/ldap-browser.css" />
22
+
23
+ <style>
24
+ :root {
25
+ --primary-color: #3949ab;
26
+ --primary-color-dark: #283593;
27
+ }
28
+
29
+ body {
30
+ background: linear-gradient(135deg, #8ea7e9 0%, #3949ab 100%);
31
+ }
32
+
33
+ .demo-header h1 {
34
+ color: #3949ab;
35
+ }
36
+
37
+ #ldap-browser {
38
+ height: 70vh;
39
+ min-height: 520px;
40
+ }
41
+ </style>
42
+ </head>
43
+ <body>
44
+ <div class="demo-container">
45
+ <div class="demo-header">
46
+ <h1>🗂️ LDAP Browser</h1>
47
+ <p>
48
+ Low-level, read-only view of the directory: tree, raw entries and
49
+ schema
50
+ </p>
51
+ </div>
52
+
53
+ <div id="status-container"></div>
54
+
55
+ <div id="ldap-browser"></div>
56
+ </div>
57
+
58
+ <!-- Shared utilities -->
59
+ <script src="/static/browser/shared.js"></script>
60
+ <!-- Library JS -->
61
+ <script src="/static/browser/ldap-browser.js"></script>
62
+
63
+ <script>
64
+ const { LdapBrowser } = window.LdapBrowser;
65
+ const { showStatus } = window.MiniDmShared;
66
+
67
+ async function initBrowser() {
68
+ try {
69
+ const browser = new LdapBrowser({
70
+ containerId: 'ldap-browser',
71
+ apiBaseUrl: window.location.origin,
72
+ onEntrySelected: dn => console.log('Entry selected:', dn),
73
+ onError: error => {
74
+ console.error('Browser error:', error);
75
+ showStatus(
76
+ 'status-container',
77
+ `Error: ${error.message}`,
78
+ 'error'
79
+ );
80
+ },
81
+ });
82
+
83
+ await browser.init();
84
+ showStatus('status-container', 'LDAP Browser loaded', 'success');
85
+ } catch (error) {
86
+ console.error('Failed to initialize browser:', error);
87
+ showStatus('status-container', `Error: ${error.message}`, 'error');
88
+ }
89
+ }
90
+
91
+ initBrowser();
92
+ </script>
93
+ </body>
94
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ldap-rest",
3
- "version": "0.4.7",
3
+ "version": "0.6.0",
4
4
  "description": "Light directory manager",
5
5
  "keywords": [
6
6
  "Identity-Manager"
@@ -132,6 +132,10 @@
132
132
  "types": "./dist/src/plugins/ldap/passwordPolicy.d.ts",
133
133
  "import": "./dist/plugins/ldap/passwordPolicy.js"
134
134
  },
135
+ "./plugin-ldap-raw": {
136
+ "types": "./dist/src/plugins/ldap/raw.d.ts",
137
+ "import": "./dist/plugins/ldap/raw.js"
138
+ },
135
139
  "./plugin-ldap-trash": {
136
140
  "types": "./dist/src/plugins/ldap/trash.d.ts",
137
141
  "import": "./dist/plugins/ldap/trash.js"
@@ -232,6 +236,34 @@
232
236
  "types": "./dist/src/abstract/twakePlugin.d.ts",
233
237
  "import": "./dist/abstract/twakePlugin.js"
234
238
  },
239
+ "./browser-ldap-browser-ldapbrowser": {
240
+ "types": "./dist/src/browser/ldap-browser/LdapBrowser.d.ts",
241
+ "import": "./static/browser/ldap-browser/LdapBrowser.js"
242
+ },
243
+ "./browser-ldap-browser-api-rawapiclient": {
244
+ "types": "./dist/src/browser/ldap-browser/api/RawApiClient.d.ts",
245
+ "import": "./static/browser/ldap-browser/api/RawApiClient.js"
246
+ },
247
+ "./browser-ldap-browser-components-entrytree": {
248
+ "types": "./dist/src/browser/ldap-browser/components/EntryTree.d.ts",
249
+ "import": "./static/browser/ldap-browser/components/EntryTree.js"
250
+ },
251
+ "./browser-ldap-browser-components-entryview": {
252
+ "types": "./dist/src/browser/ldap-browser/components/EntryView.d.ts",
253
+ "import": "./static/browser/ldap-browser/components/EntryView.js"
254
+ },
255
+ "./browser-ldap-browser-index": {
256
+ "types": "./dist/src/browser/ldap-browser/index.d.ts",
257
+ "import": "./static/browser/ldap-browser/index.js"
258
+ },
259
+ "./browser-ldap-browser-schema": {
260
+ "types": "./dist/src/browser/ldap-browser/schema.d.ts",
261
+ "import": "./static/browser/ldap-browser/schema.js"
262
+ },
263
+ "./browser-ldap-browser-types": {
264
+ "types": "./dist/src/browser/ldap-browser/types.d.ts",
265
+ "import": "./static/browser/ldap-browser/types.js"
266
+ },
235
267
  "./browser-ldap-group-editor-ldapgroupeditor": {
236
268
  "types": "./dist/src/browser/ldap-group-editor/LdapGroupEditor.d.ts",
237
269
  "import": "./static/browser/ldap-group-editor/LdapGroupEditor.js"
@@ -578,6 +610,8 @@
578
610
  "check": "npm run check:ts && npm run lint && npm run format:check",
579
611
  "check:ts": "tsc --noEmit",
580
612
  "clean": "rimraf dist/* static/browser/* coverage",
613
+ "coverage": "c8 --config .c8rc.json mocha",
614
+ "coverage:check": "npm run check:ts && c8 --config .c8rc.json --exclude 'src/browser/**' --check-coverage --statements 84 --lines 84 --branches 75 --functions 86 mocha",
581
615
  "dev": "npm run start:dev",
582
616
  "fix": "npm run lint:fix && npm run format:fix",
583
617
  "format:check": "prettier --check .",
@@ -626,6 +660,7 @@
626
660
  "@types/supertest": "^6.0.3",
627
661
  "@typescript-eslint/eslint-plugin": "^8.44.0",
628
662
  "@typescript-eslint/parser": "^8.44.0",
663
+ "c8": "^10.1.3",
629
664
  "chai": "^6.0.1",
630
665
  "eslint": "^9.35.0",
631
666
  "eslint-config-prettier": "^10.1.8",
@@ -633,6 +668,7 @@
633
668
  "eslint-plugin-node": "^11.1.0",
634
669
  "eslint-plugin-prettier": "^5.5.4",
635
670
  "fast-glob": "^3.3.3",
671
+ "globals": "^14.0.0",
636
672
  "js-yaml": "^4.1.1",
637
673
  "mocha": "^11.7.2",
638
674
  "nock": "^14.0.10",