ldap-rest 0.0.1 → 0.1.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 (62) hide show
  1. package/README.md +38 -0
  2. package/bin/sync-app-accounts.mjs +276 -0
  3. package/dist/abstract/ldapFlat.js +1 -1
  4. package/dist/abstract/plugin.js +1 -1
  5. package/dist/bin/index.js +1 -1
  6. package/dist/config/args.js +1 -1
  7. package/dist/lib/ldapActions.js +1 -1
  8. package/dist/lib/utils.js +1 -1
  9. package/dist/logger/winston.js +1 -1
  10. package/dist/plugins/auth/hmac.js +1 -0
  11. package/dist/plugins/auth/totp.js +1 -0
  12. package/dist/plugins/demo/helloworld.js +1 -1
  13. package/dist/plugins/ldap/groups.js +1 -1
  14. package/dist/plugins/ldap/onChange.js +1 -1
  15. package/dist/plugins/static.js +1 -1
  16. package/dist/plugins/twake/appAccountsApi.js +1 -0
  17. package/dist/plugins/twake/appAccountsConsistency.js +1 -0
  18. package/dist/plugins/twake/james.js +1 -1
  19. package/dist/plugins/weblogs.js +1 -1
  20. package/dist/src/abstract/ldapFlat.d.ts +0 -5
  21. package/dist/src/abstract/plugin.d.ts +1 -0
  22. package/dist/src/bin/index.d.ts +1 -0
  23. package/dist/src/browser/shared/index.d.ts +1 -0
  24. package/dist/src/browser/shared/utils/hmac.d.ts +73 -0
  25. package/dist/src/browser/shared/utils/totp.d.ts +64 -0
  26. package/dist/src/config/args.d.ts +9 -1
  27. package/dist/src/hooks.d.ts +2 -2
  28. package/dist/src/lib/ldapActions.d.ts +3 -7
  29. package/dist/src/lib/utils.d.ts +17 -0
  30. package/dist/src/logger/winston.d.ts +5 -0
  31. package/dist/src/plugins/auth/hmac.d.ts +24 -0
  32. package/dist/src/plugins/auth/totp.d.ts +35 -0
  33. package/dist/src/plugins/ldap/onChange.d.ts +1 -0
  34. package/dist/src/plugins/static.d.ts +4 -0
  35. package/dist/src/plugins/twake/appAccountsApi.d.ts +52 -0
  36. package/dist/src/plugins/twake/appAccountsConsistency.d.ts +58 -0
  37. package/docs/DEVELOPER_GUIDE.md +1 -0
  38. package/docs/PLUGIN_DEPENDENCIES.md +19 -0
  39. package/docs/README.md +74 -30
  40. package/docs/authentication.md +600 -12
  41. package/docs/plugins/DEVELOPMENT.md +148 -76
  42. package/docs/testing-with-embedded-ldap.md +342 -0
  43. package/docs/twakeAppAccountsApi.md +485 -0
  44. package/docs/weblogs.md +36 -8
  45. package/examples/web/README.md +166 -0
  46. package/examples/web/ldap-tree-viewer.html +16 -2
  47. package/examples/web/totp-client.html +543 -0
  48. package/package.json +46 -1
  49. package/static/browser/shared/index.js +1 -0
  50. package/static/browser/shared/index.js.map +1 -1
  51. package/static/browser/shared/utils/hmac.js +202 -0
  52. package/static/browser/shared/utils/hmac.js.map +1 -0
  53. package/static/browser/shared/utils/totp.js +182 -0
  54. package/static/browser/shared/utils/totp.js.map +1 -0
  55. package/static/browser/shared.esm.js +181 -1
  56. package/static/browser/shared.esm.js.map +1 -1
  57. package/static/browser/shared.js +184 -0
  58. package/static/browser/shared.js.map +1 -1
  59. package/static/browser/shared.min.js +1 -1
  60. package/static/browser/shared.min.js.map +1 -1
  61. package/static/schemas/obm/organizations.json +24 -0
  62. package/static/schemas/obm/users.json +192 -0
