ldap-rest 0.17.1 → 0.18.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/dist/abstract/ldapFlat.js +1 -1
  2. package/dist/config/schema.js +1 -1
  3. package/dist/lib/ldapActions.js +1 -1
  4. package/dist/plugins/ldap/enterpriseRules.js +1 -1
  5. package/dist/plugins/ldap/groups.js +1 -1
  6. package/dist/plugins/ldap/organizations.js +1 -1
  7. package/dist/plugins/twake/james.js +1 -1
  8. package/dist/src/abstract/ldapFlat.d.ts +9 -11
  9. package/dist/src/browser/ldap-group-editor/types.d.ts +2 -1
  10. package/dist/src/browser/ldap-resource-editor/types.d.ts +3 -2
  11. package/dist/src/browser/ldap-unit-editor/types.d.ts +2 -1
  12. package/dist/src/browser/ldap-user-editor/types.d.ts +3 -2
  13. package/dist/src/browser/shared/types/index.d.ts +7 -1
  14. package/dist/src/browser/shared/utils/schema.d.ts +20 -1
  15. package/dist/src/config/schema.d.ts +27 -4
  16. package/dist/src/plugins/ldap/organizations.d.ts +0 -8
  17. package/dist/src/plugins/twake/james.d.ts +11 -74
  18. package/docs/client-development/api/reference.md +1 -1
  19. package/docs/client-development/api/rest-api.md +11 -1
  20. package/docs/client-development/schemas/README.md +18 -13
  21. package/docs/plugin-development/dependencies.md +1 -3
  22. package/docs/presentations/en.md +0 -28
  23. package/docs/presentations/fr.md +0 -28
  24. package/docs/usage/configuration.md +12 -12
  25. package/docs/usage/plugins/integrations/james-mail.md +25 -119
  26. package/docs/usage/plugins/integrations/james-mailboxes.md +58 -78
  27. package/docs/usage/plugins/ldap/flat-generic.md +23 -5
  28. package/docs/usage/plugins/utilities/weblogs.md +1 -1
  29. package/docs/usage/upgrading.md +30 -0
  30. package/package.json +1 -1
  31. package/static/browser/ldap-resource-editor/api/ResourceApiClient.js +2 -1
  32. package/static/browser/ldap-resource-editor/api/ResourceApiClient.js.map +1 -1
  33. package/static/browser/ldap-user-editor/api/UserApiClient.js +2 -1
  34. package/static/browser/ldap-user-editor/api/UserApiClient.js.map +1 -1
  35. package/static/browser/ldap-user-editor/components/UserEditor.js +11 -8
  36. package/static/browser/ldap-user-editor/components/UserEditor.js.map +1 -1
  37. package/static/browser/ldap-user-editor/components/UserList.js +3 -1
  38. package/static/browser/ldap-user-editor/components/UserList.js.map +1 -1
  39. package/static/browser/ldap-user-editor.esm.js +52 -10
  40. package/static/browser/ldap-user-editor.esm.js.map +1 -1
  41. package/static/browser/ldap-user-editor.js +52 -10
  42. package/static/browser/ldap-user-editor.js.map +1 -1
  43. package/static/browser/ldap-user-editor.min.js +1 -1
  44. package/static/browser/ldap-user-editor.min.js.map +1 -1
  45. package/static/browser/shared/index.js +1 -1
  46. package/static/browser/shared/types/index.js.map +1 -1
  47. package/static/browser/shared/utils/form.js +2 -1
  48. package/static/browser/shared/utils/form.js.map +1 -1
  49. package/static/browser/shared/utils/schema.js +33 -1
  50. package/static/browser/shared/utils/schema.js.map +1 -1
  51. package/static/browser/shared.esm.js +153 -121
  52. package/static/browser/shared.esm.js.map +1 -1
  53. package/static/browser/shared.js +154 -120
  54. package/static/browser/shared.js.map +1 -1
  55. package/static/browser/shared.min.js +1 -1
  56. package/static/browser/shared.min.js.map +1 -1
  57. package/static/schemas/standard/groups.json +1 -1
  58. package/static/schemas/twake/groups.json +25 -7
  59. package/static/schemas/twake/nomenclature/twakeAccountStatus.json +10 -2
  60. package/static/schemas/twake/nomenclature/twakeDeliveryMode.json +10 -2
  61. package/static/schemas/twake/nomenclature/twakeDomain.json +9 -3
  62. package/static/schemas/twake/nomenclature/twakeListType.json +10 -2
  63. package/static/schemas/twake/nomenclature/twakeMailboxType.json +10 -2
  64. package/static/schemas/twake/nomenclature/twakeTitle.json +10 -2
  65. package/static/schemas/twake/organizations.json +4 -1
  66. package/static/schemas/twake/positions.json +4 -1
  67. package/static/schemas/twake/users.json +36 -9
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * TypeScript types for LDAP Unit Editor
3
3
  */
