@serve.zone/dcrouter 16.4.1 → 16.5.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.
- package/deno.json +1 -1
- package/dist_serve/bundle.js +852 -852
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.d.ts +2 -1
- package/dist_ts/classes.dcrouter.js +20 -4
- package/dist_ts/db/documents/classes.dns-record.doc.d.ts +4 -0
- package/dist_ts/db/documents/classes.dns-record.doc.js +33 -2
- package/dist_ts/db/documents/classes.email-domain.doc.d.ts +5 -1
- package/dist_ts/db/documents/classes.email-domain.doc.js +26 -2
- package/dist_ts/dns/manager.dns.d.ts +6 -0
- package/dist_ts/dns/manager.dns.js +81 -32
- package/dist_ts/dns/providers/cloudflare.provider.d.ts +2 -0
- package/dist_ts/dns/providers/cloudflare.provider.js +45 -28
- package/dist_ts/email/classes.email-domain.manager.d.ts +43 -38
- package/dist_ts/email/classes.email-domain.manager.js +391 -324
- package/dist_ts/email/classes.mail-dns-sync.d.ts +58 -17
- package/dist_ts/email/classes.mail-dns-sync.js +857 -141
- package/dist_ts/email/classes.mail-edge-eligibility.d.ts +55 -0
- package/dist_ts/email/classes.mail-edge-eligibility.js +168 -0
- package/dist_ts/email/classes.mail-egress-coordinator.d.ts +3 -1
- package/dist_ts/email/classes.mail-egress-coordinator.js +43 -22
- package/dist_ts/email/classes.workapp-mail-manager.d.ts +3 -0
- package/dist_ts/email/classes.workapp-mail-manager.js +58 -12
- package/dist_ts/email/index.d.ts +1 -0
- package/dist_ts/email/index.js +2 -1
- package/dist_ts/opsserver/handlers/email-domain.handler.d.ts +1 -0
- package/dist_ts/opsserver/handlers/email-domain.handler.js +138 -22
- package/dist_ts/remoteingress/classes.hub-lifecycle.js +2 -1
- package/dist_ts/remoteingress/classes.tunnel-manager.d.ts +6 -0
- package/dist_ts/remoteingress/classes.tunnel-manager.js +40 -2
- package/dist_ts_interfaces/data/dns-record.d.ts +6 -0
- package/dist_ts_interfaces/data/email-domain.d.ts +81 -0
- package/dist_ts_interfaces/requests/email-domains.d.ts +25 -17
- package/dist_ts_migrations/index.js +152 -9
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate/email-domains.d.ts +16 -0
- package/dist_ts_web/appstate/email-domains.js +140 -19
- package/dist_ts_web/elements/email/ops-view-email-domains.d.ts +1 -0
- package/dist_ts_web/elements/email/ops-view-email-domains.js +36 -13
- package/package.json +3 -3
- package/readme.md +13 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +22 -3
- package/ts/db/documents/classes.dns-record.doc.ts +20 -0
- package/ts/db/documents/classes.email-domain.doc.ts +14 -0
- package/ts/dns/manager.dns.ts +89 -29
- package/ts/dns/providers/cloudflare.provider.ts +46 -27
- package/ts/email/classes.email-domain.manager.ts +416 -368
- package/ts/email/classes.mail-dns-sync.ts +913 -146
- package/ts/email/classes.mail-edge-eligibility.ts +205 -0
- package/ts/email/classes.mail-egress-coordinator.ts +46 -23
- package/ts/email/classes.workapp-mail-manager.ts +69 -13
- package/ts/email/index.ts +1 -0
- package/ts/opsserver/handlers/email-domain.handler.ts +154 -21
- package/ts/remoteingress/classes.hub-lifecycle.ts +1 -0
- package/ts/remoteingress/classes.tunnel-manager.ts +53 -7
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate/email-domains.ts +187 -18
- package/ts_web/elements/email/ops-view-email-domains.ts +44 -12
|
@@ -8,10 +8,26 @@ import { getActionContext } from './login.js';
|
|
|
8
8
|
// Email Domains State
|
|
9
9
|
// ============================================================================
|
|
10
10
|
|
|
11
|
+
export type TEmailDomainOperationName =
|
|
12
|
+
| 'create'
|
|
13
|
+
| 'update'
|
|
14
|
+
| 'delete'
|
|
15
|
+
| 'validate'
|
|
16
|
+
| 'provision'
|
|
17
|
+
| 'reconcile'
|
|
18
|
+
| 'rotate';
|
|
19
|
+
|
|
20
|
+
export interface IEmailDomainOperationState extends interfaces.requests.IEmailDomainActionResult {
|
|
21
|
+
operation: TEmailDomainOperationName;
|
|
22
|
+
completedAt: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
11
25
|
export interface IEmailDomainsState {
|
|
12
26
|
domains: interfaces.data.IEmailDomain[];
|
|
13
27
|
settings: interfaces.data.IEmailServerSettings | null;
|
|
14
28
|
isLoading: boolean;
|
|
29
|
+
error: string | null;
|
|
30
|
+
lastOperation: IEmailDomainOperationState | null;
|
|
15
31
|
lastUpdated: number;
|
|
16
32
|
}
|
|
17
33
|
|
|
@@ -21,11 +37,84 @@ export const emailDomainsStatePart = await appState.getStatePart<IEmailDomainsSt
|
|
|
21
37
|
domains: [],
|
|
22
38
|
settings: null,
|
|
23
39
|
isLoading: false,
|
|
40
|
+
error: null,
|
|
41
|
+
lastOperation: null,
|
|
24
42
|
lastUpdated: 0,
|
|
25
43
|
},
|
|
26
44
|
'soft',
|
|
27
45
|
);
|
|
28
46
|
|
|
47
|
+
const createOperationState = (
|
|
48
|
+
operationArg: TEmailDomainOperationName,
|
|
49
|
+
responseArg: interfaces.requests.IEmailDomainActionResult,
|
|
50
|
+
): IEmailDomainOperationState => ({
|
|
51
|
+
operation: operationArg,
|
|
52
|
+
completedAt: Date.now(),
|
|
53
|
+
...responseArg,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const createFailedOperationState = (
|
|
57
|
+
operationArg: TEmailDomainOperationName,
|
|
58
|
+
errorArg: unknown,
|
|
59
|
+
fallbackMessageArg: string,
|
|
60
|
+
): IEmailDomainOperationState => ({
|
|
61
|
+
operation: operationArg,
|
|
62
|
+
completedAt: Date.now(),
|
|
63
|
+
success: false,
|
|
64
|
+
message: errorArg instanceof Error ? errorArg.message : fallbackMessageArg,
|
|
65
|
+
code: 'EMAIL_DOMAIN_REQUEST_FAILED',
|
|
66
|
+
errors: [
|
|
67
|
+
{
|
|
68
|
+
code: 'EMAIL_DOMAIN_REQUEST_FAILED',
|
|
69
|
+
message: errorArg instanceof Error ? errorArg.message : fallbackMessageArg,
|
|
70
|
+
retryable: true,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export const formatEmailDomainOperationMessage = (
|
|
76
|
+
operationArg: IEmailDomainOperationState,
|
|
77
|
+
fallbackMessageArg: string,
|
|
78
|
+
): string => {
|
|
79
|
+
const primaryMessage = operationArg.message || fallbackMessageArg;
|
|
80
|
+
const messageParts = [
|
|
81
|
+
operationArg.code ? `${primaryMessage} [${operationArg.code}]` : primaryMessage,
|
|
82
|
+
];
|
|
83
|
+
for (const error of operationArg.errors || []) {
|
|
84
|
+
const location = error.recordKey ? `${error.recordKey}: ` : '';
|
|
85
|
+
const detail = `${location}${error.message} [${error.code}]`;
|
|
86
|
+
const duplicatesPrimary =
|
|
87
|
+
!error.recordKey &&
|
|
88
|
+
error.message === primaryMessage &&
|
|
89
|
+
error.code === operationArg.code;
|
|
90
|
+
if (!duplicatesPrimary && !messageParts.includes(detail)) {
|
|
91
|
+
messageParts.push(detail);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (operationArg.lifecycleStatus && operationArg.lifecycleStatus !== 'active') {
|
|
95
|
+
messageParts.push(`Lifecycle: ${operationArg.lifecycleStatus}`);
|
|
96
|
+
}
|
|
97
|
+
if (operationArg.capability === 'unsupported' && !messageParts.some((part) => part.includes('unsupported'))) {
|
|
98
|
+
messageParts.push('Required capability is unsupported');
|
|
99
|
+
}
|
|
100
|
+
if (operationArg.retryAt) {
|
|
101
|
+
messageParts.push(`Retry scheduled for ${operationArg.retryAt}`);
|
|
102
|
+
}
|
|
103
|
+
return messageParts.join(' — ');
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const applyOperationState = (
|
|
107
|
+
stateArg: IEmailDomainsState,
|
|
108
|
+
operationArg: IEmailDomainOperationState,
|
|
109
|
+
fallbackMessageArg: string,
|
|
110
|
+
): IEmailDomainsState => ({
|
|
111
|
+
...stateArg,
|
|
112
|
+
error: operationArg.success
|
|
113
|
+
? null
|
|
114
|
+
: formatEmailDomainOperationMessage(operationArg, fallbackMessageArg),
|
|
115
|
+
lastOperation: operationArg,
|
|
116
|
+
});
|
|
117
|
+
|
|
29
118
|
export const fetchEmailDomainsAction = emailDomainsStatePart.createAction(
|
|
30
119
|
async (statePartArg): Promise<IEmailDomainsState> => {
|
|
31
120
|
const context = getActionContext();
|
|
@@ -46,10 +135,15 @@ export const fetchEmailDomainsAction = emailDomainsStatePart.createAction(
|
|
|
46
135
|
domains: response.domains,
|
|
47
136
|
settings: settingsResponse.settings,
|
|
48
137
|
isLoading: false,
|
|
138
|
+
error: null,
|
|
49
139
|
lastUpdated: Date.now(),
|
|
50
140
|
};
|
|
51
|
-
} catch {
|
|
52
|
-
return {
|
|
141
|
+
} catch (error: unknown) {
|
|
142
|
+
return {
|
|
143
|
+
...currentState,
|
|
144
|
+
isLoading: false,
|
|
145
|
+
error: error instanceof Error ? error.message : 'Failed to fetch email domains',
|
|
146
|
+
};
|
|
53
147
|
}
|
|
54
148
|
},
|
|
55
149
|
);
|
|
@@ -61,17 +155,62 @@ export const createEmailDomainAction = emailDomainsStatePart.createAction<{
|
|
|
61
155
|
dkimKeySize?: number;
|
|
62
156
|
rotateKeys?: boolean;
|
|
63
157
|
rotationIntervalDays?: number;
|
|
158
|
+
remoteIngress?: interfaces.data.IEmailDomainRemoteIngress;
|
|
64
159
|
}>(async (statePartArg, args, actionContext) => {
|
|
65
160
|
const context = getActionContext();
|
|
66
161
|
const currentState = statePartArg.getState()!;
|
|
162
|
+
if (!context.identity) {
|
|
163
|
+
const operation = createFailedOperationState('create', new Error('Not authenticated'), 'Not authenticated');
|
|
164
|
+
return applyOperationState(currentState, operation, 'Failed to create email domain');
|
|
165
|
+
}
|
|
67
166
|
try {
|
|
68
167
|
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
69
168
|
interfaces.requests.IReq_CreateEmailDomain
|
|
70
169
|
>('/typedrequest', 'createEmailDomain');
|
|
71
|
-
await request.fire({ identity: context.identity
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
170
|
+
const response = await request.fire({ identity: context.identity, ...args });
|
|
171
|
+
const operation = createOperationState('create', response);
|
|
172
|
+
if (!response.success) {
|
|
173
|
+
return applyOperationState(currentState, operation, 'Failed to create email domain');
|
|
174
|
+
}
|
|
175
|
+
const refreshedState = await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
176
|
+
return applyOperationState(refreshedState, operation, 'Email domain created');
|
|
177
|
+
} catch (error: unknown) {
|
|
178
|
+
const operation = createFailedOperationState('create', error, 'Failed to create email domain');
|
|
179
|
+
return applyOperationState(currentState, operation, 'Failed to create email domain');
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
export const updateEmailDomainAction = emailDomainsStatePart.createAction<{
|
|
184
|
+
id: string;
|
|
185
|
+
rotateKeys?: boolean;
|
|
186
|
+
rotationIntervalDays?: number;
|
|
187
|
+
rateLimits?: interfaces.data.IEmailDomain['rateLimits'];
|
|
188
|
+
remoteIngress?: interfaces.data.IEmailDomainRemoteIngress | null;
|
|
189
|
+
}>(async (statePartArg, args, actionContext) => {
|
|
190
|
+
const context = getActionContext();
|
|
191
|
+
const currentState = statePartArg.getState()!;
|
|
192
|
+
if (!context.identity) {
|
|
193
|
+
const operation = createFailedOperationState(
|
|
194
|
+
'update',
|
|
195
|
+
new Error('Not authenticated'),
|
|
196
|
+
'Not authenticated',
|
|
197
|
+
);
|
|
198
|
+
return applyOperationState(currentState, operation, 'Failed to update email domain');
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
202
|
+
interfaces.requests.IReq_UpdateEmailDomain
|
|
203
|
+
>('/typedrequest', 'updateEmailDomain');
|
|
204
|
+
const response = await request.fire({ identity: context.identity, ...args });
|
|
205
|
+
const operation = createOperationState('update', response);
|
|
206
|
+
if (!response.success) {
|
|
207
|
+
return applyOperationState(currentState, operation, 'Failed to update email domain');
|
|
208
|
+
}
|
|
209
|
+
const refreshedState = await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
210
|
+
return applyOperationState(refreshedState, operation, 'Email domain updated');
|
|
211
|
+
} catch (error: unknown) {
|
|
212
|
+
const operation = createFailedOperationState('update', error, 'Failed to update email domain');
|
|
213
|
+
return applyOperationState(currentState, operation, 'Failed to update email domain');
|
|
75
214
|
}
|
|
76
215
|
});
|
|
77
216
|
|
|
@@ -98,14 +237,24 @@ export const deleteEmailDomainAction = emailDomainsStatePart.createAction<string
|
|
|
98
237
|
async (statePartArg, id, actionContext) => {
|
|
99
238
|
const context = getActionContext();
|
|
100
239
|
const currentState = statePartArg.getState()!;
|
|
240
|
+
if (!context.identity) {
|
|
241
|
+
const operation = createFailedOperationState('delete', new Error('Not authenticated'), 'Not authenticated');
|
|
242
|
+
return applyOperationState(currentState, operation, 'Failed to delete email domain');
|
|
243
|
+
}
|
|
101
244
|
try {
|
|
102
245
|
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
103
246
|
interfaces.requests.IReq_DeleteEmailDomain
|
|
104
247
|
>('/typedrequest', 'deleteEmailDomain');
|
|
105
|
-
await request.fire({ identity: context.identity
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
248
|
+
const response = await request.fire({ identity: context.identity, id });
|
|
249
|
+
const operation = createOperationState('delete', response);
|
|
250
|
+
if (!response.success) {
|
|
251
|
+
return applyOperationState(currentState, operation, 'Failed to delete email domain');
|
|
252
|
+
}
|
|
253
|
+
const refreshedState = await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
254
|
+
return applyOperationState(refreshedState, operation, 'Email domain deleted');
|
|
255
|
+
} catch (error: unknown) {
|
|
256
|
+
const operation = createFailedOperationState('delete', error, 'Failed to delete email domain');
|
|
257
|
+
return applyOperationState(currentState, operation, 'Failed to delete email domain');
|
|
109
258
|
}
|
|
110
259
|
},
|
|
111
260
|
);
|
|
@@ -114,14 +263,24 @@ export const validateEmailDomainAction = emailDomainsStatePart.createAction<stri
|
|
|
114
263
|
async (statePartArg, id, actionContext) => {
|
|
115
264
|
const context = getActionContext();
|
|
116
265
|
const currentState = statePartArg.getState()!;
|
|
266
|
+
if (!context.identity) {
|
|
267
|
+
const operation = createFailedOperationState('validate', new Error('Not authenticated'), 'Not authenticated');
|
|
268
|
+
return applyOperationState(currentState, operation, 'Failed to validate email domain DNS');
|
|
269
|
+
}
|
|
117
270
|
try {
|
|
118
271
|
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
119
272
|
interfaces.requests.IReq_ValidateEmailDomain
|
|
120
273
|
>('/typedrequest', 'validateEmailDomain');
|
|
121
|
-
await request.fire({ identity: context.identity
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
274
|
+
const response = await request.fire({ identity: context.identity, id });
|
|
275
|
+
const operation = createOperationState('validate', response);
|
|
276
|
+
if (!response.success) {
|
|
277
|
+
return applyOperationState(currentState, operation, 'Failed to validate email domain DNS');
|
|
278
|
+
}
|
|
279
|
+
const refreshedState = await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
280
|
+
return applyOperationState(refreshedState, operation, 'Email domain DNS validated');
|
|
281
|
+
} catch (error: unknown) {
|
|
282
|
+
const operation = createFailedOperationState('validate', error, 'Failed to validate email domain DNS');
|
|
283
|
+
return applyOperationState(currentState, operation, 'Failed to validate email domain DNS');
|
|
125
284
|
}
|
|
126
285
|
},
|
|
127
286
|
);
|
|
@@ -130,14 +289,24 @@ export const provisionEmailDomainDnsAction = emailDomainsStatePart.createAction<
|
|
|
130
289
|
async (statePartArg, id, actionContext) => {
|
|
131
290
|
const context = getActionContext();
|
|
132
291
|
const currentState = statePartArg.getState()!;
|
|
292
|
+
if (!context.identity) {
|
|
293
|
+
const operation = createFailedOperationState('provision', new Error('Not authenticated'), 'Not authenticated');
|
|
294
|
+
return applyOperationState(currentState, operation, 'Failed to provision email domain DNS');
|
|
295
|
+
}
|
|
133
296
|
try {
|
|
134
297
|
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
135
298
|
interfaces.requests.IReq_ProvisionEmailDomainDns
|
|
136
299
|
>('/typedrequest', 'provisionEmailDomainDns');
|
|
137
|
-
await request.fire({ identity: context.identity
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
300
|
+
const response = await request.fire({ identity: context.identity, id });
|
|
301
|
+
const operation = createOperationState('provision', response);
|
|
302
|
+
if (!response.success) {
|
|
303
|
+
return applyOperationState(currentState, operation, 'Failed to provision email domain DNS');
|
|
304
|
+
}
|
|
305
|
+
const refreshedState = await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
306
|
+
return applyOperationState(refreshedState, operation, 'Email domain DNS provisioned');
|
|
307
|
+
} catch (error: unknown) {
|
|
308
|
+
const operation = createFailedOperationState('provision', error, 'Failed to provision email domain DNS');
|
|
309
|
+
return applyOperationState(currentState, operation, 'Failed to provision email domain DNS');
|
|
141
310
|
}
|
|
142
311
|
},
|
|
143
312
|
);
|
|
@@ -218,12 +218,11 @@ export class OpsViewEmailDomains extends DeesElement {
|
|
|
218
218
|
type: ['inRow', 'contextmenu'] as any,
|
|
219
219
|
actionFunc: async (actionData: any) => {
|
|
220
220
|
const d = actionData.item as interfaces.data.IEmailDomain;
|
|
221
|
-
await appstate.emailDomainsStatePart.dispatchAction(
|
|
221
|
+
const nextState = await appstate.emailDomainsStatePart.dispatchAction(
|
|
222
222
|
appstate.validateEmailDomainAction,
|
|
223
223
|
d.id,
|
|
224
224
|
);
|
|
225
|
-
|
|
226
|
-
DeesToast.show({ message: `DNS validated for ${d.domain}`, type: 'success', duration: 2500 });
|
|
225
|
+
await this.showOperationToast(nextState, `DNS validated for ${d.domain}`);
|
|
227
226
|
},
|
|
228
227
|
},
|
|
229
228
|
{
|
|
@@ -232,12 +231,11 @@ export class OpsViewEmailDomains extends DeesElement {
|
|
|
232
231
|
type: ['inRow', 'contextmenu'] as any,
|
|
233
232
|
actionFunc: async (actionData: any) => {
|
|
234
233
|
const d = actionData.item as interfaces.data.IEmailDomain;
|
|
235
|
-
await appstate.emailDomainsStatePart.dispatchAction(
|
|
234
|
+
const nextState = await appstate.emailDomainsStatePart.dispatchAction(
|
|
236
235
|
appstate.provisionEmailDomainDnsAction,
|
|
237
236
|
d.id,
|
|
238
237
|
);
|
|
239
|
-
|
|
240
|
-
DeesToast.show({ message: `DNS records provisioned for ${d.domain}`, type: 'success', duration: 2500 });
|
|
238
|
+
await this.showOperationToast(nextState, `DNS records provisioned for ${d.domain}`);
|
|
241
239
|
},
|
|
242
240
|
},
|
|
243
241
|
{
|
|
@@ -255,10 +253,11 @@ export class OpsViewEmailDomains extends DeesElement {
|
|
|
255
253
|
type: ['inRow', 'contextmenu'] as any,
|
|
256
254
|
actionFunc: async (actionData: any) => {
|
|
257
255
|
const d = actionData.item as interfaces.data.IEmailDomain;
|
|
258
|
-
await appstate.emailDomainsStatePart.dispatchAction(
|
|
256
|
+
const nextState = await appstate.emailDomainsStatePart.dispatchAction(
|
|
259
257
|
appstate.deleteEmailDomainAction,
|
|
260
258
|
d.id,
|
|
261
259
|
);
|
|
260
|
+
await this.showOperationToast(nextState, `Email domain ${d.domain} deleted`);
|
|
262
261
|
},
|
|
263
262
|
},
|
|
264
263
|
]}
|
|
@@ -282,6 +281,32 @@ export class OpsViewEmailDomains extends DeesElement {
|
|
|
282
281
|
return html`<span class="sourceBadge">${label}</span>`;
|
|
283
282
|
}
|
|
284
283
|
|
|
284
|
+
private async showOperationToast(
|
|
285
|
+
stateArg: appstate.IEmailDomainsState,
|
|
286
|
+
successMessageArg: string,
|
|
287
|
+
): Promise<boolean> {
|
|
288
|
+
const { DeesToast } = await import('@design.estate/dees-catalog');
|
|
289
|
+
const operation = stateArg.lastOperation;
|
|
290
|
+
if (!operation) {
|
|
291
|
+
DeesToast.show({
|
|
292
|
+
message: stateArg.error || 'Email domain operation returned no result',
|
|
293
|
+
type: 'error',
|
|
294
|
+
duration: 5000,
|
|
295
|
+
});
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const isPending = operation.success &&
|
|
300
|
+
operation.lifecycleStatus !== undefined &&
|
|
301
|
+
operation.lifecycleStatus !== 'active';
|
|
302
|
+
DeesToast.show({
|
|
303
|
+
message: appstate.formatEmailDomainOperationMessage(operation, successMessageArg),
|
|
304
|
+
type: operation.success ? (isPending ? 'warning' : 'success') : 'error',
|
|
305
|
+
duration: operation.success && !isPending ? 3000 : 6000,
|
|
306
|
+
});
|
|
307
|
+
return operation.success;
|
|
308
|
+
}
|
|
309
|
+
|
|
285
310
|
private parsePortList(value: string): number[] {
|
|
286
311
|
return value
|
|
287
312
|
.split(',')
|
|
@@ -454,7 +479,7 @@ export class OpsViewEmailDomains extends DeesElement {
|
|
|
454
479
|
: parseInt(data.dkimKeySize || '2048', 10);
|
|
455
480
|
|
|
456
481
|
const subdomain = data.subdomain?.trim() || undefined;
|
|
457
|
-
await appstate.emailDomainsStatePart.dispatchAction(
|
|
482
|
+
const nextState = await appstate.emailDomainsStatePart.dispatchAction(
|
|
458
483
|
appstate.createEmailDomainAction,
|
|
459
484
|
{
|
|
460
485
|
linkedDomainId,
|
|
@@ -464,7 +489,11 @@ export class OpsViewEmailDomains extends DeesElement {
|
|
|
464
489
|
rotateKeys: Boolean(data.rotateKeys),
|
|
465
490
|
},
|
|
466
491
|
);
|
|
467
|
-
|
|
492
|
+
const wasAccepted = await this.showOperationToast(
|
|
493
|
+
nextState,
|
|
494
|
+
`Email domain created`,
|
|
495
|
+
);
|
|
496
|
+
if (wasAccepted) m.destroy();
|
|
468
497
|
},
|
|
469
498
|
},
|
|
470
499
|
],
|
|
@@ -513,12 +542,15 @@ export class OpsViewEmailDomains extends DeesElement {
|
|
|
513
542
|
{
|
|
514
543
|
name: 'Auto-Provision All',
|
|
515
544
|
action: async (m: any) => {
|
|
516
|
-
await appstate.emailDomainsStatePart.dispatchAction(
|
|
545
|
+
const nextState = await appstate.emailDomainsStatePart.dispatchAction(
|
|
517
546
|
appstate.provisionEmailDomainDnsAction,
|
|
518
547
|
emailDomain.id,
|
|
519
548
|
);
|
|
520
|
-
|
|
521
|
-
|
|
549
|
+
const wasAccepted = await this.showOperationToast(
|
|
550
|
+
nextState,
|
|
551
|
+
`DNS records provisioned for ${emailDomain.domain}`,
|
|
552
|
+
);
|
|
553
|
+
if (wasAccepted) m.destroy();
|
|
522
554
|
},
|
|
523
555
|
},
|
|
524
556
|
{ name: 'Close', action: async (m: any) => m.destroy() },
|