@@ -0,0 +1,543 @@
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>TOTP Client Demo</title>
7
+
8
+ <!-- Google Fonts -->
9
+ <link
10
+ href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500;700&family=Roboto:wght@300;400;500;700&display=swap"
11
+ rel="stylesheet"
12
+ />
13
+ <link
14
+ href="https://fonts.googleapis.com/icon?family=Material+Icons"
15
+ rel="stylesheet"
16
+ />
17
+
18
+ <!-- Shared CSS -->
19
+ <link rel="stylesheet" href="/static/browser/common-demo.css" />
20
+
21
+ <style>
22
+ :root {
23
+ --primary-color: #00bfa5;
24
+ --primary-color-dark: #00897b;
25
+ --success-color: #4caf50;
26
+ --error-color: #f44336;
27
+ }
28
+
29
+ body {
30
+ background: linear-gradient(135deg, #00bfa5 0%, #00695c 100%);
31
+ }
32
+
33
+ .demo-header h1 {
34
+ color: #00bfa5;
35
+ }
36
+
37
+ .totp-code {
38
+ font-family: 'Roboto Mono', monospace;
39
+ font-size: 48px;
40
+ font-weight: 700;
41
+ text-align: center;
42
+ padding: 30px;
43
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
44
+ color: white;
45
+ border-radius: 12px;
46
+ letter-spacing: 8px;
47
+ margin: 20px 0;
48
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
49
+ user-select: all;
50
+ }
51
+
52
+ .totp-code.expired {
53
+ opacity: 0.5;
54
+ }
55
+
56
+ .countdown {
57
+ text-align: center;
58
+ font-size: 18px;
59
+ color: #666;
60
+ margin-top: 10px;
61
+ }
62
+
63
+ .countdown-bar {
64
+ height: 6px;
65
+ background: #e0e0e0;
66
+ border-radius: 3px;
67
+ overflow: hidden;
68
+ margin: 10px 0;
69
+ }
70
+
71
+ .countdown-bar-fill {
72
+ height: 100%;
73
+ background: linear-gradient(90deg, #4caf50 0%, #ff9800 50%, #f44336 100%);
74
+ transition: width 0.3s ease;
75
+ }
76
+
77
+ .secret-input {
78
+ font-family: 'Roboto Mono', monospace;
79
+ width: 100%;
80
+ padding: 12px;
81
+ font-size: 16px;
82
+ border: 2px solid #ddd;
83
+ border-radius: 8px;
84
+ margin: 10px 0;
85
+ text-transform: uppercase;
86
+ }
87
+
88
+ .secret-input:focus {
89
+ outline: none;
90
+ border-color: var(--primary-color);
91
+ }
92
+
93
+ .config-grid {
94
+ display: grid;
95
+ grid-template-columns: 1fr 1fr;
96
+ gap: 15px;
97
+ margin: 20px 0;
98
+ }
99
+
100
+ .config-field label {
101
+ display: block;
102
+ font-weight: 500;
103
+ margin-bottom: 5px;
104
+ color: #555;
105
+ }
106
+
107
+ .config-field input,
108
+ .config-field select {
109
+ width: 100%;
110
+ padding: 10px;
111
+ border: 2px solid #ddd;
112
+ border-radius: 8px;
113
+ font-size: 14px;
114
+ }
115
+
116
+ .api-test {
117
+ margin-top: 30px;
118
+ padding: 20px;
119
+ background: #f9f9f9;
120
+ border-radius: 8px;
121
+ }
122
+
123
+ .api-response {
124
+ font-family: 'Roboto Mono', monospace;
125
+ font-size: 12px;
126
+ background: #263238;
127
+ color: #aed581;
128
+ padding: 15px;
129
+ border-radius: 8px;
130
+ overflow-x: auto;
131
+ white-space: pre-wrap;
132
+ word-wrap: break-word;
133
+ max-height: 300px;
134
+ overflow-y: auto;
135
+ margin-top: 10px;
136
+ }
137
+
138
+ .api-response.error {
139
+ color: #ef5350;
140
+ }
141
+
142
+ .info-box {
143
+ background: #e3f2fd;
144
+ border-left: 4px solid #2196f3;
145
+ padding: 15px;
146
+ margin: 20px 0;
147
+ border-radius: 4px;
148
+ }
149
+
150
+ .info-box h3 {
151
+ margin-top: 0;
152
+ color: #1976d2;
153
+ }
154
+
155
+ .info-box code {
156
+ background: #fff;
157
+ padding: 2px 6px;
158
+ border-radius: 3px;
159
+ font-family: 'Roboto Mono', monospace;
160
+ }
161
+
162
+ .button-group {
163
+ display: flex;
164
+ gap: 10px;
165
+ margin: 15px 0;
166
+ }
167
+
168
+ .demo-button.secondary {
169
+ background: #6c757d;
170
+ }
171
+
172
+ .demo-button.secondary:hover {
173
+ background: #5a6268;
174
+ }
175
+
176
+ .demo-button.success {
177
+ background: #4caf50;
178
+ }
179
+
180
+ .demo-button.success:hover {
181
+ background: #45a049;
182
+ }
183
+
184
+ @media (max-width: 768px) {
185
+ .config-grid {
186
+ grid-template-columns: 1fr;
187
+ }
188
+
189
+ .totp-code {
190
+ font-size: 36px;
191
+ letter-spacing: 6px;
192
+ padding: 20px;
193
+ }
194
+ }
195
+ </style>
196
+ </head>
197
+ <body>
198
+ <div class="demo-container">
199
+ <div class="demo-header">
200
+ <h1>🔐 TOTP Client Demo</h1>
201
+ <p>Time-based One-Time Password Generator and API Client</p>
202
+ </div>
203
+
204
+ <div id="status-container"></div>
205
+
206
+ <div class="demo-grid">
207
+ <!-- TOTP Generator Panel -->
208
+ <div class="demo-panel">
209
+ <h2>
210
+ <span class="material-icons">vpn_key</span>
211
+ TOTP Generator
212
+ </h2>
213
+
214
+ <div class="info-box">
215
+ <h3>What is TOTP?</h3>
216
+ <p>
217
+ TOTP generates temporary codes that change every 30 seconds.
218
+ Enter your Base32 secret to generate codes compatible with Google
219
+ Authenticator, Authy, and other authenticator apps.
220
+ </p>
221
+ </div>
222
+
223
+ <label for="secret-input" style="font-weight: 500; margin-bottom: 5px; display: block;">
224
+ Base32 Secret
225
+ </label>
226
+ <input
227
+ type="text"
228
+ id="secret-input"
229
+ class="secret-input"
230
+ placeholder="JBSWY3DPEHPK3PXP"
231
+ value="JBSWY3DPEHPK3PXP"
232
+ />
233
+
234
+ <div class="config-grid">
235
+ <div class="config-field">
236
+ <label for="digits-input">Digits</label>
237
+ <select id="digits-input">
238
+ <option value="6" selected>6 digits</option>
239
+ <option value="8">8 digits</option>
240
+ <option value="10">10 digits</option>
241
+ </select>
242
+ </div>
243
+ <div class="config-field">
244
+ <label for="step-input">Time Step (seconds)</label>
245
+ <input
246
+ type="number"
247
+ id="step-input"
248
+ value="30"
249
+ min="10"
250
+ max="120"
251
+ />
252
+ </div>
253
+ </div>
254
+
255
+ <div class="button-group">
256
+ <button id="btn-generate" class="demo-button success">
257
+ <span class="material-icons" style="vertical-align: middle">
258
+ refresh
259
+ </span>
260
+ Generate Code
261
+ </button>
262
+ <button id="btn-copy" class="demo-button secondary">
263
+ <span class="material-icons" style="vertical-align: middle">
264
+ content_copy
265
+ </span>
266
+ Copy Code
267
+ </button>
268
+ </div>
269
+
270
+ <div id="totp-display">
271
+ <div class="totp-code" id="totp-code">------</div>
272
+ <div class="countdown-bar">
273
+ <div class="countdown-bar-fill" id="countdown-bar"></div>
274
+ </div>
275
+ <div class="countdown" id="countdown-text">
276
+ Waiting for code generation...
277
+ </div>
278
+ </div>
279
+ </div>
280
+
281
+ <!-- API Client Panel -->
282
+ <div class="demo-panel">
283
+ <h2>
284
+ <span class="material-icons">http</span>
285
+ API Client Test
286
+ </h2>
287
+
288
+ <div class="info-box">
289
+ <h3>API Authentication</h3>
290
+ <p>
291
+ The TOTP client automatically adds the current code to the
292
+ <code>Authorization: Bearer</code> header for each request.
293
+ </p>
294
+ </div>
295
+
296
+ <div class="api-test">
297
+ <h3>Test API Request</h3>
298
+ <p>
299
+ Test the TOTP authentication by making a request to the LDAP REST
300
+ API.
301
+ </p>
302
+
303
+ <div class="config-field">
304
+ <label for="api-endpoint">API Endpoint</label>
305
+ <input
306
+ type="text"
307
+ id="api-endpoint"
308
+ value="/api/hello"
309
+ placeholder="/api/v1/ldap/users"
310
+ />
311
+ </div>
312
+
313
+ <div class="button-group">
314
+ <button id="btn-test-api" class="demo-button">
315
+ <span class="material-icons" style="vertical-align: middle">
316
+ send
317
+ </span>
318
+ Test Request
319
+ </button>
320
+ </div>
321
+
322
+ <div id="api-response-container" style="display: none">
323
+ <h4>Response:</h4>
324
+ <div id="api-response" class="api-response"></div>
325
+ </div>
326
+ </div>
327
+ </div>
328
+ </div>
329
+
330
+ <!-- Usage Examples Panel -->
331
+ <div class="demo-panel" style="margin-top: 20px">
332
+ <h2>
333
+ <span class="material-icons">code</span>
334
+ Usage Examples
335
+ </h2>
336
+
337
+ <h3>Installation</h3>
338
+ <div class="api-response" style="margin-bottom: 20px">
339
+ npm install ldap-rest
340
+ # or
341
+ yarn add ldap-rest</div>
342
+
343
+ <h3>Import the TOTP Client</h3>
344
+ <div class="api-response" style="margin-bottom: 20px">
345
+ import { generateTotp, TotpAuthClient } from 'ldap-rest/browser-shared-utils-totp';</div>
346
+
347
+ <h3>Generate TOTP Code</h3>
348
+ <div class="api-response" style="margin-bottom: 20px">
349
+ // Generate a TOTP code
350
+ const code = await generateTotp({
351
+ secret: 'JBSWY3DPEHPK3PXP',
352
+ digits: 6,
353
+ step: 30
354
+ });
355
+
356
+ console.log('Current TOTP code:', code);</div>
357
+
358
+ <h3>Use TotpAuthClient for API Requests</h3>
359
+ <div class="api-response" style="margin-bottom: 20px">
360
+ // Create authenticated client
361
+ const client = new TotpAuthClient({
362
+ secret: 'JBSWY3DPEHPK3PXP',
363
+ digits: 6,
364
+ step: 30
365
+ });
366
+
367
+ // Make authenticated requests
368
+ const users = await client.get('/api/v1/ldap/users');
369
+ const userData = await users.json();
370
+
371
+ // POST with automatic authentication
372
+ await client.post('/api/v1/ldap/users', {
373
+ uid: 'user1',
374
+ mail: 'user1@example.com'
375
+ });
376
+
377
+ // Other methods: put, patch, delete
378
+ await client.put('/api/v1/ldap/users/user1', { mail: 'new@example.com' });
379
+ await client.delete('/api/v1/ldap/users/user1');</div>
380
+
381
+ <h3>Helper Functions</h3>
382
+ <div class="api-response">
383
+ import { getRemainingSeconds, isValidBase32 } from 'ldap-rest/browser-shared-utils-totp';
384
+
385
+ // Check how much time until next code
386
+ const remaining = getRemainingSeconds(30);
387
+ console.log(`Code expires in ${remaining} seconds`);
388
+
389
+ // Validate Base32 secret
390
+ if (isValidBase32('JBSWY3DPEHPK3PXP')) {
391
+ console.log('Valid secret!');
392
+ }</div>
393
+ </div>
394
+ </div>
395
+
396
+ <script type="module">
397
+ import {
398
+ generateTotp,
399
+ TotpAuthClient,
400
+ getRemainingSeconds,
401
+ isValidBase32,
402
+ } from '/static/browser/shared/utils/totp.js';
403
+ import { showStatus } from '/static/browser/shared/components/StatusMessage.js';
404
+
405
+ const secretInput = document.getElementById('secret-input');
406
+ const digitsInput = document.getElementById('digits-input');
407
+ const stepInput = document.getElementById('step-input');
408
+ const totpCodeEl = document.getElementById('totp-code');
409
+ const countdownBar = document.getElementById('countdown-bar');
410
+ const countdownText = document.getElementById('countdown-text');
411
+ const btnGenerate = document.getElementById('btn-generate');
412
+ const btnCopy = document.getElementById('btn-copy');
413
+ const btnTestApi = document.getElementById('btn-test-api');
414
+ const apiEndpoint = document.getElementById('api-endpoint');
415
+ const apiResponseContainer = document.getElementById(
416
+ 'api-response-container'
417
+ );
418
+ const apiResponse = document.getElementById('api-response');
419
+
420
+ let intervalId = null;
421
+ let currentCode = '';
422
+
423
+ async function updateTotpCode() {
424
+ const secret = secretInput.value.trim().toUpperCase();
425
+ const digits = parseInt(digitsInput.value);
426
+ const step = parseInt(stepInput.value);
427
+
428
+ if (!secret) {
429
+ showStatus('error', 'Please enter a Base32 secret');
430
+ return;
431
+ }
432
+
433
+ if (!isValidBase32(secret)) {
434
+ showStatus('error', 'Invalid Base32 secret (use A-Z and 2-7)');
435
+ totpCodeEl.textContent = 'ERROR';
436
+ totpCodeEl.classList.add('expired');
437
+ return;
438
+ }
439
+
440
+ try {
441
+ const code = await generateTotp({ secret, digits, step });
442
+ currentCode = code;
443
+ totpCodeEl.textContent = code;
444
+ totpCodeEl.classList.remove('expired');
445
+
446
+ // Update countdown
447
+ const remaining = getRemainingSeconds(step);
448
+ const percentage = (remaining / step) * 100;
449
+ countdownBar.style.width = `${percentage}%`;
450
+ countdownText.textContent = `Expires in ${remaining} seconds`;
451
+
452
+ // Mark as expired if less than 3 seconds
453
+ if (remaining <= 3) {
454
+ totpCodeEl.classList.add('expired');
455
+ }
456
+ } catch (error) {
457
+ showStatus('error', `Error generating code: ${error.message}`);
458
+ totpCodeEl.textContent = 'ERROR';
459
+ totpCodeEl.classList.add('expired');
460
+ }
461
+ }
462
+
463
+ function startAutoRefresh() {
464
+ if (intervalId) {
465
+ clearInterval(intervalId);
466
+ }
467
+
468
+ updateTotpCode();
469
+ intervalId = setInterval(updateTotpCode, 1000);
470
+ }
471
+
472
+ btnGenerate.addEventListener('click', () => {
473
+ startAutoRefresh();
474
+ showStatus('success', 'TOTP code generated and auto-refresh started');
475
+ });
476
+
477
+ btnCopy.addEventListener('click', async () => {
478
+ if (currentCode && currentCode !== '------' && currentCode !== 'ERROR') {
479
+ try {
480
+ await navigator.clipboard.writeText(currentCode);
481
+ showStatus('success', `Code ${currentCode} copied to clipboard!`);
482
+ } catch (error) {
483
+ showStatus('error', 'Failed to copy to clipboard');
484
+ }
485
+ } else {
486
+ showStatus('error', 'No valid code to copy');
487
+ }
488
+ });
489
+
490
+ btnTestApi.addEventListener('click', async () => {
491
+ const secret = secretInput.value.trim().toUpperCase();
492
+ const digits = parseInt(digitsInput.value);
493
+ const step = parseInt(stepInput.value);
494
+ const endpoint = apiEndpoint.value;
495
+
496
+ if (!secret) {
497
+ showStatus('error', 'Please enter a Base32 secret first');
498
+ return;
499
+ }
500
+
501
+ if (!isValidBase32(secret)) {
502
+ showStatus('error', 'Invalid Base32 secret');
503
+ return;
504
+ }
505
+
506
+ try {
507
+ showStatus('info', 'Sending request...');
508
+
509
+ const client = new TotpAuthClient({ secret, digits, step });
510
+ const response = await client.get(endpoint);
511
+
512
+ apiResponseContainer.style.display = 'block';
513
+
514
+ const data = await response.json();
515
+ apiResponse.textContent = JSON.stringify(data, null, 2);
516
+ apiResponse.classList.remove('error');
517
+
518
+ if (response.ok) {
519
+ showStatus('success', `API request successful (${response.status})`);
520
+ } else {
521
+ showStatus('warning', `API returned status ${response.status}`);
522
+ apiResponse.classList.add('error');
523
+ }
524
+ } catch (error) {
525
+ apiResponseContainer.style.display = 'block';
526
+ apiResponse.textContent = `Error: ${error.message}`;
527
+ apiResponse.classList.add('error');
528
+ showStatus('error', `Request failed: ${error.message}`);
529
+ }
530
+ });
531
+
532
+ // Auto-start on load
533
+ startAutoRefresh();
534
+
535
+ // Clean up on page unload
536
+ window.addEventListener('beforeunload', () => {
537
+ if (intervalId) {
538
+ clearInterval(intervalId);
539
+ }
540
+ });
541
+ </script>
542
+ </body>
543
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ldap-rest",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "Light directory manager",
5
5
  "keywords": [
6
6
  "Identity-Manager"
@@ -40,6 +40,10 @@
40
40
  "import": "./dist/plugins/auth/crowdsec.js",
41
41
  "types": "./dist/src/plugins/auth/crowdsec.d.ts"
42
42
  },
43
+ "plugin-auth-hmac": {
44
+ "import": "./dist/plugins/auth/hmac.js",
45
+ "types": "./dist/src/plugins/auth/hmac.d.ts"
46
+ },
43
47
  "plugin-auth-llng": {
44
48
  "import": "./dist/plugins/auth/llng.js",
45
49
  "types": "./dist/src/plugins/auth/llng.d.ts"
@@ -56,6 +60,10 @@
56
60
  "import": "./dist/plugins/auth/token.js",
57
61
  "types": "./dist/src/plugins/auth/token.d.ts"
58
62
  },
63
+ "plugin-auth-totp": {
64
+ "import": "./dist/plugins/auth/totp.js",
65
+ "types": "./dist/src/plugins/auth/totp.d.ts"
66
+ },
59
67
  "plugin-configapi": {
60
68
  "import": "./dist/plugins/configApi.js",
61
69
  "types": "./dist/src/plugins/configApi.d.ts"
@@ -100,6 +108,14 @@
100
108
  "import": "./dist/plugins/static.js",
101
109
  "types": "./dist/src/plugins/static.d.ts"
102
110
  },
111
+ "plugin-twake-appaccountsapi": {
112
+ "import": "./dist/plugins/twake/appAccountsApi.js",
113
+ "types": "./dist/src/plugins/twake/appAccountsApi.d.ts"
114
+ },
115
+ "plugin-twake-appaccountsconsistency": {
116
+ "import": "./dist/plugins/twake/appAccountsConsistency.js",
117
+ "types": "./dist/src/plugins/twake/appAccountsConsistency.d.ts"
118
+ },
103
119
  "plugin-twake-calendarresources": {
104
120
  "import": "./dist/plugins/twake/calendarResources.js",
105
121
  "types": "./dist/src/plugins/twake/calendarResources.d.ts"
@@ -112,6 +128,18 @@
112
128
  "import": "./dist/plugins/weblogs.js",
113
129
  "types": "./dist/src/plugins/weblogs.d.ts"
114
130
  },
131
+ "abstract-ldapflat": {
132
+ "import": "./dist/abstract/ldapFlat.js",
133
+ "types": "./dist/src/abstract/ldapFlat.d.ts"
134
+ },
135
+ "abstract-plugin": {
136
+ "import": "./dist/abstract/plugin.js",
137
+ "types": "./dist/src/abstract/plugin.d.ts"
138
+ },
139
+ "abstract-twakeplugin": {
140
+ "import": "./dist/abstract/twakePlugin.js",
141
+ "types": "./dist/src/abstract/twakePlugin.d.ts"
142
+ },
115
143
  "browser-ldap-group-editor-ldapgroupeditor": {
116
144
  "import": "./static/browser/ldap-group-editor/LdapGroupEditor.js",
117
145
  "types": "./dist/src/browser/ldap-group-editor/LdapGroupEditor.d.ts"
@@ -288,10 +316,18 @@
288
316
  "import": "./static/browser/shared/utils/form.js",
289
317
  "types": "./dist/src/browser/shared/utils/form.d.ts"
290
318
  },
319
+ "browser-shared-utils-hmac": {
320
+ "import": "./static/browser/shared/utils/hmac.js",
321
+ "types": "./dist/src/browser/shared/utils/hmac.d.ts"
322
+ },
291
323
  "browser-shared-utils-schema": {
292
324
  "import": "./static/browser/shared/utils/schema.js",
293
325
  "types": "./dist/src/browser/shared/utils/schema.d.ts"
294
326
  },
327
+ "browser-shared-utils-totp": {
328
+ "import": "./static/browser/shared/utils/totp.js",
329
+ "types": "./dist/src/browser/shared/utils/totp.d.ts"
330
+ },
295
331
  "schema-ad-computers": {
296
332
  "import": "./static/schemas/ad/computers.json",
297
333
  "require": "./static/schemas/ad/computers.json"
@@ -308,6 +344,14 @@
308
344
  "import": "./static/schemas/ad/users.json",
309
345
  "require": "./static/schemas/ad/users.json"
310
346
  },
347
+ "schema-obm-organizations": {
348
+ "import": "./static/schemas/obm/organizations.json",
349
+ "require": "./static/schemas/obm/organizations.json"
350
+ },
351
+ "schema-obm-users": {
352
+ "import": "./static/schemas/obm/users.json",
353
+ "require": "./static/schemas/obm/users.json"
354
+ },
311
355
  "schema-standard-devices": {
312
356
  "import": "./static/schemas/standard/devices.json",
313
357
  "require": "./static/schemas/standard/devices.json"
@@ -369,6 +413,7 @@
369
413
  "bin": {
370
414
  "cleanup-external-users": "bin/cleanup-external-users.mjs",
371
415
  "ldap-rest": "bin/index.mjs",
416
+ "sync-app-accounts": "bin/sync-app-accounts.mjs",
372
417
  "sync-james": "bin/sync-james.mjs"
373
418
  },
374
419
  "files": [
@@ -1,6 +1,7 @@
1
1
  export { createElement, escapeHtml, getElementByIdSafe, querySelectorAllSafe, querySelectorSafe, setInnerHTML, toTitleCase } from './utils/dom.js';
2
2
  export { collectPointerArrayValues, generateFormField, getFieldLabel, groupSchemaFields, processFormData } from './utils/form.js';
3
3
  export { clearPointerOptionsCache, getOrganizationPath, loadPointerOptions, loadSchema, replacePlaceholders, replaceSchemaPlaceholders } from './utils/schema.js';
4
+ export { TotpAuthClient, generateTotp, getRemainingSeconds, isValidBase32 } from './utils/totp.js';
4
5
  export { Modal } from './components/Modal.js';
5
6
  export { StatusMessage, showStatus } from './components/StatusMessage.js';
6
7
  export { THEMES } from './types/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}