ldap-rest 0.18.0 → 0.19.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.
- package/dist/abstract/twakePlugin.js +1 -1
- package/dist/config/args.js +1 -1
- package/dist/lib/authz/base.js +1 -1
- package/dist/plugins/ldap/externalUsersInGroups.js +1 -1
- package/dist/plugins/ldap/groups.js +1 -1
- package/dist/plugins/ldap/passwordPolicy.js +1 -1
- package/dist/plugins/twake/james.js +1 -1
- package/dist/src/config/args.d.ts +1 -0
- package/dist/src/lib/authz/base.d.ts +42 -0
- package/dist/src/plugins/ldap/externalUsersInGroups.d.ts +11 -0
- package/dist/src/plugins/ldap/groups.d.ts +34 -3
- package/dist/src/plugins/ldap/passwordPolicy.d.ts +5 -0
- package/dist/src/plugins/twake/james.d.ts +54 -3
- package/docs/client-development/api/rest-api.md +2 -0
- package/docs/usage/configuration.md +13 -12
- package/docs/usage/plugins/auth/authz-linid1.md +21 -0
- package/docs/usage/plugins/integrations/james-mail.md +67 -10
- package/docs/usage/plugins/integrations/james-mailboxes.md +14 -7
- package/docs/usage/plugins/ldap/external-users.md +23 -2
- package/docs/usage/upgrading.md +18 -0
- package/package.json +1 -1
- package/static/schemas/twake/groups.json +34 -17
- package/static/schemas/twake/nomenclature/twakeAccountStatus.json +16 -8
- package/static/schemas/twake/nomenclature/twakeDeliveryMode.json +14 -7
- package/static/schemas/twake/nomenclature/twakeDomain.json +14 -7
- package/static/schemas/twake/nomenclature/twakeListType.json +14 -7
- package/static/schemas/twake/nomenclature/twakeMailboxType.json +14 -7
- package/static/schemas/twake/nomenclature/twakeTitle.json +24 -12
- package/static/schemas/twake/organizations.json +26 -13
- package/static/schemas/twake/positions.json +10 -5
- package/static/schemas/twake/users.json +76 -38
|
@@ -5,6 +5,16 @@ 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
|
+
type Identity = {
|
|
9
|
+
id: string;
|
|
10
|
+
email: string;
|
|
11
|
+
mayDelete?: boolean;
|
|
12
|
+
sortOrder?: number;
|
|
13
|
+
htmlSignature?: string;
|
|
14
|
+
textSignature?: string;
|
|
15
|
+
};
|
|
16
|
+
/** Signatures an identity carries over, see {@link Identity} */
|
|
17
|
+
export type Signatures = Pick<Identity, 'htmlSignature' | 'textSignature'>;
|
|
8
18
|
export default class James extends TwakePlugin {
|
|
9
19
|
name: string;
|
|
10
20
|
roles: Role[];
|
|
@@ -15,6 +25,7 @@ export default class James extends TwakePlugin {
|
|
|
15
25
|
private quotaAttr;
|
|
16
26
|
private aliasAttr;
|
|
17
27
|
private mailboxTypeAttr;
|
|
28
|
+
private forwardAttr;
|
|
18
29
|
private initDelay;
|
|
19
30
|
constructor(server: DM);
|
|
20
31
|
/**
|
|
@@ -27,16 +38,30 @@ export default class James extends TwakePlugin {
|
|
|
27
38
|
private getUserQuota;
|
|
28
39
|
hooks: Hooks;
|
|
29
40
|
/**
|
|
30
|
-
* The address of the team mailbox an entry stands for, and
|
|
31
|
-
* refused
|
|
41
|
+
* The address of the team mailbox an entry stands for, and why it is
|
|
42
|
+
* refused, if it is: it lies in a mailing list branch, or TMail cannot
|
|
43
|
+
* name a team mailbox after its address.
|
|
32
44
|
*/
|
|
33
45
|
private teamMailboxOf;
|
|
46
|
+
/**
|
|
47
|
+
* Give James what an account holds: quota, aliases and identity, after
|
|
48
|
+
* dropping the forwards left on its addresses. Runs when an entry is
|
|
49
|
+
* added with a mail, or gains one.
|
|
50
|
+
*/
|
|
51
|
+
private provisionAccount;
|
|
34
52
|
/**
|
|
35
53
|
* Bring James from the team mailbox an entry was to the one it is. A
|
|
36
54
|
* mailbox the entry no longer stands for is kept, emptied of its members.
|
|
37
55
|
*/
|
|
38
56
|
private followTeamMailbox;
|
|
39
57
|
private teamMailboxQueue;
|
|
58
|
+
/**
|
|
59
|
+
* The WebAdmin path of the team mailbox at an address
|
|
60
|
+
* {@link teamMailboxOf} accepted: TMail names it by the local part, under
|
|
61
|
+
* its domain. Lower-cased, so that a change of case only, which keeps the
|
|
62
|
+
* mailbox, keeps its path.
|
|
63
|
+
*/
|
|
64
|
+
private teamMailboxUrl;
|
|
40
65
|
private teamMailboxMembers;
|
|
41
66
|
/**
|
|
42
67
|
* Extract display name from LDAP attributes
|
|
@@ -62,10 +87,35 @@ export default class James extends TwakePlugin {
|
|
|
62
87
|
* Calls for one address run one after the other: an add triggers this twice
|
|
63
88
|
* (ldapadddone, then the display name "change" onChange publishes), and two
|
|
64
89
|
* concurrent first calls would both find no default and both create one.
|
|
90
|
+
*
|
|
91
|
+
* `signatures` are written when `--james-signature-template` is not set:
|
|
92
|
+
* those of the identity the user had before a rename.
|
|
65
93
|
*/
|
|
66
|
-
updateJamesIdentity(dn: string, mail: string, displayName: string): Promise<void>;
|
|
94
|
+
updateJamesIdentity(dn: string, mail: string, displayName: string, signatures?: Signatures): Promise<void>;
|
|
67
95
|
private identityQueue;
|
|
68
96
|
private doUpdateJamesIdentity;
|
|
97
|
+
/**
|
|
98
|
+
* The signatures of an address's default identity, none when it has none
|
|
99
|
+
* or James cannot be read.
|
|
100
|
+
*/
|
|
101
|
+
private defaultSignatures;
|
|
102
|
+
/**
|
|
103
|
+
* The forwards the directory gives an entry, those James is to keep on its
|
|
104
|
+
* address: none unless the directory owns forwards
|
|
105
|
+
* (`--james-sync-forwards`).
|
|
106
|
+
*/
|
|
107
|
+
private ownForwards;
|
|
108
|
+
/**
|
|
109
|
+
* Remove the forwards James holds from an address an entry takes, but
|
|
110
|
+
* those in `keep`: the entry's own. A rename leaves one from the old
|
|
111
|
+
* address to the new, and its next owner would not get its mail.
|
|
112
|
+
*
|
|
113
|
+
* Runs whether forwards are synced or not: Twake Mail keeps a user's
|
|
114
|
+
* forwards under their own address, and none can have been set yet on an
|
|
115
|
+
* address the account is only now taking. The rename calls this before
|
|
116
|
+
* James moves the user's forwards to the new address.
|
|
117
|
+
*/
|
|
118
|
+
private dropStaleForwards;
|
|
69
119
|
private warnAndWait;
|
|
70
120
|
/**
|
|
71
121
|
* Delete user data via James WebAdmin API
|
|
@@ -101,3 +151,4 @@ export default class James extends TwakePlugin {
|
|
|
101
151
|
_getDelegateEmail(dn: string): Promise<string | null>;
|
|
102
152
|
_normalizeToArray(value: AttributeValue | null): string[];
|
|
103
153
|
}
|
|
154
|
+
export {};
|
|
@@ -245,6 +245,8 @@ curl -H "Accept: application/json" \
|
|
|
245
245
|
- `features.ldapFlatGeneric.flatResources`: Array of flat LDAP resources (users, positions, etc.)
|
|
246
246
|
- `features.ldapGroups`: Group management configuration (if enabled)
|
|
247
247
|
- `features.ldapOrganizations`: Organization tree configuration (if enabled)
|
|
248
|
+
- `features.externalUsersInGroups`: where to send an external group member
|
|
249
|
+
(if enabled), [details](../../usage/plugins/ldap/external-users.md#config-api)
|
|
248
250
|
- `features.openidconnect.endpoints.logout`: the logout route, when OpenID Connect
|
|
249
251
|
guards the server ([details](../../usage/plugins/auth/oidc.md#logout))
|
|
250
252
|
|
|
@@ -452,18 +452,19 @@ 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` | `[]` | Branches refused to team mailboxes
|
|
465
|
-
| `--james-mailbox-type-attribute` | | `DM_JAMES_MAILBOX_TYPE_ATTRIBUTE` | `twakeMailboxType` | Mailbox type attribute
|
|
466
|
-
| `--
|
|
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
|
+
| `--james-sync-forwards` | | `DM_JAMES_SYNC_FORWARDS` | `false` | Copy LDAP forwards to Twake Mail — [details](plugins/integrations/james-mail.md#forwards) |
|
|
467
|
+
| `--ldap-concurrency` | | `DM_LDAP_CONCURRENCY` | `10` | LDAP operations concurrency |
|
|
467
468
|
|
|
468
469
|
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
470
|
|
|
@@ -96,6 +96,27 @@ to the transit branch follows the same rules through
|
|
|
96
96
|
`POST /api/v1/ldap/groups/:cn/move`; that endpoint does not move a group
|
|
97
97
|
attached to no organization.
|
|
98
98
|
|
|
99
|
+
### Mail domains
|
|
100
|
+
|
|
101
|
+
The mail domains an organization's entries may use are those it links in
|
|
102
|
+
`twakeDomainLink` and those every organization above it links
|
|
103
|
+
(`ldap/enterpriseRules`). Creating or changing an organization only asks for
|
|
104
|
+
write on its parent, so the link itself is held to more:
|
|
105
|
+
|
|
106
|
+
- a domain newly linked to an organization must already be linked by an
|
|
107
|
+
organization above it, up to the top organization;
|
|
108
|
+
- a caller holding write on the top organization links any domain: they are
|
|
109
|
+
the one giving each organization its own;
|
|
110
|
+
- a domain the organization already links can be kept, and removing one is
|
|
111
|
+
judged as any other change.
|
|
112
|
+
|
|
113
|
+
So the administrator of `ou=Sales` can create `ou=Sales-EU` restricted to
|
|
114
|
+
Sales' domain, but cannot give it another customer's. The attribute is the
|
|
115
|
+
organization schema's `domainLink` role, or
|
|
116
|
+
`--enterprise-domain-link-attribute`; with neither, nothing is checked. The
|
|
117
|
+
rule belongs to the base of the authorization plugins, so `authzPerBranch`
|
|
118
|
+
applies it too.
|
|
119
|
+
|
|
99
120
|
## Configuration
|
|
100
121
|
|
|
101
122
|
No configuration file needed - permissions are read from LDAP. Simply load the plugin:
|
|
@@ -39,6 +39,8 @@ DM_JAMES_WEBADMIN_TOKEN="your-admin-token"
|
|
|
39
39
|
- `--mail-attribute`: LDAP attribute for email (default: `mail`)
|
|
40
40
|
- `--quota-attribute`: LDAP attribute for quota (default: `mailQuotaSize`)
|
|
41
41
|
- `--alias-attribute`: LDAP attribute for email aliases (default: `mailAlternateAddress`)
|
|
42
|
+
- `--forward-attribute`: LDAP attribute for forwards (default: `mailForwardingAddress`)
|
|
43
|
+
- `--james-sync-forwards`: copy that attribute to Twake Mail's forwards (default: `false`), see [Forwards](#forwards)
|
|
42
44
|
- `--james-mailbox-type-attribute`: LDAP attribute for mailbox type (default: `twakeMailboxType`)
|
|
43
45
|
- `--james-retry-attempts`: attempts in all of a call about a user James may not see yet (default: `5`), see [Replication lag](#replication-lag)
|
|
44
46
|
- `--james-retry-delay`: base delay between those attempts, in ms (default: `1000`); the total wait is delay × n(n−1)/2 for n attempts
|
|
@@ -87,7 +89,29 @@ When a user's mail attribute changes:
|
|
|
87
89
|
POST /users/old@company.com/rename/john.doe@company.com?action=rename
|
|
88
90
|
```
|
|
89
91
|
|
|
90
|
-
4. **James** renames the mail account and
|
|
92
|
+
4. **James** renames the mail account and its mailboxes, and adds a forward
|
|
93
|
+
from the old address to the new one, so that mail sent to the old address
|
|
94
|
+
still arrives. It leaves the identities under the old address.
|
|
95
|
+
|
|
96
|
+
5. **James plugin** moves the aliases (see
|
|
97
|
+
[Aliases and Mail Changes](#aliases-and-mail-changes)) and gives the new
|
|
98
|
+
address its [default identity](#display-name-and-identity) back, with the
|
|
99
|
+
signatures of the old one when `--james-signature-template` is not set.
|
|
100
|
+
|
|
101
|
+
#### Forwards Left on an Address
|
|
102
|
+
|
|
103
|
+
The forward a rename leaves outlives the account. When an address becomes the
|
|
104
|
+
`mail` or an alias of an account, at its creation, a rename, a mail added to
|
|
105
|
+
an existing entry or an alias add, the plugin removes the forwards James holds
|
|
106
|
+
from it, except the entry's own when the directory owns forwards
|
|
107
|
+
(`--forward-attribute`, with `--james-sync-forwards`):
|
|
108
|
+
|
|
109
|
+
```http
|
|
110
|
+
GET /address/forwards/old@company.com
|
|
111
|
+
DELETE /address/forwards/old@company.com/targets/john.doe@company.com
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Otherwise the new owner of the address would not get its mail.
|
|
91
115
|
|
|
92
116
|
### Quota Changes
|
|
93
117
|
|
|
@@ -115,11 +139,33 @@ When a user's quota changes:
|
|
|
115
139
|
5000000000
|
|
116
140
|
```
|
|
117
141
|
|
|
142
|
+
### Forwards
|
|
143
|
+
|
|
144
|
+
Forwards are a setting of the user in Twake Mail, beside "keep a copy in my
|
|
145
|
+
mailbox", and Twake Mail Admin can change them too. By default the plugin
|
|
146
|
+
does not copy `--forward-attribute` to them. It still removes the
|
|
147
|
+
[forwards left](#forwards-left-on-an-address) on an address an account takes:
|
|
148
|
+
Twake Mail keeps a user's forwards under their own address, and none can have
|
|
149
|
+
been set on an address the account is only now taking.
|
|
150
|
+
|
|
151
|
+
With `--james-sync-forwards`, the directory owns them: each change of
|
|
152
|
+
`--forward-attribute` is applied to Twake Mail, and overwrites what the user
|
|
153
|
+
set there.
|
|
154
|
+
|
|
155
|
+
```http
|
|
156
|
+
PUT /address/forwards/jdoe@company.com/targets/john@partner.com
|
|
157
|
+
DELETE /address/forwards/jdoe@company.com/targets/old@partner.com
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Only the change is applied: a forward the user added in Twake Mail stays
|
|
161
|
+
until the directory names it and removes it, and the directory is never told
|
|
162
|
+
about the forwards set in Twake Mail.
|
|
163
|
+
|
|
118
164
|
### Display Name and Identity
|
|
119
165
|
|
|
120
|
-
When a user is added, or their display name changes, the plugin names
|
|
121
|
-
default identity in Twake Mail after the directory. The name is the first
|
|
122
|
-
found in `--display-name-attribute` (`displayName` by default), `cn`, then
|
|
166
|
+
When a user is added, renamed, or their display name changes, the plugin names
|
|
167
|
+
their default identity in Twake Mail after the directory. The name is the first
|
|
168
|
+
one found in `--display-name-attribute` (`displayName` by default), `cn`, then
|
|
123
169
|
`givenName` and `sn`. The optional signature is `--james-signature-template`.
|
|
124
170
|
|
|
125
171
|
1. **James plugin** reads the default identity, the deletable one with the
|
|
@@ -226,7 +272,8 @@ When the primary email address changes, all aliases are automatically updated:
|
|
|
226
272
|
PUT /address/aliases/john.smith@company.com/sources/jdoe@company.com
|
|
227
273
|
```
|
|
228
274
|
|
|
229
|
-
|
|
275
|
+
James forwards the old address to the new one, see
|
|
276
|
+
[Forwards Left on an Address](#forwards-left-on-an-address).
|
|
230
277
|
|
|
231
278
|
#### Active Directory Format Support
|
|
232
279
|
|
|
@@ -430,14 +477,19 @@ const signature = await james.generateSignature(
|
|
|
430
477
|
|
|
431
478
|
---
|
|
432
479
|
|
|
433
|
-
### updateJamesIdentity(dn, mail, displayName)
|
|
480
|
+
### updateJamesIdentity(dn, mail, displayName, signatures?)
|
|
434
481
|
|
|
435
482
|
Update a user's JMAP identity in James (name and optional signature).
|
|
436
483
|
|
|
437
484
|
**Signature:**
|
|
438
485
|
|
|
439
486
|
```typescript
|
|
440
|
-
async updateJamesIdentity(
|
|
487
|
+
async updateJamesIdentity(
|
|
488
|
+
dn: string,
|
|
489
|
+
mail: string,
|
|
490
|
+
displayName: string,
|
|
491
|
+
signatures?: { htmlSignature?: string; textSignature?: string }
|
|
492
|
+
): Promise<void>
|
|
441
493
|
```
|
|
442
494
|
|
|
443
495
|
**Parameters:**
|
|
@@ -445,6 +497,8 @@ async updateJamesIdentity(dn: string, mail: string, displayName: string): Promis
|
|
|
445
497
|
- `dn` (string): LDAP Distinguished Name (used for signature generation)
|
|
446
498
|
- `mail` (string): User's email address
|
|
447
499
|
- `displayName` (string): New display name for the identity
|
|
500
|
+
- `signatures` (object, optional): written when `--james-signature-template`
|
|
501
|
+
is not set
|
|
448
502
|
|
|
449
503
|
**Example:**
|
|
450
504
|
|
|
@@ -551,6 +605,8 @@ const type = await james.getGroupMailboxType(
|
|
|
551
605
|
| Remove delegation | `/users/{mail}/authorizedUsers/{delegate}` | DELETE |
|
|
552
606
|
| Add alias | `/address/aliases/{mail}/sources/{alias}` | PUT |
|
|
553
607
|
| Remove alias | `/address/aliases/{mail}/sources/{alias}` | DELETE |
|
|
608
|
+
| List forwards | `/address/forwards/{mail}` | GET |
|
|
609
|
+
| Remove forward | `/address/forwards/{mail}/targets/{to}` | DELETE |
|
|
554
610
|
|
|
555
611
|
### Authentication
|
|
556
612
|
|
|
@@ -783,9 +839,10 @@ Quota values are in **bytes**:
|
|
|
783
839
|
|
|
784
840
|
### Scenario 1: User Creation
|
|
785
841
|
|
|
786
|
-
1. Create user in LDAP with mail attribute
|
|
787
|
-
2. James plugin
|
|
788
|
-
|
|
842
|
+
1. Create user in LDAP with mail attribute: James reads its users from LDAP
|
|
843
|
+
2. James plugin sets the quota, the aliases and the default identity, after
|
|
844
|
+
dropping the [forwards left](#forwards-left-on-an-address) on its addresses
|
|
845
|
+
3. A mail added later to an existing entry is handled the same way
|
|
789
846
|
4. Future mail/quota changes are synced automatically
|
|
790
847
|
|
|
791
848
|
### Scenario 2: Mail Address Change
|
|
@@ -97,8 +97,8 @@ await dm.ldap.add('cn=sales-team,ou=groups,dc=example,dc=com', {
|
|
|
97
97
|
|
|
98
98
|
This will:
|
|
99
99
|
|
|
100
|
-
1. Create the team mailbox via `PUT /domains/example.com/team-mailboxes/sales
|
|
101
|
-
2. Add each member via `PUT /domains/example.com/team-mailboxes/sales
|
|
100
|
+
1. Create the team mailbox via `PUT /domains/example.com/team-mailboxes/sales`
|
|
101
|
+
2. Add each member via `PUT /domains/example.com/team-mailboxes/sales/members/{member-email}`
|
|
102
102
|
|
|
103
103
|
### Creating a Mailing List
|
|
104
104
|
|
|
@@ -159,9 +159,16 @@ address cannot be read.
|
|
|
159
159
|
|
|
160
160
|
### Team Mailboxes
|
|
161
161
|
|
|
162
|
-
- **Create**: `PUT /domains/{domain}/team-mailboxes/{
|
|
163
|
-
- **Add member**: `PUT /domains/{domain}/team-mailboxes/{
|
|
164
|
-
- **Delete member**: `DELETE /domains/{domain}/team-mailboxes/{
|
|
162
|
+
- **Create**: `PUT /domains/{domain}/team-mailboxes/{name}`
|
|
163
|
+
- **Add member**: `PUT /domains/{domain}/team-mailboxes/{name}/members/{memberEmail}`
|
|
164
|
+
- **Delete member**: `DELETE /domains/{domain}/team-mailboxes/{name}/members/{memberEmail}`
|
|
165
|
+
|
|
166
|
+
TMail names a team mailbox by the local part of its address, `{name}@{domain}`,
|
|
167
|
+
and accepts only letters, digits, `#`, `-` and `_` in it, up to 255 characters.
|
|
168
|
+
A group whose address has any other character, such as a dot, gets no team
|
|
169
|
+
mailbox: the plugin logs an error once, when the group comes to have such an
|
|
170
|
+
address, and does not call TMail. The name is lower-cased, so a change of case
|
|
171
|
+
of the address keeps the same team mailbox.
|
|
165
172
|
|
|
166
173
|
## Validation Rules
|
|
167
174
|
|
|
@@ -220,7 +227,7 @@ await dm.ldap.modify('cn=sales,ou=groups,dc=example,dc=com', {
|
|
|
220
227
|
|
|
221
228
|
**What happens:**
|
|
222
229
|
|
|
223
|
-
1. Creates the team mailbox (`PUT /domains/{domain}/team-mailboxes/{
|
|
230
|
+
1. Creates the team mailbox (`PUT /domains/{domain}/team-mailboxes/{name}`)
|
|
224
231
|
2. Adds all current members to the team mailbox
|
|
225
232
|
|
|
226
233
|
#### teamMailbox → mailingList
|
|
@@ -236,7 +243,7 @@ await dm.ldap.modify('cn=sales,ou=groups,dc=example,dc=com', {
|
|
|
236
243
|
|
|
237
244
|
**What happens:**
|
|
238
245
|
|
|
239
|
-
1. Removes all members from the team mailbox (`DELETE /domains/{domain}/team-mailboxes/{
|
|
246
|
+
1. Removes all members from the team mailbox (`DELETE /domains/{domain}/team-mailboxes/{name}/members/{member}`)
|
|
240
247
|
2. **Preserves the team mailbox** (does NOT delete it - can be recovered later)
|
|
241
248
|
|
|
242
249
|
#### group → mailingList or teamMailbox
|
|
@@ -33,10 +33,31 @@ This plugin intercepts group member validation and automatically creates missing
|
|
|
33
33
|
### Important Notes
|
|
34
34
|
|
|
35
35
|
- **Dependencies**: This plugin requires the `core/ldap/groups` plugin
|
|
36
|
-
- **DN Format**: External members are in the format `mail={email},{external_members_branch}
|
|
37
|
-
|
|
36
|
+
- **DN Format**: External members are in the format `mail={email},{external_members_branch}`,
|
|
37
|
+
the address escaped as any DN value (RFC 4514): `mail=a\+b@partner.com,…`
|
|
38
|
+
creates an entry whose `mail` is `a+b@partner.com`. Only the direct children of the
|
|
39
|
+
branch are external members.
|
|
40
|
+
- **Domain Protection**: External users cannot be created if their mail are in managed domains (configured via `--mail-domain`, compared case-insensitively)
|
|
38
41
|
- **Automatic Creation**: Users are created automatically when added to a group if they don't exist
|
|
39
42
|
|
|
43
|
+
### Config API
|
|
44
|
+
|
|
45
|
+
`GET /api/v1/config` tells a client whether external members are accepted, and
|
|
46
|
+
where to send them:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
"externalUsersInGroups": {
|
|
50
|
+
"enabled": true,
|
|
51
|
+
"branch": "ou=contacts,dc=example,dc=com",
|
|
52
|
+
"rdnAttribute": "mail",
|
|
53
|
+
"managedDomains": ["example.com"]
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
A client turns an address into a member with
|
|
58
|
+
`rdnAttribute=<escaped address>,<branch>`, and can refuse a `managedDomains`
|
|
59
|
+
address before sending it.
|
|
60
|
+
|
|
40
61
|
## How It Works
|
|
41
62
|
|
|
42
63
|
### Member Validation Hook
|
package/docs/usage/upgrading.md
CHANGED
|
@@ -4,6 +4,24 @@ What to check before deploying, newest first. Only releases that need a
|
|
|
4
4
|
decision or a configuration change appear here; see the
|
|
5
5
|
[CHANGELOG](../../CHANGELOG.md) for everything else.
|
|
6
6
|
|
|
7
|
+
## To 0.19.0
|
|
8
|
+
|
|
9
|
+
### Forwards are no longer copied to Twake Mail
|
|
10
|
+
|
|
11
|
+
**Who is affected:** a deployment that loads `twake/james` and stores
|
|
12
|
+
forwards in `--forward-attribute` (`mailForwardingAddress` by default).
|
|
13
|
+
|
|
14
|
+
`twake/james` no longer applies the changes of that attribute to Twake Mail's
|
|
15
|
+
forwards: users set them in Twake Mail. The forwards already in Twake Mail
|
|
16
|
+
stay as they are, except those left on an address an account takes, removed
|
|
17
|
+
as before,
|
|
18
|
+
[details](plugins/integrations/james-mail.md#forwards-left-on-an-address).
|
|
19
|
+
|
|
20
|
+
To keep the directory as the owner of the forwards, set
|
|
21
|
+
`--james-sync-forwards` (`DM_JAMES_SYNC_FORWARDS=true`); it then overwrites
|
|
22
|
+
what users set in Twake Mail,
|
|
23
|
+
[details](plugins/integrations/james-mail.md#forwards).
|
|
24
|
+
|
|
7
25
|
## To 0.18.0
|
|
8
26
|
|
|
9
27
|
### Mailing lists are no longer copied to James
|
package/package.json
CHANGED
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
"base": "ou=groups,__ldap_base__",
|
|
9
9
|
"label": {
|
|
10
10
|
"en": "Groups",
|
|
11
|
-
"fr": "Groupes"
|
|
11
|
+
"fr": "Groupes",
|
|
12
|
+
"mn": "Бүлгүүд"
|
|
12
13
|
},
|
|
13
14
|
"singularLabel": {
|
|
14
15
|
"en": "group",
|
|
15
|
-
"fr": "groupe"
|
|
16
|
+
"fr": "groupe",
|
|
17
|
+
"mn": "бүлэг"
|
|
16
18
|
}
|
|
17
19
|
},
|
|
18
20
|
"strict": true,
|
|
@@ -33,13 +35,15 @@
|
|
|
33
35
|
"test": "^(?!.*\\.\\.)[a-zA-Z0-9!#$%&'*+/=?^_`{|}.-]{1,64}$",
|
|
34
36
|
"hint": {
|
|
35
37
|
"en": "Must match an email local part: letters, digits and ! # $ % & ' * + / = ? ^ _ ` { | } . -, no consecutive dots",
|
|
36
|
-
"fr": "Partie locale d'une adresse électronique : lettres, chiffres et ! # $ % & ' * + / = ? ^ _ ` { | } . -, sans points consécutifs"
|
|
38
|
+
"fr": "Partie locale d'une adresse électronique : lettres, chiffres et ! # $ % & ' * + / = ? ^ _ ` { | } . -, sans points consécutifs",
|
|
39
|
+
"mn": "Имэйл хаягийн @-ээс өмнөх хэсэг: үсэг, тоо болон ! # $ % & ' * + / = ? ^ _ ` { | } . -, дараалсан цэггүй"
|
|
37
40
|
},
|
|
38
41
|
"required": true,
|
|
39
42
|
"role": "identifier",
|
|
40
43
|
"label": {
|
|
41
44
|
"en": "Name",
|
|
42
|
-
"fr": "Nom"
|
|
45
|
+
"fr": "Nom",
|
|
46
|
+
"mn": "Нэр"
|
|
43
47
|
}
|
|
44
48
|
},
|
|
45
49
|
"description": {
|
|
@@ -48,7 +52,8 @@
|
|
|
48
52
|
"required": false,
|
|
49
53
|
"label": {
|
|
50
54
|
"en": "Description",
|
|
51
|
-
"fr": "Description"
|
|
55
|
+
"fr": "Description",
|
|
56
|
+
"mn": "Тайлбар"
|
|
52
57
|
}
|
|
53
58
|
},
|
|
54
59
|
"mail": {
|
|
@@ -57,7 +62,8 @@
|
|
|
57
62
|
"test": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
|
|
58
63
|
"hint": {
|
|
59
64
|
"en": "Expected an email address, e.g. all-staff@lists.example.org",
|
|
60
|
-
"fr": "Une adresse électronique est attendue, par ex. all-staff@lists.example.org"
|
|
65
|
+
"fr": "Une adresse électronique est attendue, par ex. all-staff@lists.example.org",
|
|
66
|
+
"mn": "Имэйл хаяг оруулна уу, жишээ нь all-staff@lists.example.org"
|
|
61
67
|
},
|
|
62
68
|
"required": false,
|
|
63
69
|
"unique": {
|
|
@@ -69,7 +75,8 @@
|
|
|
69
75
|
"role": "primaryEmail",
|
|
70
76
|
"label": {
|
|
71
77
|
"en": "Email",
|
|
72
|
-
"fr": "Adresse électronique"
|
|
78
|
+
"fr": "Adresse électronique",
|
|
79
|
+
"mn": "Имэйл хаяг"
|
|
73
80
|
}
|
|
74
81
|
},
|
|
75
82
|
"businessCategory": {
|
|
@@ -79,11 +86,13 @@
|
|
|
79
86
|
"role": "writePolicy",
|
|
80
87
|
"label": {
|
|
81
88
|
"en": "List type",
|
|
82
|
-
"fr": "Type de liste"
|
|
89
|
+
"fr": "Type de liste",
|
|
90
|
+
"mn": "Жагсаалтын төрөл"
|
|
83
91
|
},
|
|
84
92
|
"group": {
|
|
85
93
|
"en": "Mailbox Settings",
|
|
86
|
-
"fr": "Paramètres de messagerie"
|
|
94
|
+
"fr": "Paramètres de messagerie",
|
|
95
|
+
"mn": "Шуудангийн хайрцгийн тохиргоо"
|
|
87
96
|
}
|
|
88
97
|
},
|
|
89
98
|
"twakeMailboxType": {
|
|
@@ -91,13 +100,15 @@
|
|
|
91
100
|
"branch": ["ou=twakeMailboxType,ou=nomenclature,__LDAP_BASE__"],
|
|
92
101
|
"group": {
|
|
93
102
|
"en": "Mailbox Settings",
|
|
94
|
-
"fr": "Paramètres de messagerie"
|
|
103
|
+
"fr": "Paramètres de messagerie",
|
|
104
|
+
"mn": "Шуудангийн хайрцгийн тохиргоо"
|
|
95
105
|
},
|
|
96
106
|
"required": false,
|
|
97
107
|
"role": "mailboxType",
|
|
98
108
|
"label": {
|
|
99
109
|
"en": "Group type",
|
|
100
|
-
"fr": "Type de groupe"
|
|
110
|
+
"fr": "Type de groupe",
|
|
111
|
+
"mn": "Бүлгийн төрөл"
|
|
101
112
|
}
|
|
102
113
|
},
|
|
103
114
|
"member": {
|
|
@@ -107,14 +118,16 @@
|
|
|
107
118
|
"test": "^[a-zA-Z]+=.*,__LDAP_BASE__$",
|
|
108
119
|
"hint": {
|
|
109
120
|
"en": "Expected the DN of an entry of this directory",
|
|
110
|
-
"fr": "Le DN d'une entrée de cet annuaire est attendu"
|
|
121
|
+
"fr": "Le DN d'une entrée de cet annuaire est attendu",
|
|
122
|
+
"mn": "Энэ лавлахын бичлэгийн DN оруулна уу"
|
|
111
123
|
}
|
|
112
124
|
},
|
|
113
125
|
"required": false,
|
|
114
126
|
"role": "members",
|
|
115
127
|
"label": {
|
|
116
128
|
"en": "Members",
|
|
117
|
-
"fr": "Membres"
|
|
129
|
+
"fr": "Membres",
|
|
130
|
+
"mn": "Гишүүд"
|
|
118
131
|
}
|
|
119
132
|
},
|
|
120
133
|
"owner": {
|
|
@@ -124,14 +137,16 @@
|
|
|
124
137
|
"test": "^[a-zA-Z]+=.*,__LDAP_BASE__$",
|
|
125
138
|
"hint": {
|
|
126
139
|
"en": "Expected the DN of an entry of this directory",
|
|
127
|
-
"fr": "Le DN d'une entrée de cet annuaire est attendu"
|
|
140
|
+
"fr": "Le DN d'une entrée de cet annuaire est attendu",
|
|
141
|
+
"mn": "Энэ лавлахын бичлэгийн DN оруулна уу"
|
|
128
142
|
}
|
|
129
143
|
},
|
|
130
144
|
"required": false,
|
|
131
145
|
"role": "owners",
|
|
132
146
|
"label": {
|
|
133
147
|
"en": "Owners",
|
|
134
|
-
"fr": "Propriétaires"
|
|
148
|
+
"fr": "Propriétaires",
|
|
149
|
+
"mn": "Эзэмшигчид"
|
|
135
150
|
}
|
|
136
151
|
},
|
|
137
152
|
"twakeDepartmentLink": {
|
|
@@ -141,7 +156,8 @@
|
|
|
141
156
|
"role": "organizationLink",
|
|
142
157
|
"label": {
|
|
143
158
|
"en": "Department",
|
|
144
|
-
"fr": "Organisation"
|
|
159
|
+
"fr": "Organisation",
|
|
160
|
+
"mn": "Байгууллага"
|
|
145
161
|
}
|
|
146
162
|
},
|
|
147
163
|
"twakeDepartmentPath": {
|
|
@@ -152,7 +168,8 @@
|
|
|
152
168
|
"role": "organizationPath",
|
|
153
169
|
"label": {
|
|
154
170
|
"en": "Department path",
|
|
155
|
-
"fr": "Chemin"
|
|
171
|
+
"fr": "Chemin",
|
|
172
|
+
"mn": "Зам"
|
|
156
173
|
}
|
|
157
174
|
}
|
|
158
175
|
}
|
|
@@ -7,28 +7,34 @@
|
|
|
7
7
|
"pluralName": "accountStatuses",
|
|
8
8
|
"label": {
|
|
9
9
|
"en": "Account states",
|
|
10
|
-
"fr": "États de compte"
|
|
10
|
+
"fr": "États de compte",
|
|
11
|
+
"mn": "Бүртгэлийн төлөвүүд"
|
|
11
12
|
},
|
|
12
13
|
"singularLabel": {
|
|
13
14
|
"en": "account state",
|
|
14
|
-
"fr": "état de compte"
|
|
15
|
+
"fr": "état de compte",
|
|
16
|
+
"mn": "бүртгэлийн төлөв"
|
|
15
17
|
},
|
|
16
18
|
"valueLabels": {
|
|
17
19
|
"active": {
|
|
18
20
|
"en": "Active",
|
|
19
|
-
"fr": "Actif"
|
|
21
|
+
"fr": "Actif",
|
|
22
|
+
"mn": "Идэвхтэй"
|
|
20
23
|
},
|
|
21
24
|
"disabled": {
|
|
22
25
|
"en": "Disabled",
|
|
23
|
-
"fr": "Désactivé"
|
|
26
|
+
"fr": "Désactivé",
|
|
27
|
+
"mn": "Идэвхгүй"
|
|
24
28
|
},
|
|
25
29
|
"noaccess": {
|
|
26
30
|
"en": "No access",
|
|
27
|
-
"fr": "Sans accès"
|
|
31
|
+
"fr": "Sans accès",
|
|
32
|
+
"mn": "Хандах эрхгүй"
|
|
28
33
|
},
|
|
29
34
|
"todelete": {
|
|
30
35
|
"en": "To delete",
|
|
31
|
-
"fr": "À supprimer"
|
|
36
|
+
"fr": "À supprimer",
|
|
37
|
+
"mn": "Устгах"
|
|
32
38
|
}
|
|
33
39
|
},
|
|
34
40
|
"base": "ou=twakeAccountStatus,ou=nomenclature,{ldap_base}"
|
|
@@ -50,7 +56,8 @@
|
|
|
50
56
|
"required": true,
|
|
51
57
|
"label": {
|
|
52
58
|
"en": "Name",
|
|
53
|
-
"fr": "Nom"
|
|
59
|
+
"fr": "Nom",
|
|
60
|
+
"mn": "Нэр"
|
|
54
61
|
}
|
|
55
62
|
},
|
|
56
63
|
"description": {
|
|
@@ -58,7 +65,8 @@
|
|
|
58
65
|
"required": false,
|
|
59
66
|
"label": {
|
|
60
67
|
"en": "Description",
|
|
61
|
-
"fr": "Description"
|
|
68
|
+
"fr": "Description",
|
|
69
|
+
"mn": "Тайлбар"
|
|
62
70
|
}
|
|
63
71
|
}
|
|
64
72
|
}
|