ldap-rest 0.3.0 → 0.3.2
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.
- package/README.md +1 -1
- package/dist/config/args.js +1 -1
- package/dist/lib/expressFormatedResponses.js +1 -1
- package/dist/plugins/auth/authzPerRoute.js +1 -0
- package/dist/plugins/ldap/organization.js +1 -1
- package/dist/plugins/ldap/organizations.js +1 -0
- package/dist/plugins/priority.json.js +1 -1
- package/dist/plugins/twake/cozyProvision.js +1 -0
- package/dist/src/abstract/ldapFlat.d.ts +107 -0
- package/dist/src/config/args.d.ts +10 -0
- package/dist/src/plugins/auth/authzPerRoute.d.ts +22 -0
- package/dist/src/plugins/configApi.d.ts +51 -0
- package/dist/src/plugins/demo/helloworld.d.ts +21 -0
- package/dist/src/plugins/ldap/bulkImport.d.ts +65 -0
- package/dist/src/plugins/ldap/groups.d.ts +68 -0
- package/dist/src/plugins/ldap/organization.d.ts +8 -65
- package/dist/src/plugins/ldap/organizations.d.ts +155 -0
- package/dist/src/plugins/ldap/passwordPolicy.d.ts +178 -0
- package/dist/src/plugins/scim/scim.d.ts +389 -0
- package/dist/src/plugins/static.d.ts +33 -0
- package/dist/src/plugins/twake/appAccountsApi.d.ts +63 -0
- package/dist/src/plugins/twake/cozyProvision.d.ts +54 -0
- package/dist/src/plugins/twake/james.d.ts +47 -0
- package/docs/plugin-development/README.md +2 -1
- package/docs/plugin-development/openapi.md +144 -0
- package/docs/usage/configuration.md +7 -0
- package/docs/usage/plugins/auth/README.md +1 -0
- package/docs/usage/plugins/auth/authz-per-route.md +144 -0
- package/package.json +17 -1
|
@@ -3,6 +3,395 @@ import DmPlugin, { type Role } from '../../abstract/plugin';
|
|
|
3
3
|
import type { DM } from '../../bin';
|
|
4
4
|
import type ldapActions from '../../lib/ldapActions';
|
|
5
5
|
import { writeScimErrorFromException } from './errors';
|
|
6
|
+
/**
|
|
7
|
+
* Reusable SCIM 2.0 schemas surfaced by this plugin.
|
|
8
|
+
* Picked up by scripts/generate-openapi.ts and merged into `components.schemas`.
|
|
9
|
+
*
|
|
10
|
+
* @openapi-component
|
|
11
|
+
* ScimUser:
|
|
12
|
+
* type: object
|
|
13
|
+
* description: |
|
|
14
|
+
* SCIM 2.0 User resource (RFC 7643 §4.1).
|
|
15
|
+
* required: [schemas, userName]
|
|
16
|
+
* properties:
|
|
17
|
+
* schemas:
|
|
18
|
+
* type: array
|
|
19
|
+
* items: { type: string }
|
|
20
|
+
* example: ['urn:ietf:params:scim:schemas:core:2.0:User']
|
|
21
|
+
* id:
|
|
22
|
+
* type: string
|
|
23
|
+
* description: Opaque server-assigned identifier.
|
|
24
|
+
* example: 2819c223-7f76-453a-919d-413861904646
|
|
25
|
+
* externalId:
|
|
26
|
+
* type: string
|
|
27
|
+
* description: Provisioner-assigned identifier.
|
|
28
|
+
* example: 701984
|
|
29
|
+
* userName:
|
|
30
|
+
* type: string
|
|
31
|
+
* description: Unique user identifier (login name).
|
|
32
|
+
* example: bjensen
|
|
33
|
+
* name:
|
|
34
|
+
* type: object
|
|
35
|
+
* properties:
|
|
36
|
+
* formatted: { type: string, example: Ms. Barbara J Jensen III }
|
|
37
|
+
* familyName: { type: string, example: Jensen }
|
|
38
|
+
* givenName: { type: string, example: Barbara }
|
|
39
|
+
* middleName: { type: string, example: Jane }
|
|
40
|
+
* honorificPrefix: { type: string, example: Ms. }
|
|
41
|
+
* honorificSuffix: { type: string, example: III }
|
|
42
|
+
* displayName:
|
|
43
|
+
* type: string
|
|
44
|
+
* example: Babs Jensen
|
|
45
|
+
* nickName:
|
|
46
|
+
* type: string
|
|
47
|
+
* example: Babs
|
|
48
|
+
* profileUrl:
|
|
49
|
+
* type: string
|
|
50
|
+
* example: https://login.example.com/bjensen
|
|
51
|
+
* title:
|
|
52
|
+
* type: string
|
|
53
|
+
* example: Tour Guide
|
|
54
|
+
* userType:
|
|
55
|
+
* type: string
|
|
56
|
+
* example: Employee
|
|
57
|
+
* preferredLanguage:
|
|
58
|
+
* type: string
|
|
59
|
+
* example: en-US
|
|
60
|
+
* locale:
|
|
61
|
+
* type: string
|
|
62
|
+
* example: en-US
|
|
63
|
+
* timezone:
|
|
64
|
+
* type: string
|
|
65
|
+
* example: America/Los_Angeles
|
|
66
|
+
* active:
|
|
67
|
+
* type: boolean
|
|
68
|
+
* example: true
|
|
69
|
+
* emails:
|
|
70
|
+
* type: array
|
|
71
|
+
* items:
|
|
72
|
+
* type: object
|
|
73
|
+
* properties:
|
|
74
|
+
* value: { type: string }
|
|
75
|
+
* display: { type: string }
|
|
76
|
+
* type: { type: string }
|
|
77
|
+
* primary: { type: boolean }
|
|
78
|
+
* example:
|
|
79
|
+
* - value: bjensen@example.com
|
|
80
|
+
* type: work
|
|
81
|
+
* primary: true
|
|
82
|
+
* phoneNumbers:
|
|
83
|
+
* type: array
|
|
84
|
+
* items:
|
|
85
|
+
* type: object
|
|
86
|
+
* properties:
|
|
87
|
+
* value: { type: string }
|
|
88
|
+
* type: { type: string }
|
|
89
|
+
* primary: { type: boolean }
|
|
90
|
+
* addresses:
|
|
91
|
+
* type: array
|
|
92
|
+
* items:
|
|
93
|
+
* type: object
|
|
94
|
+
* properties:
|
|
95
|
+
* streetAddress: { type: string }
|
|
96
|
+
* locality: { type: string }
|
|
97
|
+
* region: { type: string }
|
|
98
|
+
* postalCode: { type: string }
|
|
99
|
+
* country: { type: string }
|
|
100
|
+
* type: { type: string }
|
|
101
|
+
* primary: { type: boolean }
|
|
102
|
+
* groups:
|
|
103
|
+
* type: array
|
|
104
|
+
* description: Groups the user belongs to (read-only).
|
|
105
|
+
* items:
|
|
106
|
+
* type: object
|
|
107
|
+
* properties:
|
|
108
|
+
* value: { type: string }
|
|
109
|
+
* $ref: { type: string }
|
|
110
|
+
* display: { type: string }
|
|
111
|
+
* meta:
|
|
112
|
+
* type: object
|
|
113
|
+
* properties:
|
|
114
|
+
* resourceType: { type: string, example: User }
|
|
115
|
+
* created: { type: string, format: date-time }
|
|
116
|
+
* lastModified: { type: string, format: date-time }
|
|
117
|
+
* location: { type: string }
|
|
118
|
+
* version: { type: string }
|
|
119
|
+
* ScimGroup:
|
|
120
|
+
* type: object
|
|
121
|
+
* description: |
|
|
122
|
+
* SCIM 2.0 Group resource (RFC 7643 §4.2).
|
|
123
|
+
* required: [schemas, displayName]
|
|
124
|
+
* properties:
|
|
125
|
+
* schemas:
|
|
126
|
+
* type: array
|
|
127
|
+
* items: { type: string }
|
|
128
|
+
* example: ['urn:ietf:params:scim:schemas:core:2.0:Group']
|
|
129
|
+
* id:
|
|
130
|
+
* type: string
|
|
131
|
+
* description: Opaque server-assigned identifier.
|
|
132
|
+
* example: e9e30dba-f08f-4109-8486-d5c6a331660a
|
|
133
|
+
* externalId:
|
|
134
|
+
* type: string
|
|
135
|
+
* example: 00g1emaKYZTWRINFRGETl
|
|
136
|
+
* displayName:
|
|
137
|
+
* type: string
|
|
138
|
+
* example: Tour Guides
|
|
139
|
+
* members:
|
|
140
|
+
* type: array
|
|
141
|
+
* description: Members of the group.
|
|
142
|
+
* items:
|
|
143
|
+
* type: object
|
|
144
|
+
* properties:
|
|
145
|
+
* value: { type: string, description: User or Group id }
|
|
146
|
+
* $ref: { type: string }
|
|
147
|
+
* display: { type: string }
|
|
148
|
+
* example:
|
|
149
|
+
* - value: 2819c223-7f76-453a-919d-413861904646
|
|
150
|
+
* display: Babs Jensen
|
|
151
|
+
* - value: 902c246b-6245-4190-8e05-00816be7344a
|
|
152
|
+
* display: Mandy Pepperidge
|
|
153
|
+
* meta:
|
|
154
|
+
* type: object
|
|
155
|
+
* properties:
|
|
156
|
+
* resourceType: { type: string, example: Group }
|
|
157
|
+
* created: { type: string, format: date-time }
|
|
158
|
+
* lastModified: { type: string, format: date-time }
|
|
159
|
+
* location: { type: string }
|
|
160
|
+
* version: { type: string }
|
|
161
|
+
* ScimListResponse:
|
|
162
|
+
* type: object
|
|
163
|
+
* description: |
|
|
164
|
+
* SCIM 2.0 list query response (urn:ietf:params:scim:api:messages:2.0:ListResponse).
|
|
165
|
+
* required: [schemas, totalResults, Resources]
|
|
166
|
+
* properties:
|
|
167
|
+
* schemas:
|
|
168
|
+
* type: array
|
|
169
|
+
* items: { type: string }
|
|
170
|
+
* example: ['urn:ietf:params:scim:api:messages:2.0:ListResponse']
|
|
171
|
+
* totalResults:
|
|
172
|
+
* type: integer
|
|
173
|
+
* description: Total number of matching resources.
|
|
174
|
+
* example: 2
|
|
175
|
+
* startIndex:
|
|
176
|
+
* type: integer
|
|
177
|
+
* description: 1-based index of the first result returned.
|
|
178
|
+
* example: 1
|
|
179
|
+
* itemsPerPage:
|
|
180
|
+
* type: integer
|
|
181
|
+
* description: Number of resources returned in this page.
|
|
182
|
+
* example: 2
|
|
183
|
+
* Resources:
|
|
184
|
+
* type: array
|
|
185
|
+
* items: {}
|
|
186
|
+
* description: The matching resources.
|
|
187
|
+
* ScimError:
|
|
188
|
+
* type: object
|
|
189
|
+
* description: |
|
|
190
|
+
* SCIM 2.0 error response (urn:ietf:params:scim:api:messages:2.0:Error).
|
|
191
|
+
* required: [schemas, status]
|
|
192
|
+
* properties:
|
|
193
|
+
* schemas:
|
|
194
|
+
* type: array
|
|
195
|
+
* items: { type: string }
|
|
196
|
+
* example: ['urn:ietf:params:scim:api:messages:2.0:Error']
|
|
197
|
+
* status:
|
|
198
|
+
* type: string
|
|
199
|
+
* description: HTTP status code as a string.
|
|
200
|
+
* example: '404'
|
|
201
|
+
* scimType:
|
|
202
|
+
* type: string
|
|
203
|
+
* description: |
|
|
204
|
+
* SCIM error type keyword (RFC 7644 §3.12). One of: invalidFilter,
|
|
205
|
+
* tooMany, uniqueness, mutability, invalidSyntax, invalidPath,
|
|
206
|
+
* noTarget, invalidValue, invalidVers, sensitive.
|
|
207
|
+
* example: mutability
|
|
208
|
+
* detail:
|
|
209
|
+
* type: string
|
|
210
|
+
* description: Human-readable error description.
|
|
211
|
+
* example: Resource 2819c223-7f76-453a-919d-413861904646 not found.
|
|
212
|
+
* example:
|
|
213
|
+
* schemas: ['urn:ietf:params:scim:api:messages:2.0:Error']
|
|
214
|
+
* status: '404'
|
|
215
|
+
* detail: Resource 2819c223-7f76-453a-919d-413861904646 not found.
|
|
216
|
+
* ScimPatchOp:
|
|
217
|
+
* type: object
|
|
218
|
+
* description: |
|
|
219
|
+
* SCIM 2.0 patch request body (urn:ietf:params:scim:api:messages:2.0:PatchOp,
|
|
220
|
+
* RFC 7644 §3.5.2).
|
|
221
|
+
* required: [schemas, Operations]
|
|
222
|
+
* properties:
|
|
223
|
+
* schemas:
|
|
224
|
+
* type: array
|
|
225
|
+
* items: { type: string }
|
|
226
|
+
* example: ['urn:ietf:params:scim:api:messages:2.0:PatchOp']
|
|
227
|
+
* Operations:
|
|
228
|
+
* type: array
|
|
229
|
+
* items:
|
|
230
|
+
* type: object
|
|
231
|
+
* required: [op]
|
|
232
|
+
* properties:
|
|
233
|
+
* op:
|
|
234
|
+
* type: string
|
|
235
|
+
* enum: [add, remove, replace, Add, Remove, Replace]
|
|
236
|
+
* path:
|
|
237
|
+
* type: string
|
|
238
|
+
* description: SCIM attribute path (e.g. "emails[type eq \"work\"].value").
|
|
239
|
+
* value:
|
|
240
|
+
* description: New value for the target attribute.
|
|
241
|
+
* example:
|
|
242
|
+
* schemas: ['urn:ietf:params:scim:api:messages:2.0:PatchOp']
|
|
243
|
+
* Operations:
|
|
244
|
+
* - op: replace
|
|
245
|
+
* path: active
|
|
246
|
+
* value: false
|
|
247
|
+
* - op: replace
|
|
248
|
+
* path: emails[type eq "work"].value
|
|
249
|
+
* value: bjensen@newdomain.example.com
|
|
250
|
+
* ScimBulkRequest:
|
|
251
|
+
* type: object
|
|
252
|
+
* description: |
|
|
253
|
+
* SCIM 2.0 Bulk request (urn:ietf:params:scim:api:messages:2.0:BulkRequest,
|
|
254
|
+
* RFC 7644 §3.7).
|
|
255
|
+
* required: [schemas, Operations]
|
|
256
|
+
* properties:
|
|
257
|
+
* schemas:
|
|
258
|
+
* type: array
|
|
259
|
+
* items: { type: string }
|
|
260
|
+
* example: ['urn:ietf:params:scim:api:messages:2.0:BulkRequest']
|
|
261
|
+
* failOnErrors:
|
|
262
|
+
* type: integer
|
|
263
|
+
* description: |
|
|
264
|
+
* Stop processing after this many errors. Omit or set to 0 to
|
|
265
|
+
* continue on errors and process all operations.
|
|
266
|
+
* example: 1
|
|
267
|
+
* Operations:
|
|
268
|
+
* type: array
|
|
269
|
+
* items:
|
|
270
|
+
* type: object
|
|
271
|
+
* required: [method, path]
|
|
272
|
+
* properties:
|
|
273
|
+
* method:
|
|
274
|
+
* type: string
|
|
275
|
+
* enum: [POST, PUT, PATCH, DELETE]
|
|
276
|
+
* bulkId:
|
|
277
|
+
* type: string
|
|
278
|
+
* description: |
|
|
279
|
+
* Temporary client-assigned identifier for this operation.
|
|
280
|
+
* Subsequent operations in the same request may reference the
|
|
281
|
+
* created resource as "bulkId:<value>".
|
|
282
|
+
* path:
|
|
283
|
+
* type: string
|
|
284
|
+
* description: Resource path relative to the SCIM prefix (e.g. /Users or /Groups/123).
|
|
285
|
+
* data:
|
|
286
|
+
* description: Request body for POST/PUT/PATCH operations.
|
|
287
|
+
* example:
|
|
288
|
+
* schemas: ['urn:ietf:params:scim:api:messages:2.0:BulkRequest']
|
|
289
|
+
* failOnErrors: 1
|
|
290
|
+
* Operations:
|
|
291
|
+
* - method: POST
|
|
292
|
+
* bulkId: qwerty
|
|
293
|
+
* path: /Users
|
|
294
|
+
* data:
|
|
295
|
+
* schemas: ['urn:ietf:params:scim:schemas:core:2.0:User']
|
|
296
|
+
* userName: bjensen
|
|
297
|
+
* name:
|
|
298
|
+
* familyName: Jensen
|
|
299
|
+
* givenName: Barbara
|
|
300
|
+
* - method: DELETE
|
|
301
|
+
* path: /Users/2819c223-7f76-453a-919d-413861904646
|
|
302
|
+
* ScimBulkResponse:
|
|
303
|
+
* type: object
|
|
304
|
+
* description: |
|
|
305
|
+
* SCIM 2.0 Bulk response (urn:ietf:params:scim:api:messages:2.0:BulkResponse).
|
|
306
|
+
* required: [schemas, Operations]
|
|
307
|
+
* properties:
|
|
308
|
+
* schemas:
|
|
309
|
+
* type: array
|
|
310
|
+
* items: { type: string }
|
|
311
|
+
* example: ['urn:ietf:params:scim:api:messages:2.0:BulkResponse']
|
|
312
|
+
* Operations:
|
|
313
|
+
* type: array
|
|
314
|
+
* items:
|
|
315
|
+
* type: object
|
|
316
|
+
* required: [method, status]
|
|
317
|
+
* properties:
|
|
318
|
+
* method:
|
|
319
|
+
* type: string
|
|
320
|
+
* enum: [POST, PUT, PATCH, DELETE]
|
|
321
|
+
* bulkId:
|
|
322
|
+
* type: string
|
|
323
|
+
* location:
|
|
324
|
+
* type: string
|
|
325
|
+
* description: URL of the created/modified resource.
|
|
326
|
+
* version:
|
|
327
|
+
* type: string
|
|
328
|
+
* status:
|
|
329
|
+
* type: string
|
|
330
|
+
* description: HTTP status code for this individual operation.
|
|
331
|
+
* response:
|
|
332
|
+
* $ref: '#/components/schemas/ScimError'
|
|
333
|
+
* description: Present only when the operation failed.
|
|
334
|
+
* example:
|
|
335
|
+
* schemas: ['urn:ietf:params:scim:api:messages:2.0:BulkResponse']
|
|
336
|
+
* Operations:
|
|
337
|
+
* - method: POST
|
|
338
|
+
* bulkId: qwerty
|
|
339
|
+
* location: https://example.com/scim/v2/Users/2819c223-7f76-453a-919d-413861904646
|
|
340
|
+
* status: '201'
|
|
341
|
+
* - method: DELETE
|
|
342
|
+
* status: '204'
|
|
343
|
+
* ScimResourceType:
|
|
344
|
+
* type: object
|
|
345
|
+
* description: SCIM 2.0 ResourceType definition (RFC 7643 §6).
|
|
346
|
+
* required: [schemas, id, name, endpoint, schema]
|
|
347
|
+
* properties:
|
|
348
|
+
* schemas:
|
|
349
|
+
* type: array
|
|
350
|
+
* items: { type: string }
|
|
351
|
+
* example: ['urn:ietf:params:scim:schemas:core:2.0:ResourceType']
|
|
352
|
+
* id: { type: string, example: User }
|
|
353
|
+
* name: { type: string, example: User }
|
|
354
|
+
* endpoint: { type: string, example: /Users }
|
|
355
|
+
* description: { type: string, example: User Account }
|
|
356
|
+
* schema:
|
|
357
|
+
* type: string
|
|
358
|
+
* example: urn:ietf:params:scim:schemas:core:2.0:User
|
|
359
|
+
* schemaExtensions:
|
|
360
|
+
* type: array
|
|
361
|
+
* items:
|
|
362
|
+
* type: object
|
|
363
|
+
* properties:
|
|
364
|
+
* schema: { type: string }
|
|
365
|
+
* required: { type: boolean }
|
|
366
|
+
* meta:
|
|
367
|
+
* type: object
|
|
368
|
+
* properties:
|
|
369
|
+
* resourceType: { type: string, example: ResourceType }
|
|
370
|
+
* location: { type: string }
|
|
371
|
+
* ScimSchema:
|
|
372
|
+
* type: object
|
|
373
|
+
* description: SCIM 2.0 Schema definition (RFC 7643 §7).
|
|
374
|
+
* required: [schemas, id, name, attributes]
|
|
375
|
+
* properties:
|
|
376
|
+
* schemas:
|
|
377
|
+
* type: array
|
|
378
|
+
* items: { type: string }
|
|
379
|
+
* example: ['urn:ietf:params:scim:schemas:core:2.0:Schema']
|
|
380
|
+
* id:
|
|
381
|
+
* type: string
|
|
382
|
+
* example: urn:ietf:params:scim:schemas:core:2.0:User
|
|
383
|
+
* name: { type: string, example: User }
|
|
384
|
+
* description: { type: string, example: User Account }
|
|
385
|
+
* attributes:
|
|
386
|
+
* type: array
|
|
387
|
+
* items: {}
|
|
388
|
+
* description: Schema attribute definitions.
|
|
389
|
+
* meta:
|
|
390
|
+
* type: object
|
|
391
|
+
* properties:
|
|
392
|
+
* resourceType: { type: string, example: Schema }
|
|
393
|
+
* location: { type: string }
|
|
394
|
+
*/
|
|
6
395
|
export default class Scim extends DmPlugin {
|
|
7
396
|
name: string;
|
|
8
397
|
roles: Role[];
|
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
import type { Express } from 'express';
|
|
2
2
|
import DmPlugin, { type Role } from '../abstract/plugin';
|
|
3
|
+
/**
|
|
4
|
+
* @openapi-component
|
|
5
|
+
* LdapSchema:
|
|
6
|
+
* type: object
|
|
7
|
+
* description: |
|
|
8
|
+
* A JSON schema file served from the `schemas/` sub-directory of the
|
|
9
|
+
* static path. These schemas describe LDAP entity types (users, groups,
|
|
10
|
+
* organizations, …) and are consumed by browser-embedded editors to
|
|
11
|
+
* render attribute forms and validate input before submission.
|
|
12
|
+
*
|
|
13
|
+
* The server replaces `__FOO_BAR__` placeholders on the fly with the
|
|
14
|
+
* value of the corresponding `--foo-bar` CLI option so that a single
|
|
15
|
+
* schema file can be shared between server-side validation and
|
|
16
|
+
* client-side rendering.
|
|
17
|
+
* additionalProperties: true
|
|
18
|
+
* example:
|
|
19
|
+
* entity:
|
|
20
|
+
* name: standardUser
|
|
21
|
+
* mainAttribute: uid
|
|
22
|
+
* objectClass: [top, inetOrgPerson]
|
|
23
|
+
* singularName: user
|
|
24
|
+
* pluralName: users
|
|
25
|
+
* base: ou=users,dc=example,dc=com
|
|
26
|
+
* strict: true
|
|
27
|
+
* attributes:
|
|
28
|
+
* uid:
|
|
29
|
+
* type: string
|
|
30
|
+
* required: true
|
|
31
|
+
* role: identifier
|
|
32
|
+
* cn:
|
|
33
|
+
* type: string
|
|
34
|
+
* required: true
|
|
35
|
+
*/
|
|
3
36
|
export default class Static extends DmPlugin {
|
|
4
37
|
name: string;
|
|
5
38
|
roles: Role[];
|
|
@@ -1,6 +1,69 @@
|
|
|
1
1
|
import type { Express } from 'express';
|
|
2
2
|
import DmPlugin, { type Role } from '../../abstract/plugin';
|
|
3
3
|
import type { DM } from '../../bin';
|
|
4
|
+
/**
|
|
5
|
+
* @openapi-component
|
|
6
|
+
* AppAccount:
|
|
7
|
+
* type: object
|
|
8
|
+
* description: |
|
|
9
|
+
* An application-specific identity attached to a user. App accounts
|
|
10
|
+
* allow a single principal user to authenticate as different named
|
|
11
|
+
* "devices" or "applications" each with its own credential, while
|
|
12
|
+
* sharing the same mail address.
|
|
13
|
+
* required: [uid]
|
|
14
|
+
* properties:
|
|
15
|
+
* uid:
|
|
16
|
+
* type: string
|
|
17
|
+
* description: |
|
|
18
|
+
* Unique identifier of the app account. Format:
|
|
19
|
+
* `<username>_c<8-digits>` (e.g. `alice_c04729183`).
|
|
20
|
+
* example: alice_c04729183
|
|
21
|
+
* name:
|
|
22
|
+
* type: string
|
|
23
|
+
* description: Human-readable label (stored as LDAP `description`).
|
|
24
|
+
* example: Work laptop
|
|
25
|
+
* example:
|
|
26
|
+
* uid: alice_c04729183
|
|
27
|
+
* name: Work laptop
|
|
28
|
+
* AppAccountCreated:
|
|
29
|
+
* type: object
|
|
30
|
+
* description: |
|
|
31
|
+
* Response returned when a new app account is successfully created.
|
|
32
|
+
* The one-time cleartext password is included here and never returned
|
|
33
|
+
* again — callers must store it immediately.
|
|
34
|
+
* required: [uid, pwd, mail]
|
|
35
|
+
* properties:
|
|
36
|
+
* uid:
|
|
37
|
+
* type: string
|
|
38
|
+
* description: Identifier of the newly created app account.
|
|
39
|
+
* example: alice_c04729183
|
|
40
|
+
* pwd:
|
|
41
|
+
* type: string
|
|
42
|
+
* description: |
|
|
43
|
+
* One-time cleartext password generated for this account.
|
|
44
|
+
* Format: 6 blocks of 4 characters separated by `-`
|
|
45
|
+
* (e.g. `Ab3@-xYz!-9pQ#-Sv4$-mN8!-pQ5@`).
|
|
46
|
+
* OpenLDAP hashes it via ppolicy before storage.
|
|
47
|
+
* example: Ab3@-xYz!-9pQ#-Sv4$-mN8!-pQ5@
|
|
48
|
+
* mail:
|
|
49
|
+
* type: string
|
|
50
|
+
* description: Mail address of the principal account this app account belongs to.
|
|
51
|
+
* example: alice@example.com
|
|
52
|
+
* example:
|
|
53
|
+
* uid: alice_c04729183
|
|
54
|
+
* pwd: Ab3@-xYz!-9pQ#-Sv4$-mN8!-pQ5@
|
|
55
|
+
* mail: alice@example.com
|
|
56
|
+
* AppAccountCreate:
|
|
57
|
+
* type: object
|
|
58
|
+
* description: Request body for creating a new app account.
|
|
59
|
+
* properties:
|
|
60
|
+
* name:
|
|
61
|
+
* type: string
|
|
62
|
+
* description: Optional human-readable label for the new account.
|
|
63
|
+
* example: Work laptop
|
|
64
|
+
* example:
|
|
65
|
+
* name: Work laptop
|
|
66
|
+
*/
|
|
4
67
|
export default class AppAccountsApi extends DmPlugin {
|
|
5
68
|
name: string;
|
|
6
69
|
roles: Role[];
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import DmPlugin, { type Role } from '../../abstract/plugin';
|
|
2
|
+
import type { DM } from '../../bin';
|
|
3
|
+
import { Hooks } from '../../hooks';
|
|
4
|
+
interface RabbitPublisher {
|
|
5
|
+
init(): Promise<void>;
|
|
6
|
+
publish(exchange: string, routingKey: string, message: Record<string, unknown>): Promise<void>;
|
|
7
|
+
close(clearSubscriptions?: boolean): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export default class CozyProvision extends DmPlugin {
|
|
10
|
+
name: string;
|
|
11
|
+
roles: Role[];
|
|
12
|
+
private readonly cozyAdminUrl;
|
|
13
|
+
private readonly cozyAdminPassphrase;
|
|
14
|
+
private readonly cozyAdminUser;
|
|
15
|
+
private readonly cozyOrgId;
|
|
16
|
+
private readonly cozyOrgDomain;
|
|
17
|
+
private readonly cozyDefaultLocale;
|
|
18
|
+
private readonly rabbitmqUrl;
|
|
19
|
+
private readonly authExchange;
|
|
20
|
+
private readonly b2bExchange;
|
|
21
|
+
private publisher;
|
|
22
|
+
private publisherInit;
|
|
23
|
+
constructor(server: DM);
|
|
24
|
+
hooks: Hooks;
|
|
25
|
+
/**
|
|
26
|
+
* POST /instances on the cozy-stack admin API. Returns true on success
|
|
27
|
+
* (including 409 idempotent "already exists").
|
|
28
|
+
*/
|
|
29
|
+
private createCozyInstance;
|
|
30
|
+
/**
|
|
31
|
+
* Publish user.created on the `auth` topic exchange. Payload mirrors what
|
|
32
|
+
* cozy-stack expects: a sub identifier, an optional email, and the
|
|
33
|
+
* organizationDomain so consumers can match the instance.
|
|
34
|
+
*/
|
|
35
|
+
private publishUserCreated;
|
|
36
|
+
/**
|
|
37
|
+
* Publish domain.user.deleted on the `b2b` topic exchange so peer cozy
|
|
38
|
+
* instances can drop the deleted user's contact card.
|
|
39
|
+
*/
|
|
40
|
+
private publishUserDeleted;
|
|
41
|
+
/**
|
|
42
|
+
* Lazy-init the AMQP publisher. The `@linagora/rabbitmq-client` dependency
|
|
43
|
+
* is optional — if the package or the broker is unreachable, return null
|
|
44
|
+
* so callers can no-op cleanly.
|
|
45
|
+
*
|
|
46
|
+
* Override this in tests to inject a stub publisher.
|
|
47
|
+
*/
|
|
48
|
+
protected getPublisher(): Promise<RabbitPublisher | null>;
|
|
49
|
+
private extractId;
|
|
50
|
+
private extractPrimaryEmail;
|
|
51
|
+
private extractLocale;
|
|
52
|
+
private registerShutdown;
|
|
53
|
+
}
|
|
54
|
+
export {};
|
|
@@ -5,6 +5,53 @@ import type { DM } from '../../bin';
|
|
|
5
5
|
import type { AttributeValue } from '../../lib/ldapActions';
|
|
6
6
|
import { Hooks } from '../../hooks';
|
|
7
7
|
import type { ChangesToNotify } from '../ldap/onChange';
|
|
8
|
+
/**
|
|
9
|
+
* OpenAPI schemas specific to the James integration.
|
|
10
|
+
*
|
|
11
|
+
* @openapi-component
|
|
12
|
+
* JamesQuotaUsage:
|
|
13
|
+
* type: object
|
|
14
|
+
* description: |
|
|
15
|
+
* Quota information for a mailbox user as returned by the James
|
|
16
|
+
* WebAdmin API (`GET /quota/users/{mail}`). Contains separate
|
|
17
|
+
* counters for message count and storage size.
|
|
18
|
+
* properties:
|
|
19
|
+
* count:
|
|
20
|
+
* type: object
|
|
21
|
+
* description: Message-count quota.
|
|
22
|
+
* properties:
|
|
23
|
+
* used:
|
|
24
|
+
* type: integer
|
|
25
|
+
* description: Number of messages currently stored.
|
|
26
|
+
* example: 142
|
|
27
|
+
* max:
|
|
28
|
+
* type: integer
|
|
29
|
+
* nullable: true
|
|
30
|
+
* description: |
|
|
31
|
+
* Maximum number of messages allowed. `null` means unlimited.
|
|
32
|
+
* example: 10000
|
|
33
|
+
* size:
|
|
34
|
+
* type: object
|
|
35
|
+
* description: Storage-size quota (bytes).
|
|
36
|
+
* properties:
|
|
37
|
+
* used:
|
|
38
|
+
* type: integer
|
|
39
|
+
* description: Bytes currently used.
|
|
40
|
+
* example: 524288000
|
|
41
|
+
* max:
|
|
42
|
+
* type: integer
|
|
43
|
+
* nullable: true
|
|
44
|
+
* description: |
|
|
45
|
+
* Maximum bytes allowed. `null` means unlimited.
|
|
46
|
+
* example: 2147483648
|
|
47
|
+
* example:
|
|
48
|
+
* count:
|
|
49
|
+
* used: 142
|
|
50
|
+
* max: 10000
|
|
51
|
+
* size:
|
|
52
|
+
* used: 524288000
|
|
53
|
+
* max: 2147483648
|
|
54
|
+
*/
|
|
8
55
|
export default class James extends TwakePlugin {
|
|
9
56
|
name: string;
|
|
10
57
|
roles: Role[];
|
|
@@ -13,6 +13,7 @@ This guide will help you create powerful, production-ready plugins for LDAP-Rest
|
|
|
13
13
|
- [Configuration Best Practices](#configuration-best-practices)
|
|
14
14
|
- [Complete Plugin Example](#complete-plugin-example)
|
|
15
15
|
- [Testing Your Plugin](#testing-your-plugin)
|
|
16
|
+
- [Documenting REST endpoints (OpenAPI)](./openapi.md)
|
|
16
17
|
|
|
17
18
|
---
|
|
18
19
|
|
|
@@ -1282,7 +1283,7 @@ source ~/.test-env && npm run test:dev
|
|
|
1282
1283
|
## Additional Resources
|
|
1283
1284
|
|
|
1284
1285
|
- [Contributing Guide](../../CONTRIBUTING.md) - Git workflow and PR guidelines
|
|
1285
|
-
- [Hooks Reference](
|
|
1286
|
+
- [Hooks Reference](./hooks.md) - Complete list of available hooks
|
|
1286
1287
|
- [Core Plugin Examples](../../src/plugins/) - Browse existing plugins
|
|
1287
1288
|
- [Test Examples](../../test/plugins/) - See how core plugins are tested
|
|
1288
1289
|
|