ldap-rest 0.3.0 → 0.3.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.
@@ -11,6 +11,184 @@
11
11
  */
12
12
  import type { Express } from 'express';
13
13
  import DmPlugin, { type Role } from '../../abstract/plugin';
14
+ /**
15
+ * Shared OpenAPI schemas surfaced by this plugin. Picked up by
16
+ * scripts/generate-openapi.ts and merged into `components.schemas`.
17
+ *
18
+ * @openapi-component
19
+ * PasswordPolicy:
20
+ * type: object
21
+ * description: |
22
+ * Active OpenLDAP ppolicy configuration. All duration fields are in
23
+ * **seconds**. Absent fields mean the policy attribute is not set.
24
+ * properties:
25
+ * dn:
26
+ * type: string
27
+ * description: DN of the ppolicy entry.
28
+ * example: cn=default,ou=policies,dc=example,dc=com
29
+ * pwdMaxAge:
30
+ * type: integer
31
+ * description: Maximum password age in seconds (0 = never expires).
32
+ * example: 7776000
33
+ * pwdMinAge:
34
+ * type: integer
35
+ * description: Minimum password age in seconds before it may be changed.
36
+ * example: 0
37
+ * pwdInHistory:
38
+ * type: integer
39
+ * description: Number of previous passwords stored.
40
+ * example: 5
41
+ * pwdCheckQuality:
42
+ * type: integer
43
+ * description: Password quality enforcement level (0-2).
44
+ * example: 1
45
+ * pwdMinLength:
46
+ * type: integer
47
+ * description: Minimum password length.
48
+ * example: 12
49
+ * pwdMaxFailure:
50
+ * type: integer
51
+ * description: Maximum bind failures before lockout.
52
+ * example: 5
53
+ * pwdLockout:
54
+ * type: boolean
55
+ * description: Whether account lockout is enabled.
56
+ * example: true
57
+ * pwdLockoutDuration:
58
+ * type: integer
59
+ * description: Lockout duration in seconds (0 = permanent until admin reset).
60
+ * example: 300
61
+ * pwdGraceAuthNLimit:
62
+ * type: integer
63
+ * description: Number of grace logins allowed after password expires.
64
+ * example: 0
65
+ * pwdExpireWarning:
66
+ * type: integer
67
+ * description: Seconds before expiry at which a warning is issued.
68
+ * example: 1209600
69
+ * pwdMustChange:
70
+ * type: boolean
71
+ * description: If true, users must change their password after an admin reset.
72
+ * example: true
73
+ * pwdAllowUserChange:
74
+ * type: boolean
75
+ * description: Whether users are allowed to change their own password.
76
+ * example: true
77
+ * PasswordStatus:
78
+ * type: object
79
+ * description: Current password status for a specific user account.
80
+ * required: [dn, passwordSet, isExpired, isExpiringSoon, mustChange, isLocked, failureCount, graceLoginsUsed]
81
+ * properties:
82
+ * dn:
83
+ * type: string
84
+ * description: Fully-qualified DN of the user.
85
+ * example: uid=alice,ou=users,dc=example,dc=com
86
+ * passwordSet:
87
+ * type: boolean
88
+ * description: Whether a userPassword attribute is present.
89
+ * example: true
90
+ * lastChanged:
91
+ * type: string
92
+ * format: date-time
93
+ * nullable: true
94
+ * description: ISO-8601 timestamp of last password change, or null if never set.
95
+ * example: '2026-01-15T10:00:00.000Z'
96
+ * expiresAt:
97
+ * type: string
98
+ * format: date-time
99
+ * nullable: true
100
+ * description: ISO-8601 expiry timestamp, or null if no max age is configured.
101
+ * example: '2026-04-15T10:00:00.000Z'
102
+ * daysUntilExpiration:
103
+ * type: integer
104
+ * nullable: true
105
+ * description: Remaining days until expiry (negative means already expired).
106
+ * example: 80
107
+ * isExpired:
108
+ * type: boolean
109
+ * example: false
110
+ * isExpiringSoon:
111
+ * type: boolean
112
+ * description: True when expiry is within the configured warning window.
113
+ * example: false
114
+ * mustChange:
115
+ * type: boolean
116
+ * description: True when `pwdReset` is set (admin forced change).
117
+ * example: false
118
+ * isLocked:
119
+ * type: boolean
120
+ * description: True when the account is currently locked.
121
+ * example: false
122
+ * lockedAt:
123
+ * type: string
124
+ * format: date-time
125
+ * nullable: true
126
+ * description: ISO-8601 timestamp of lockout, or null.
127
+ * example: null
128
+ * failureCount:
129
+ * type: integer
130
+ * description: Number of recorded bind failures still within the window.
131
+ * example: 0
132
+ * graceLoginsUsed:
133
+ * type: integer
134
+ * description: Number of grace logins already consumed.
135
+ * example: 0
136
+ * ExpiringAccount:
137
+ * type: object
138
+ * description: User whose password is expiring within the warning window.
139
+ * required: [dn, expiresAt, daysUntilExpiration]
140
+ * properties:
141
+ * dn: { type: string, example: uid=bob,ou=users,dc=example,dc=com }
142
+ * uid: { type: string, example: bob }
143
+ * displayName: { type: string, example: Bob Builder }
144
+ * mail: { type: string, example: bob@example.com }
145
+ * expiresAt:
146
+ * type: string
147
+ * format: date-time
148
+ * example: '2026-05-01T08:00:00.000Z'
149
+ * daysUntilExpiration: { type: integer, example: 6 }
150
+ * LockedAccount:
151
+ * type: object
152
+ * description: User account that is currently locked.
153
+ * required: [dn, failureCount]
154
+ * properties:
155
+ * dn: { type: string, example: uid=charlie,ou=users,dc=example,dc=com }
156
+ * uid: { type: string, example: charlie }
157
+ * displayName: { type: string, example: Charlie Chaplin }
158
+ * mail: { type: string, example: charlie@example.com }
159
+ * lockedAt:
160
+ * type: string
161
+ * format: date-time
162
+ * nullable: true
163
+ * example: '2026-04-24T14:30:00.000Z'
164
+ * failureCount: { type: integer, example: 5 }
165
+ * PasswordValidationRequest:
166
+ * type: object
167
+ * required: [password]
168
+ * properties:
169
+ * password:
170
+ * type: string
171
+ * format: password
172
+ * description: The candidate password to validate.
173
+ * example: 'S3cur3P@ss!'
174
+ * dn:
175
+ * type: string
176
+ * description: Optional user DN for context (not used in local validation).
177
+ * example: uid=alice,ou=users,dc=example,dc=com
178
+ * PasswordValidationResponse:
179
+ * type: object
180
+ * required: [valid, errors]
181
+ * properties:
182
+ * valid:
183
+ * type: boolean
184
+ * description: True when the password meets all complexity rules.
185
+ * example: true
186
+ * errors:
187
+ * type: array
188
+ * items: { type: string }
189
+ * description: List of failed rule descriptions (empty when valid).
190
+ * example: []
191
+ */
14
192
  export default class PasswordPolicy extends DmPlugin {
15
193
  name: string;
16
194
  roles: Role[];
@@ -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[];