@serve.zone/dcrouter 13.9.2 → 13.11.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/dist_serve/bundle.js +1306 -1180
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/classes.dcrouter.d.ts +2 -0
- package/dist_ts/classes.dcrouter.js +15 -1
- package/dist_ts/db/documents/classes.email-domain.doc.d.ts +16 -0
- package/dist_ts/db/documents/classes.email-domain.doc.js +118 -0
- package/dist_ts/db/documents/index.d.ts +1 -0
- package/dist_ts/db/documents/index.js +3 -1
- package/dist_ts/email/classes.email-domain.manager.d.ts +45 -0
- package/dist_ts/email/classes.email-domain.manager.js +272 -0
- package/dist_ts/email/index.d.ts +1 -0
- package/dist_ts/email/index.js +2 -0
- package/dist_ts/opsserver/classes.opsserver.d.ts +1 -0
- package/dist_ts/opsserver/classes.opsserver.js +3 -1
- package/dist_ts/opsserver/handlers/email-domain.handler.d.ts +16 -0
- package/dist_ts/opsserver/handlers/email-domain.handler.js +149 -0
- package/dist_ts/opsserver/handlers/index.d.ts +1 -0
- package/dist_ts/opsserver/handlers/index.js +2 -1
- package/dist_ts_interfaces/data/email-domain.d.ts +68 -0
- package/dist_ts_interfaces/data/email-domain.js +2 -0
- package/dist_ts_interfaces/data/index.d.ts +1 -0
- package/dist_ts_interfaces/data/index.js +2 -1
- package/dist_ts_interfaces/requests/email-domains.d.ts +140 -0
- package/dist_ts_interfaces/requests/email-domains.js +2 -0
- package/dist_ts_interfaces/requests/index.d.ts +1 -0
- package/dist_ts_interfaces/requests/index.js +2 -1
- package/dist_ts_web/00_commitinfo_data.js +2 -2
- package/dist_ts_web/appstate.d.ts +20 -0
- package/dist_ts_web/appstate.js +81 -1
- package/dist_ts_web/elements/domains/ops-view-certificates.js +17 -96
- package/dist_ts_web/elements/email/index.d.ts +1 -0
- package/dist_ts_web/elements/email/index.js +2 -1
- package/dist_ts_web/elements/email/ops-view-email-domains.d.ts +19 -0
- package/dist_ts_web/elements/email/ops-view-email-domains.js +403 -0
- package/dist_ts_web/elements/email/ops-view-email-security.d.ts +1 -1
- package/dist_ts_web/elements/email/ops-view-email-security.js +39 -58
- package/dist_ts_web/elements/ops-dashboard.js +3 -1
- package/dist_ts_web/router.js +2 -2
- package/package.json +2 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +17 -0
- package/ts/db/documents/classes.email-domain.doc.ts +53 -0
- package/ts/db/documents/index.ts +3 -0
- package/ts/email/classes.email-domain.manager.ts +316 -0
- package/ts/email/index.ts +1 -0
- package/ts/opsserver/classes.opsserver.ts +2 -0
- package/ts/opsserver/handlers/email-domain.handler.ts +194 -0
- package/ts/opsserver/handlers/index.ts +2 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +123 -0
- package/ts_web/elements/domains/ops-view-certificates.ts +16 -95
- package/ts_web/elements/email/index.ts +1 -0
- package/ts_web/elements/email/ops-view-email-domains.ts +389 -0
- package/ts_web/elements/email/ops-view-email-security.ts +38 -57
- package/ts_web/elements/ops-dashboard.ts +2 -0
- package/ts_web/router.ts +1 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
import * as interfaces from '../../../ts_interfaces/index.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CRUD + DNS provisioning handler for email domains.
|
|
7
|
+
*
|
|
8
|
+
* Auth: admin JWT or API token with `email-domains:read` / `email-domains:write` scope.
|
|
9
|
+
*/
|
|
10
|
+
export class EmailDomainHandler {
|
|
11
|
+
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
12
|
+
|
|
13
|
+
constructor(private opsServerRef: OpsServer) {
|
|
14
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
15
|
+
this.registerHandlers();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private async requireAuth(
|
|
19
|
+
request: { identity?: interfaces.data.IIdentity; apiToken?: string },
|
|
20
|
+
requiredScope?: interfaces.data.TApiTokenScope,
|
|
21
|
+
): Promise<string> {
|
|
22
|
+
if (request.identity?.jwt) {
|
|
23
|
+
try {
|
|
24
|
+
const isAdmin = await this.opsServerRef.adminHandler.adminIdentityGuard.exec({
|
|
25
|
+
identity: request.identity,
|
|
26
|
+
});
|
|
27
|
+
if (isAdmin) return request.identity.userId;
|
|
28
|
+
} catch { /* fall through */ }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (request.apiToken) {
|
|
32
|
+
const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager;
|
|
33
|
+
if (tokenManager) {
|
|
34
|
+
const token = await tokenManager.validateToken(request.apiToken);
|
|
35
|
+
if (token) {
|
|
36
|
+
if (!requiredScope || tokenManager.hasScope(token, requiredScope)) {
|
|
37
|
+
return token.createdBy;
|
|
38
|
+
}
|
|
39
|
+
throw new plugins.typedrequest.TypedResponseError('insufficient scope');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
throw new plugins.typedrequest.TypedResponseError('unauthorized');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private get manager() {
|
|
48
|
+
return this.opsServerRef.dcRouterRef.emailDomainManager;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private registerHandlers(): void {
|
|
52
|
+
// List all email domains
|
|
53
|
+
this.typedrouter.addTypedHandler(
|
|
54
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetEmailDomains>(
|
|
55
|
+
'getEmailDomains',
|
|
56
|
+
async (dataArg) => {
|
|
57
|
+
await this.requireAuth(dataArg, 'email-domains:read' as any);
|
|
58
|
+
if (!this.manager) return { domains: [] };
|
|
59
|
+
return { domains: await this.manager.getAll() };
|
|
60
|
+
},
|
|
61
|
+
),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Get single email domain
|
|
65
|
+
this.typedrouter.addTypedHandler(
|
|
66
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetEmailDomain>(
|
|
67
|
+
'getEmailDomain',
|
|
68
|
+
async (dataArg) => {
|
|
69
|
+
await this.requireAuth(dataArg, 'email-domains:read' as any);
|
|
70
|
+
if (!this.manager) return { domain: null };
|
|
71
|
+
return { domain: await this.manager.getById(dataArg.id) };
|
|
72
|
+
},
|
|
73
|
+
),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// Create email domain
|
|
77
|
+
this.typedrouter.addTypedHandler(
|
|
78
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateEmailDomain>(
|
|
79
|
+
'createEmailDomain',
|
|
80
|
+
async (dataArg) => {
|
|
81
|
+
await this.requireAuth(dataArg, 'email-domains:write' as any);
|
|
82
|
+
if (!this.manager) {
|
|
83
|
+
return { success: false, message: 'EmailDomainManager not initialized' };
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
const domain = await this.manager.createEmailDomain({
|
|
87
|
+
linkedDomainId: dataArg.linkedDomainId,
|
|
88
|
+
dkimSelector: dataArg.dkimSelector,
|
|
89
|
+
dkimKeySize: dataArg.dkimKeySize,
|
|
90
|
+
rotateKeys: dataArg.rotateKeys,
|
|
91
|
+
rotationIntervalDays: dataArg.rotationIntervalDays,
|
|
92
|
+
});
|
|
93
|
+
return { success: true, domain };
|
|
94
|
+
} catch (err: unknown) {
|
|
95
|
+
return { success: false, message: (err as Error).message };
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Update email domain
|
|
102
|
+
this.typedrouter.addTypedHandler(
|
|
103
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateEmailDomain>(
|
|
104
|
+
'updateEmailDomain',
|
|
105
|
+
async (dataArg) => {
|
|
106
|
+
await this.requireAuth(dataArg, 'email-domains:write' as any);
|
|
107
|
+
if (!this.manager) {
|
|
108
|
+
return { success: false, message: 'EmailDomainManager not initialized' };
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
await this.manager.updateEmailDomain(dataArg.id, {
|
|
112
|
+
rotateKeys: dataArg.rotateKeys,
|
|
113
|
+
rotationIntervalDays: dataArg.rotationIntervalDays,
|
|
114
|
+
rateLimits: dataArg.rateLimits,
|
|
115
|
+
});
|
|
116
|
+
return { success: true };
|
|
117
|
+
} catch (err: unknown) {
|
|
118
|
+
return { success: false, message: (err as Error).message };
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// Delete email domain
|
|
125
|
+
this.typedrouter.addTypedHandler(
|
|
126
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteEmailDomain>(
|
|
127
|
+
'deleteEmailDomain',
|
|
128
|
+
async (dataArg) => {
|
|
129
|
+
await this.requireAuth(dataArg, 'email-domains:write' as any);
|
|
130
|
+
if (!this.manager) {
|
|
131
|
+
return { success: false, message: 'EmailDomainManager not initialized' };
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
await this.manager.deleteEmailDomain(dataArg.id);
|
|
135
|
+
return { success: true };
|
|
136
|
+
} catch (err: unknown) {
|
|
137
|
+
return { success: false, message: (err as Error).message };
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
),
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Validate DNS records
|
|
144
|
+
this.typedrouter.addTypedHandler(
|
|
145
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_ValidateEmailDomain>(
|
|
146
|
+
'validateEmailDomain',
|
|
147
|
+
async (dataArg) => {
|
|
148
|
+
await this.requireAuth(dataArg, 'email-domains:read' as any);
|
|
149
|
+
if (!this.manager) {
|
|
150
|
+
return { success: false, message: 'EmailDomainManager not initialized' };
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const records = await this.manager.validateDns(dataArg.id);
|
|
154
|
+
const domain = await this.manager.getById(dataArg.id);
|
|
155
|
+
return { success: true, domain: domain ?? undefined, records };
|
|
156
|
+
} catch (err: unknown) {
|
|
157
|
+
return { success: false, message: (err as Error).message };
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
),
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// Get required DNS records
|
|
164
|
+
this.typedrouter.addTypedHandler(
|
|
165
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetEmailDomainDnsRecords>(
|
|
166
|
+
'getEmailDomainDnsRecords',
|
|
167
|
+
async (dataArg) => {
|
|
168
|
+
await this.requireAuth(dataArg, 'email-domains:read' as any);
|
|
169
|
+
if (!this.manager) return { records: [] };
|
|
170
|
+
return { records: await this.manager.getRequiredDnsRecords(dataArg.id) };
|
|
171
|
+
},
|
|
172
|
+
),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
// Auto-provision DNS records
|
|
176
|
+
this.typedrouter.addTypedHandler(
|
|
177
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_ProvisionEmailDomainDns>(
|
|
178
|
+
'provisionEmailDomainDns',
|
|
179
|
+
async (dataArg) => {
|
|
180
|
+
await this.requireAuth(dataArg, 'email-domains:write' as any);
|
|
181
|
+
if (!this.manager) {
|
|
182
|
+
return { success: false, message: 'EmailDomainManager not initialized' };
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
const provisioned = await this.manager.provisionDnsRecords(dataArg.id);
|
|
186
|
+
return { success: true, provisioned };
|
|
187
|
+
} catch (err: unknown) {
|
|
188
|
+
return { success: false, message: (err as Error).message };
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
),
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -17,4 +17,5 @@ export * from './users.handler.js';
|
|
|
17
17
|
export * from './dns-provider.handler.js';
|
|
18
18
|
export * from './domain.handler.js';
|
|
19
19
|
export * from './dns-record.handler.js';
|
|
20
|
-
export * from './acme-config.handler.js';
|
|
20
|
+
export * from './acme-config.handler.js';
|
|
21
|
+
export * from './email-domain.handler.js';
|
package/ts_web/appstate.ts
CHANGED
|
@@ -2377,6 +2377,129 @@ export const toggleApiTokenAction = routeManagementStatePart.createAction<{
|
|
|
2377
2377
|
}
|
|
2378
2378
|
});
|
|
2379
2379
|
|
|
2380
|
+
// ============================================================================
|
|
2381
|
+
// Email Domains State
|
|
2382
|
+
// ============================================================================
|
|
2383
|
+
|
|
2384
|
+
export interface IEmailDomainsState {
|
|
2385
|
+
domains: interfaces.data.IEmailDomain[];
|
|
2386
|
+
isLoading: boolean;
|
|
2387
|
+
lastUpdated: number;
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
export const emailDomainsStatePart = await appState.getStatePart<IEmailDomainsState>(
|
|
2391
|
+
'emailDomains',
|
|
2392
|
+
{
|
|
2393
|
+
domains: [],
|
|
2394
|
+
isLoading: false,
|
|
2395
|
+
lastUpdated: 0,
|
|
2396
|
+
},
|
|
2397
|
+
'soft',
|
|
2398
|
+
);
|
|
2399
|
+
|
|
2400
|
+
export const fetchEmailDomainsAction = emailDomainsStatePart.createAction(
|
|
2401
|
+
async (statePartArg): Promise<IEmailDomainsState> => {
|
|
2402
|
+
const context = getActionContext();
|
|
2403
|
+
const currentState = statePartArg.getState()!;
|
|
2404
|
+
if (!context.identity) return currentState;
|
|
2405
|
+
|
|
2406
|
+
try {
|
|
2407
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
2408
|
+
interfaces.requests.IReq_GetEmailDomains
|
|
2409
|
+
>('/typedrequest', 'getEmailDomains');
|
|
2410
|
+
const response = await request.fire({ identity: context.identity });
|
|
2411
|
+
return {
|
|
2412
|
+
...currentState,
|
|
2413
|
+
domains: response.domains,
|
|
2414
|
+
isLoading: false,
|
|
2415
|
+
lastUpdated: Date.now(),
|
|
2416
|
+
};
|
|
2417
|
+
} catch {
|
|
2418
|
+
return { ...currentState, isLoading: false };
|
|
2419
|
+
}
|
|
2420
|
+
},
|
|
2421
|
+
);
|
|
2422
|
+
|
|
2423
|
+
export const createEmailDomainAction = emailDomainsStatePart.createAction<{
|
|
2424
|
+
linkedDomainId: string;
|
|
2425
|
+
dkimSelector?: string;
|
|
2426
|
+
dkimKeySize?: number;
|
|
2427
|
+
rotateKeys?: boolean;
|
|
2428
|
+
rotationIntervalDays?: number;
|
|
2429
|
+
}>(async (statePartArg, args, actionContext) => {
|
|
2430
|
+
const context = getActionContext();
|
|
2431
|
+
const currentState = statePartArg.getState()!;
|
|
2432
|
+
try {
|
|
2433
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
2434
|
+
interfaces.requests.IReq_CreateEmailDomain
|
|
2435
|
+
>('/typedrequest', 'createEmailDomain');
|
|
2436
|
+
await request.fire({ identity: context.identity!, ...args });
|
|
2437
|
+
return await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
2438
|
+
} catch {
|
|
2439
|
+
return currentState;
|
|
2440
|
+
}
|
|
2441
|
+
});
|
|
2442
|
+
|
|
2443
|
+
export const deleteEmailDomainAction = emailDomainsStatePart.createAction<string>(
|
|
2444
|
+
async (statePartArg, id, actionContext) => {
|
|
2445
|
+
const context = getActionContext();
|
|
2446
|
+
const currentState = statePartArg.getState()!;
|
|
2447
|
+
try {
|
|
2448
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
2449
|
+
interfaces.requests.IReq_DeleteEmailDomain
|
|
2450
|
+
>('/typedrequest', 'deleteEmailDomain');
|
|
2451
|
+
await request.fire({ identity: context.identity!, id });
|
|
2452
|
+
return await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
2453
|
+
} catch {
|
|
2454
|
+
return currentState;
|
|
2455
|
+
}
|
|
2456
|
+
},
|
|
2457
|
+
);
|
|
2458
|
+
|
|
2459
|
+
export const validateEmailDomainAction = emailDomainsStatePart.createAction<string>(
|
|
2460
|
+
async (statePartArg, id, actionContext) => {
|
|
2461
|
+
const context = getActionContext();
|
|
2462
|
+
const currentState = statePartArg.getState()!;
|
|
2463
|
+
try {
|
|
2464
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
2465
|
+
interfaces.requests.IReq_ValidateEmailDomain
|
|
2466
|
+
>('/typedrequest', 'validateEmailDomain');
|
|
2467
|
+
await request.fire({ identity: context.identity!, id });
|
|
2468
|
+
return await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
2469
|
+
} catch {
|
|
2470
|
+
return currentState;
|
|
2471
|
+
}
|
|
2472
|
+
},
|
|
2473
|
+
);
|
|
2474
|
+
|
|
2475
|
+
export const provisionEmailDomainDnsAction = emailDomainsStatePart.createAction<string>(
|
|
2476
|
+
async (statePartArg, id, actionContext) => {
|
|
2477
|
+
const context = getActionContext();
|
|
2478
|
+
const currentState = statePartArg.getState()!;
|
|
2479
|
+
try {
|
|
2480
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
2481
|
+
interfaces.requests.IReq_ProvisionEmailDomainDns
|
|
2482
|
+
>('/typedrequest', 'provisionEmailDomainDns');
|
|
2483
|
+
await request.fire({ identity: context.identity!, id });
|
|
2484
|
+
return await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
2485
|
+
} catch {
|
|
2486
|
+
return currentState;
|
|
2487
|
+
}
|
|
2488
|
+
},
|
|
2489
|
+
);
|
|
2490
|
+
|
|
2491
|
+
// ============================================================================
|
|
2492
|
+
// Email Domain Standalone Functions
|
|
2493
|
+
// ============================================================================
|
|
2494
|
+
|
|
2495
|
+
export async function fetchEmailDomainDnsRecords(id: string) {
|
|
2496
|
+
const context = getActionContext();
|
|
2497
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
2498
|
+
interfaces.requests.IReq_GetEmailDomainDnsRecords
|
|
2499
|
+
>('/typedrequest', 'getEmailDomainDnsRecords');
|
|
2500
|
+
return request.fire({ identity: context.identity!, id });
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2380
2503
|
// ============================================================================
|
|
2381
2504
|
// TypedSocket Client for Real-time Log Streaming
|
|
2382
2505
|
// ============================================================================
|
|
@@ -54,51 +54,6 @@ export class OpsViewCertificates extends DeesElement {
|
|
|
54
54
|
gap: 24px;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
.acmeTileHeader {
|
|
58
|
-
display: flex;
|
|
59
|
-
justify-content: space-between;
|
|
60
|
-
align-items: center;
|
|
61
|
-
width: 100%;
|
|
62
|
-
padding: 8px 12px;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.acmeTileHeading {
|
|
66
|
-
font-size: 14px;
|
|
67
|
-
font-weight: 600;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.acmeEmptyContent {
|
|
71
|
-
padding: 16px;
|
|
72
|
-
font-size: 13px;
|
|
73
|
-
line-height: 1.5;
|
|
74
|
-
color: ${cssManager.bdTheme('#78350f', '#fde68a')};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.acmeGrid {
|
|
78
|
-
display: grid;
|
|
79
|
-
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
80
|
-
gap: 12px 24px;
|
|
81
|
-
padding: 16px;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.acmeField {
|
|
85
|
-
display: flex;
|
|
86
|
-
flex-direction: column;
|
|
87
|
-
gap: 2px;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.acmeLabel {
|
|
91
|
-
font-size: 11px;
|
|
92
|
-
text-transform: uppercase;
|
|
93
|
-
letter-spacing: 0.03em;
|
|
94
|
-
color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.acmeValue {
|
|
98
|
-
font-size: 13px;
|
|
99
|
-
color: ${cssManager.bdTheme('#111827', '#f3f4f6')};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
57
|
.statusBadge {
|
|
103
58
|
display: inline-flex;
|
|
104
59
|
align-items: center;
|
|
@@ -227,60 +182,26 @@ export class OpsViewCertificates extends DeesElement {
|
|
|
227
182
|
|
|
228
183
|
if (!config) {
|
|
229
184
|
return html`
|
|
230
|
-
<dees-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
.type=${'highlighted'}
|
|
236
|
-
>Configure</dees-button>
|
|
237
|
-
</div>
|
|
238
|
-
<div class="acmeEmptyContent">
|
|
239
|
-
No ACME configuration yet. Click <strong>Configure</strong> to set up automated TLS
|
|
240
|
-
certificate issuance via Let's Encrypt. You'll also need at least one DNS provider
|
|
241
|
-
under <strong>Domains > Providers</strong>.
|
|
242
|
-
</div>
|
|
243
|
-
</dees-tile>
|
|
185
|
+
<dees-settings
|
|
186
|
+
.heading=${'ACME Settings'}
|
|
187
|
+
.description=${'No ACME configuration yet. Click Configure to set up automated TLS certificate issuance via Let\'s Encrypt. You\'ll also need at least one DNS provider under Domains > Providers.'}
|
|
188
|
+
.actions=${[{ name: 'Configure', action: () => this.showEditAcmeDialog() }]}
|
|
189
|
+
></dees-settings>
|
|
244
190
|
`;
|
|
245
191
|
}
|
|
246
192
|
|
|
247
193
|
return html`
|
|
248
|
-
<dees-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
<span class="acmeLabel">Status</span>
|
|
260
|
-
<span class="acmeValue">
|
|
261
|
-
<span class="statusBadge ${config.enabled ? 'valid' : 'unknown'}">
|
|
262
|
-
${config.enabled ? 'enabled' : 'disabled'}
|
|
263
|
-
</span>
|
|
264
|
-
</span>
|
|
265
|
-
</div>
|
|
266
|
-
<div class="acmeField">
|
|
267
|
-
<span class="acmeLabel">Mode</span>
|
|
268
|
-
<span class="acmeValue">
|
|
269
|
-
<span class="statusBadge ${config.useProduction ? 'valid' : 'provisioning'}">
|
|
270
|
-
${config.useProduction ? 'production' : 'staging'}
|
|
271
|
-
</span>
|
|
272
|
-
</span>
|
|
273
|
-
</div>
|
|
274
|
-
<div class="acmeField">
|
|
275
|
-
<span class="acmeLabel">Auto-renew</span>
|
|
276
|
-
<span class="acmeValue">${config.autoRenew ? 'on' : 'off'}</span>
|
|
277
|
-
</div>
|
|
278
|
-
<div class="acmeField">
|
|
279
|
-
<span class="acmeLabel">Renewal threshold</span>
|
|
280
|
-
<span class="acmeValue">${config.renewThresholdDays} days</span>
|
|
281
|
-
</div>
|
|
282
|
-
</div>
|
|
283
|
-
</dees-tile>
|
|
194
|
+
<dees-settings
|
|
195
|
+
.heading=${'ACME Settings'}
|
|
196
|
+
.settingsFields=${[
|
|
197
|
+
{ key: 'email', label: 'Account email', value: config.accountEmail || '(not set)' },
|
|
198
|
+
{ key: 'status', label: 'Status', value: config.enabled ? 'enabled' : 'disabled' },
|
|
199
|
+
{ key: 'mode', label: 'Mode', value: config.useProduction ? 'production' : 'staging' },
|
|
200
|
+
{ key: 'autoRenew', label: 'Auto-renew', value: config.autoRenew ? 'on' : 'off' },
|
|
201
|
+
{ key: 'threshold', label: 'Renewal threshold', value: `${config.renewThresholdDays} days` },
|
|
202
|
+
]}
|
|
203
|
+
.actions=${[{ name: 'Edit', action: () => this.showEditAcmeDialog() }]}
|
|
204
|
+
></dees-settings>
|
|
284
205
|
`;
|
|
285
206
|
}
|
|
286
207
|
|