4
+ import type { LocalizedText } from '../shared/types';
4
5
  export interface UnitEditorOptions {
5
6
  containerId: string;
6
7
  apiBaseUrl?: string;
@@ -45,7 +46,7 @@ export interface SchemaAttribute {
45
46
  type: string;
46
47
  branch?: string[];
47
48
  };
48
- group?: string;
49
+ group?: LocalizedText;
49
50
  }
50
51
  export interface LdapUnit {
51
52
  dn: string;
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * LDAP User Editor - Type definitions
3
3
  */
4
+ import type { LocalizedText } from '../shared/types';
4
5
  export interface EditorOptions {
5
6
  containerId: string;
6
7
  apiBaseUrl?: string;
@@ -15,13 +16,13 @@ export interface SchemaAttribute {
15
16
  type: string;
16
17
  required?: boolean;
17
18
  fixed?: boolean;
18
- role?: string;
19
+ role?: string | string[];
19
20
  test?: string;
20
21
  branch?: string[];
21
22
  items?: SchemaAttribute;
22
23
  default?: unknown;
23
24
  ui?: 'select' | 'search';
24
- group?: string;
25
+ group?: LocalizedText;
25
26
  }
26
27
  export interface Schema {
27
28
  entity: {
@@ -2,6 +2,11 @@
2
2
  * Shared TypeScript types for browser components
3
3
  * @module browser/shared/types
4
4
  */
5
+ /**
6
+ * Text of a schema in one language (a plain string) or several (a map keyed
7
+ * by language tag), see `localizedText`
8
+ */
9
+ export type LocalizedText = string | Record<string, string>;
5
10
  export interface EditorConfig {
6
11
  ldapBase?: string;
7
12
  features?: {
@@ -27,13 +32,14 @@ export interface SchemaAttribute {
27
32
  type: 'string' | 'number' | 'integer' | 'array' | 'pointer';
28
33
  required?: boolean;
29
34
  fixed?: boolean;
35
+ role?: string | string[];
30
36
  default?: unknown;
31
37
  branch?: string[];
32
38
  items?: {
33
39
  type: string;
34
40
  branch?: string[];
35
41
  };
36
- group?: string;
42
+ group?: LocalizedText;
37
43
  }
38
44
  export interface PointerOption {
39
45
  dn: string;
@@ -2,7 +2,7 @@
2
2
  * Schema utility functions
3
3
  * @module browser/shared/utils/schema
4
4
  */
5
- import type { PointerOption } from '../types';
5
+ import type { LocalizedText, PointerOption, SchemaAttribute } from '../types';
6
6
  /**
7
7
  * Load pointer options from API
8
8
  */
@@ -27,3 +27,22 @@ export declare function getOrganizationPath(orgDn: string, apiBaseUrl: string):
27
27
  * Load schema from URL or object
28
28
  */
29
29
  export declare function loadSchema<T = unknown>(schemaSource: string | T): Promise<T>;
30
+ /**
31
+ * Tell whether an attribute carries a role: a schema names one, or several.
32
+ *
33
+ * @param attr attribute definition
34
+ * @param role role to look for
35
+ * @returns true when the attribute declares that role
36
+ */
37
+ export declare function hasRole(attr: Pick<SchemaAttribute, 'role'> | undefined, role: string): boolean;
38
+ /**
39
+ * Pick the text of a {@link LocalizedText} for a language: the exact tag,
40
+ * then its primary language, then English, then whatever the map holds.
41
+ *
42
+ * The editors are written in English, so English is the default.
43
+ *
44
+ * @param text plain string or map keyed by language tag
45
+ * @param language tag to look for
46
+ * @returns the text, or undefined when there is none
47
+ */
48
+ export declare function localizedText(text: LocalizedText | undefined, language?: string): string | undefined;
@@ -49,6 +49,29 @@ export type SchemaRole = string;
49
49
  * rather than in a catalogue shipped with the code.
50
50
  */
51
51
  export type LocalizedText = string | Record<string, string>;
52
+ /**
53
+ * Pick the text of a {@link LocalizedText} for a language: the exact tag,
54
+ * then its primary language, then English, then whatever the map holds.
55
+ *
56
+ * @param text plain string or map keyed by language tag
57
+ * @param language tag to look for, English when omitted
58
+ * @returns the text, or undefined when there is none
59
+ */
60
+ export declare function localizedText(text: LocalizedText | undefined, language?: string): string | undefined;
61
+ /**
62
+ * Refusal of a value that failed its schema `test`, for a `BadRequestError`.
63
+ *
64
+ * When the schema carries a `hint`, the message says what a valid value
65
+ * looks like instead of only that this one was not. The hint lives next to
66
+ * the pattern so the two cannot drift apart, and so a client can show it
67
+ * under the field *before* the user gets it wrong. Its English text is
68
+ * quoted, the language of every other API message.
69
+ *
70
+ * @param name attribute name
71
+ * @param attr its schema definition
72
+ * @returns the message
73
+ */
74
+ export declare function invalidValueMessage(name: string, attr: SchemaAttribute | undefined): string;
52
75
  /** Roles the core itself looks for. See {@link SchemaRole}. */
53
76
  export declare const CORE_ROLES: readonly ["identifier", "displayName", "primaryEmail", "emailAliases", "emailQuota", "organizationLink", "organizationPath", "members", "owners", "accountStatus", "password", "passwordReset", "accountExpiry", "domainLink", "domainName"];
54
77
  /**
@@ -114,7 +137,7 @@ export interface SchemaAttribute {
114
137
  items?: {
115
138
  type: string;
116
139
  test?: string | RegExp;
117
- hint?: string;
140
+ hint?: LocalizedText;
118
141
  branch?: string[];
119
142
  };
120
143
  default?: AttributeValue;
@@ -126,7 +149,7 @@ export interface SchemaAttribute {
126
149
  * schema so the pattern and its explanation cannot drift apart, and so a
127
150
  * client never has to hardcode either.
128
151
  */
129
- hint?: string;
152
+ hint?: LocalizedText;
130
153
  branch?: string[];
131
154
  fixed?: boolean;
132
155
  /** Semantic role(s) — see {@link SchemaRole} */
@@ -209,8 +232,8 @@ export interface SchemaAttribute {
209
232
  * under `example.org`. Off by default: the domain must match exactly.
210
233
  */
211
234
  allowSubdomains?: boolean;
212
- /** Grouping hint for a form, e.g. `Mailbox Settings` */
213
- group?: string;
235
+ /** Section of a form the attribute belongs to, e.g. `Mailbox settings` */
236
+ group?: LocalizedText;
214
237
  /** Name a client shows for this attribute, in one or several languages */
215
238
  label?: LocalizedText;
216
239
  }
@@ -231,14 +231,6 @@ export default class LdapOrganizations extends DmPlugin {
231
231
  addOrganization(dn: string, entry: AttributesList, req?: Request): Promise<boolean>;
232
232
  modifyOrganization(dn: string, changes: ModifyRequest, req?: Request): Promise<boolean>;
233
233
  validateNewOrganization(dn: string, entry: AttributesList): Promise<boolean>;
234
- /**
235
- * Build the rejection message for a value that failed its schema `test`,
236
- * quoting the `hint` when the schema carries one so the answer says what a
237
- * valid value looks like.
238
- *
239
- * @param field attribute name
240
- * @returns message for a `BadRequestError`
241
- */
242
234
  invalidValueMessage(field: string): string;
243
235
  validateChanges(dn: string, changes: ModifyRequest): Promise<boolean>;
244
236
  _validateOneChange(field: string, value: AttributeValue | null): Promise<boolean>;
@@ -5,53 +5,6 @@ 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
- */
55
8
  export default class James extends TwakePlugin {
56
9
  name: string;
57
10
  roles: Role[];
@@ -74,14 +27,23 @@ export default class James extends TwakePlugin {
74
27
  private getUserQuota;
75
28
  hooks: Hooks;
76
29
  /**
77
- * Handle mailbox type transitions when twakeMailboxType changes
30
+ * The address of the team mailbox an entry stands for, and whether it is
31
+ * refused for lying in a mailing list branch.
78
32
  */
79
- private handleMailboxTypeTransition;
33
+ private teamMailboxOf;
34
+ /**
35
+ * Bring James from the team mailbox an entry was to the one it is. A
36
+ * mailbox the entry no longer stands for is kept, emptied of its members.
37
+ */
38
+ private followTeamMailbox;
39
+ private teamMailboxQueue;
40
+ private teamMailboxMembers;
80
41
  /**
81
42
  * Extract display name from LDAP attributes
82
43
  * Fallback logic: displayName → cn → givenName+sn → mail
83
44
  */
84
45
  private getDisplayNameFromAttributes;
46
+ private isGroupDn;
85
47
  getMailFromDN(dn: string): Promise<string | null>;
86
48
  getDisplayNameFromDN(dn: string): Promise<string | null>;
87
49
  generateSignature(dn: string): Promise<string | null>;
@@ -113,40 +75,15 @@ export default class James extends TwakePlugin {
113
75
  deleteUserData(mail: string, fromStep?: string): Promise<{
114
76
  taskId: string;
115
77
  } | null>;
116
- /**
117
- * Type guard to check if delete operation is an AttributesList
118
- */
119
- private isAttributesList;
120
78
  /**
121
79
  * Extract mailbox type from group attributes
122
80
  * Returns: 'group', 'mailingList', 'teamMailbox', or null if not set
123
81
  */
124
82
  private getMailboxType;
125
- /**
126
- * Validate that a DN is within one of the allowed branches
127
- */
128
- private isInAllowedBranches;
129
- /**
130
- * Create a mailing list in James
131
- */
132
- private createMailingList;
133
83
  /**
134
84
  * Create a team mailbox in James
135
85
  */
136
86
  private createTeamMailbox;
137
- /**
138
- * Delete a team mailbox from James
139
- */
140
- private deleteTeamMailbox;
141
- /**
142
- * Remove all members from a team mailbox (without deleting it)
143
- * This preserves the mailbox for potential future use
144
- */
145
- private removeAllTeamMailboxMembers;
146
- /**
147
- * Delete a mailing list from James
148
- */
149
- private deleteMailingList;
150
87
  /**
151
88
  * Get email addresses for a list of member DNs
152
89
  * Uses p-limit to parallelize LDAP queries while limiting concurrency
@@ -875,7 +875,7 @@ Ensure all required fields are included:
875
875
 
876
876
  ```json
877
877
  {
878
- "error": "Invalid value for attribute \"mail\": must match ^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
878
+ "error": "Invalid value for attribute \"mail\": Expected an email address, e.g. jane.doe@example.org"
879
879
  }
880
880
  ```
881
881
 
@@ -1075,6 +1075,16 @@ curl -X POST \
1075
1075
  }
1076
1076
  ```
1077
1077
 
1078
+ A member that does not exist answers 400 naming it, and none of the members
1079
+ is added (unless `--group-allow-unexistent-members` is set). Group creation
1080
+ checks its `member` list the same way:
1081
+
1082
+ ```json
1083
+ {
1084
+ "error": "Member uid=nobody,ou=users,dc=example,dc=com not found"
1085
+ }
1086
+ ```
1087
+
1078
1088
  ### Remove Group Member
1079
1089
 
1080
1090
  Remove a user from a group.
@@ -1146,7 +1156,7 @@ All errors return a JSON object with an error message:
1146
1156
 
1147
1157
  ```json
1148
1158
  {
1149
- "error": "Invalid value for attribute \"uid\": must match ^[a-zA-Z0-9._-]{1,255}$"
1159
+ "error": "Invalid value for attribute \"uid\""
1150
1160
  }
1151
1161
  ```
1152
1162
 
@@ -335,18 +335,23 @@ Complete reference for all attribute properties.
335
335
 
336
336
  ### Attribute Properties Table
337
337
 
338
- | Property | Type | Applies To | Description | Example |
339
- | ---------- | ------------ | ------------------- | -------------------------------------------------------------------------------- | ----------------------------------- |
340
- | `type` | string | All | Attribute data type: `"string"`, `"array"`, `"pointer"`, `"number"`, `"integer"` | `"string"` |
341
- | `required` | boolean | All | Whether the attribute must be present | `true` |
342
- | `fixed` | boolean | All | Whether the attribute value cannot be changed after creation | `true` |
343
- | `role` | string | String | Semantic role for special handling (see [Semantic Roles](#semantic-roles)) | `"identifier"` |
344
- | `test` | string/regex | String, Array items | Regular expression for validation | `"^[a-zA-Z0-9._-]{1,255}$"` |
345
- | `branch` | string[] | Pointer | LDAP branches where referenced entries exist | `["ou=users,dc=example,dc=com"]` |
346
- | `ui` | object | Pointer | UI configuration for pointer selection (future feature) | `{}` |
347
- | `group` | string | All | UI grouping for form organization (future feature) | `"contact"` |
348
- | `default` | any | All | Default value for new entries | `["top", "person"]` |
349
- | `items` | object | Array | Schema for array element validation | `{"type": "string", "test": "..."}` |
338
+ | Property | Type | Applies To | Description | Example |
339
+ | ---------- | --------------- | ------------------- | ------------------------------------------------------------------------------------- | ----------------------------------- |
340
+ | `type` | string | All | Attribute data type: `"string"`, `"array"`, `"pointer"`, `"number"`, `"integer"` | `"string"` |
341
+ | `required` | boolean | All | Whether the attribute must be present | `true` |
342
+ | `fixed` | boolean | All | Whether the attribute value cannot be changed after creation | `true` |
343
+ | `role` | string/string[] | String | Semantic role, or roles, for special handling (see [Semantic Roles](#semantic-roles)) | `"identifier"` |
344
+ | `test` | string/regex | String, Array items | Regular expression for validation | `"^[a-zA-Z0-9._-]{1,255}$"` |
345
+ | `branch` | string[] | Pointer | LDAP branches where referenced entries exist | `["ou=users,dc=example,dc=com"]` |
346
+ | `ui` | object | Pointer | UI configuration for pointer selection (future feature) | `{}` |
347
+ | `hint` | text | String, Array items | What a valid value looks like, shown under the field and quoted in refusals | `"Expected pattern 999 9999"` |
348
+ | `group` | text | All | Form section the attribute is shown in | `"Mailbox Settings"` |
349
+ | `default` | any | All | Default value for new entries | `["top", "person"]` |
350
+ | `items` | object | Array | Schema for array element validation | `{"type": "string", "test": "..."}` |
351
+
352
+ A _text_ is a plain string or a map keyed by language tag,
353
+ `{ "en": "Mailbox Settings", "fr": "Paramètres de messagerie" }`, picked as
354
+ [labels are](../../usage/plugins/ldap/flat-generic.md#naming-things-in-the-readers-language).
350
355
 
351
356
  ### Property Details
352
357
 
@@ -394,7 +399,7 @@ Marks the attribute as immutable after creation. Useful for objectClass or ident
394
399
 
395
400
  #### `role` (Optional)
396
401
 
397
- Assigns semantic meaning to attributes for special handling by the application. See [Semantic Roles](#semantic-roles).
402
+ Assigns semantic meaning to attributes for special handling by the application. See [Semantic Roles](#semantic-roles). An attribute holding several roles lists them: `"role": ["domainName", "displayName"]`.
398
403
 
399
404
  ```json
400
405
  {
@@ -200,9 +200,7 @@ overrides builds a second instance, and it needs a name of its own.
200
200
  - `onLdapForwardChange` - Syncs forwarding
201
201
  - `onLdapChange` - General LDAP change handling
202
202
  - `onLdapDisplayNameChange` - Syncs display name
203
- - `ldapgroupadddone` - After group added
204
- - `ldapgroupmodifydone` - After group modified
205
- - `ldapgroupdeletedone` - After group deleted
203
+ - `onLdapEntryChange` - Follows team mailboxes
206
204
  - **Consumes Hooks**: (Hooks provided by `onLdapChange`)
207
205
  - **Notes**: Synchronizes LDAP users/groups with Apache James mail server
208
206
 
@@ -115,7 +115,6 @@ export default class MyPlugin extends DmPlugin {
115
115
  - 📧 **Automatic LDAP → James Sync**
116
116
  - 🔄 **Mail Address Changes** - Account renaming + data
117
117
  - 💾 **Quota Management** - Automatic updates
118
- - 👥 **Mailing Lists** - LDAP Groups → Address Groups
119
118
  - 📨 **Mail Aliases** - mailAlternateAddress → James aliases
120
119
  - 🎯 **WebAdmin API** - REST Communication
121
120
 
@@ -159,33 +158,6 @@ James WebAdmin: PUT /quota/users/alice@.../size
159
158
 
160
159
  <!-- end_slide -->
161
160
 
162
- # James Plugin - List Consistency
163
-
164
- ## LDAP Groups → James Address Groups
165
-
166
- ```bash
167
- # Create a group with mail attribute
168
- POST /api/v1/ldap/groups
169
- {
170
- "cn": "engineering",
171
- "mail": "engineering@company.com",
172
- "member": ["uid=alice,...", "uid=bob,..."]
173
- }
174
- ```
175
-
176
- ### Automatic List Consistency
177
-
178
- 1. ✅ **Creation** → Group created in James + members added
179
- 2. ✅ **Add Member** → Member added to James list
180
- 3. ✅ **Remove Member** → Member removed from James list
181
- 4. ✅ **Delete Group** → List deleted in James
182
-
183
- ### Guarantee
184
-
185
- **LDAP is the source of truth, James stays synchronized**
186
-
187
- <!-- end_slide -->
188
-
189
161
  # LDAP Consistency
190
162
 
191
163
  ## Automatic Consistency Plugins
@@ -115,7 +115,6 @@ export default class MyPlugin extends DmPlugin {
115
115
  - 📧 **Synchronisation automatique LDAP → James**
116
116
  - 🔄 **Changement d'adresse mail** - Renommage compte + données
117
117
  - 💾 **Gestion des quotas** - Mise à jour automatique
118
- - 👥 **Listes de diffusion** - Groupes LDAP → Address Groups
119
118
  - 📨 **Alias mail** - mailAlternateAddress → James aliases
120
119
  - 🎯 **WebAdmin API** - Communication via REST
121
120
 
@@ -159,33 +158,6 @@ James WebAdmin: PUT /quota/users/alice@.../size
159
158
 
160
159
  <!-- end_slide -->
161
160
 
162
- # Plugin James - Cohérence des listes
163
-
164
- ## Groupes LDAP → James Address Groups
165
-
166
- ```bash
167
- # Création d'un groupe avec attribut mail
168
- POST /api/v1/ldap/groups
169
- {
170
- "cn": "engineering",
171
- "mail": "engineering@company.com",
172
- "member": ["uid=alice,...", "uid=bob,..."]
173
- }
174
- ```
175
-
176
- ### Cohérence automatique des listes
177
-
178
- 1. ✅ **Création** → Groupe créé dans James + membres ajoutés
179
- 2. ✅ **Ajout membre** → Membre ajouté à la liste James
180
- 3. ✅ **Retrait membre** → Membre retiré de la liste James
181
- 4. ✅ **Suppression groupe** → Liste supprimée dans James
182
-
183
- ### Garantie
184
-
185
- **LDAP est la source de vérité, James reste synchronisé**
186
-
187
- <!-- end_slide -->
188
-
189
161
  # Cohérence LDAP
190
162
 
191
163
  ## Plugins de cohérence automatique
@@ -452,18 +452,18 @@ whichever of the two names it selects. A value other than `req.user` or
452
452
 
453
453
  #### `core/twake/james`
454
454
 
455
- | CLI | Plural | Env | Default | Description |
456
- | -------------------------------- | ------------------------------- | --------------------------------- | ----------------------- | --------------------------- |
457
- | `--james-webadmin-url` | | `DM_JAMES_WEBADMIN_URL` | `http://localhost:8000` | James WebAdmin API URL |
458
- | `--james-webadmin-token` | | `DM_JAMES_WEBADMIN_TOKEN` | | James authentication token |
459
- | `--james-signature-template` | | `DM_JAMES_SIGNATURE_TEMPLATE` | | Email signature template |
460
- | `--james-concurrency` | | `DM_JAMES_CONCURRENCY` | `10` | James API concurrency |
461
- | `--james-init-delay` | | `DM_JAMES_INIT_DELAY` | `1000` | Init delay (ms) |
462
- | `--james-retry-attempts` | | `DM_JAMES_RETRY_ATTEMPTS` | `5` | Attempts per user call |
463
- | `--james-retry-delay` | | `DM_JAMES_RETRY_DELAY` | `1000` | Base retry delay (ms) |
464
- | `--james-mailing-list-branch` | `--james-mailing-list-branches` | `DM_JAMES_MAILING_LIST_BRANCHES` | `[]` | Mailing list branches |
465
- | `--james-mailbox-type-attribute` | | `DM_JAMES_MAILBOX_TYPE_ATTRIBUTE` | `twakeMailboxType` | Mailbox type attribute |
466
- | `--ldap-concurrency` | | `DM_LDAP_CONCURRENCY` | `10` | LDAP operations concurrency |
455
+ | CLI | Plural | Env | Default | Description |
456
+ | -------------------------------- | ------------------------------- | --------------------------------- | ----------------------- | ---------------------------------- |
457
+ | `--james-webadmin-url` | | `DM_JAMES_WEBADMIN_URL` | `http://localhost:8000` | James WebAdmin API URL |
458
+ | `--james-webadmin-token` | | `DM_JAMES_WEBADMIN_TOKEN` | | James authentication token |
459
+ | `--james-signature-template` | | `DM_JAMES_SIGNATURE_TEMPLATE` | | Email signature template |
460
+ | `--james-concurrency` | | `DM_JAMES_CONCURRENCY` | `10` | James API concurrency |
461
+ | `--james-init-delay` | | `DM_JAMES_INIT_DELAY` | `1000` | Init delay (ms) |
462
+ | `--james-retry-attempts` | | `DM_JAMES_RETRY_ATTEMPTS` | `5` | Attempts per user call |
463
+ | `--james-retry-delay` | | `DM_JAMES_RETRY_DELAY` | `1000` | Base retry delay (ms) |
464
+ | `--james-mailing-list-branch` | `--james-mailing-list-branches` | `DM_JAMES_MAILING_LIST_BRANCHES` | `[]` | Branches refused to team mailboxes |
465
+ | `--james-mailbox-type-attribute` | | `DM_JAMES_MAILBOX_TYPE_ATTRIBUTE` | `twakeMailboxType` | Mailbox type attribute |
466
+ | `--ldap-concurrency` | | `DM_LDAP_CONCURRENCY` | `10` | LDAP operations concurrency |
467
467
 
468
468
  The wait before each retry grows with the attempt, so the total wait is `--james-retry-delay` × n(n−1)/2 for n attempts: 10 s with the defaults, 190 s with 20 attempts.
469
469