@serve.zone/dcrouter 12.1.0 → 12.2.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_serve/bundle.js +752 -688
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.d.ts +6 -1
- package/dist_ts/classes.dcrouter.js +11 -3
- package/dist_ts/config/classes.db-seeder.d.ts +25 -0
- package/dist_ts/config/classes.db-seeder.js +69 -0
- package/dist_ts/config/classes.reference-resolver.d.ts +80 -0
- package/dist_ts/config/classes.reference-resolver.js +482 -0
- package/dist_ts/config/classes.route-config-manager.d.ts +13 -3
- package/dist_ts/config/classes.route-config-manager.js +53 -3
- package/dist_ts/config/index.d.ts +2 -0
- package/dist_ts/config/index.js +3 -1
- package/dist_ts/db/documents/classes.network-target.doc.d.ts +15 -0
- package/dist_ts/db/documents/classes.network-target.doc.js +118 -0
- package/dist_ts/db/documents/classes.security-profile.doc.d.ts +16 -0
- package/dist_ts/db/documents/classes.security-profile.doc.js +118 -0
- package/dist_ts/db/documents/classes.stored-route.doc.d.ts +2 -0
- package/dist_ts/db/documents/classes.stored-route.doc.js +8 -2
- package/dist_ts/db/documents/index.d.ts +2 -0
- package/dist_ts/db/documents/index.js +3 -1
- package/dist_ts/opsserver/classes.opsserver.d.ts +2 -0
- package/dist_ts/opsserver/classes.opsserver.js +5 -1
- package/dist_ts/opsserver/handlers/index.d.ts +2 -0
- package/dist_ts/opsserver/handlers/index.js +3 -1
- package/dist_ts/opsserver/handlers/network-target.handler.d.ts +10 -0
- package/dist_ts/opsserver/handlers/network-target.handler.js +117 -0
- package/dist_ts/opsserver/handlers/route-management.handler.js +3 -2
- package/dist_ts/opsserver/handlers/security-profile.handler.d.ts +10 -0
- package/dist_ts/opsserver/handlers/security-profile.handler.js +119 -0
- package/dist_ts_interfaces/data/route-management.d.ts +48 -1
- package/dist_ts_interfaces/requests/index.d.ts +2 -0
- package/dist_ts_interfaces/requests/index.js +3 -1
- package/dist_ts_interfaces/requests/network-targets.d.ts +102 -0
- package/dist_ts_interfaces/requests/network-targets.js +2 -0
- package/dist_ts_interfaces/requests/route-management.d.ts +3 -1
- package/dist_ts_interfaces/requests/security-profiles.d.ts +102 -0
- package/dist_ts_interfaces/requests/security-profiles.js +2 -0
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +43 -0
- package/dist_ts_web/appstate.js +176 -2
- package/dist_ts_web/elements/index.d.ts +2 -0
- package/dist_ts_web/elements/index.js +3 -1
- package/dist_ts_web/elements/ops-dashboard.js +13 -1
- package/dist_ts_web/elements/ops-view-networktargets.d.ts +17 -0
- package/dist_ts_web/elements/ops-view-networktargets.js +247 -0
- package/dist_ts_web/elements/ops-view-securityprofiles.d.ts +17 -0
- package/dist_ts_web/elements/ops-view-securityprofiles.js +276 -0
- package/dist_ts_web/router.d.ts +1 -1
- package/dist_ts_web/router.js +2 -2
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +19 -1
- package/ts/config/classes.db-seeder.ts +95 -0
- package/ts/config/classes.reference-resolver.ts +576 -0
- package/ts/config/classes.route-config-manager.ts +64 -1
- package/ts/config/index.ts +3 -1
- package/ts/db/documents/classes.network-target.doc.ts +48 -0
- package/ts/db/documents/classes.security-profile.doc.ts +49 -0
- package/ts/db/documents/classes.stored-route.doc.ts +4 -0
- package/ts/db/documents/index.ts +2 -0
- package/ts/opsserver/classes.opsserver.ts +4 -0
- package/ts/opsserver/handlers/index.ts +3 -1
- package/ts/opsserver/handlers/network-target.handler.ts +167 -0
- package/ts/opsserver/handlers/route-management.handler.ts +2 -1
- package/ts/opsserver/handlers/security-profile.handler.ts +169 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +243 -1
- package/ts_web/elements/index.ts +2 -0
- package/ts_web/elements/ops-dashboard.ts +12 -0
- package/ts_web/elements/ops-view-networktargets.ts +215 -0
- package/ts_web/elements/ops-view-securityprofiles.ts +243 -0
- package/ts_web/router.ts +1 -1
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DeesElement,
|
|
3
|
+
html,
|
|
4
|
+
customElement,
|
|
5
|
+
type TemplateResult,
|
|
6
|
+
css,
|
|
7
|
+
state,
|
|
8
|
+
cssManager,
|
|
9
|
+
} from '@design.estate/dees-element';
|
|
10
|
+
import * as appstate from '../appstate.js';
|
|
11
|
+
import * as interfaces from '../../dist_ts_interfaces/index.js';
|
|
12
|
+
import { viewHostCss } from './shared/css.js';
|
|
13
|
+
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
14
|
+
|
|
15
|
+
declare global {
|
|
16
|
+
interface HTMLElementTagNameMap {
|
|
17
|
+
'ops-view-securityprofiles': OpsViewSecurityProfiles;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@customElement('ops-view-securityprofiles')
|
|
22
|
+
export class OpsViewSecurityProfiles extends DeesElement {
|
|
23
|
+
@state()
|
|
24
|
+
accessor profilesState: appstate.IProfilesTargetsState = appstate.profilesTargetsStatePart.getState()!;
|
|
25
|
+
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
const sub = appstate.profilesTargetsStatePart.select().subscribe((newState) => {
|
|
29
|
+
this.profilesState = newState;
|
|
30
|
+
});
|
|
31
|
+
this.rxSubscriptions.push(sub);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async connectedCallback() {
|
|
35
|
+
await super.connectedCallback();
|
|
36
|
+
await appstate.profilesTargetsStatePart.dispatchAction(appstate.fetchProfilesAndTargetsAction, null);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public static styles = [
|
|
40
|
+
cssManager.defaultStyles,
|
|
41
|
+
viewHostCss,
|
|
42
|
+
css`
|
|
43
|
+
.profilesContainer {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
gap: 24px;
|
|
47
|
+
}
|
|
48
|
+
`,
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
public render(): TemplateResult {
|
|
52
|
+
const profiles = this.profilesState.profiles;
|
|
53
|
+
|
|
54
|
+
const statsTiles: IStatsTile[] = [
|
|
55
|
+
{
|
|
56
|
+
id: 'totalProfiles',
|
|
57
|
+
title: 'Total Profiles',
|
|
58
|
+
type: 'number',
|
|
59
|
+
value: profiles.length,
|
|
60
|
+
icon: 'lucide:shieldCheck',
|
|
61
|
+
description: 'Reusable security profiles',
|
|
62
|
+
color: '#3b82f6',
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
return html`
|
|
67
|
+
<div class="profilesContainer">
|
|
68
|
+
<dees-statsgrid .tiles=${statsTiles}></dees-statsgrid>
|
|
69
|
+
<dees-table
|
|
70
|
+
.heading1=${'Security Profiles'}
|
|
71
|
+
.heading2=${'Reusable security configurations for routes'}
|
|
72
|
+
.data=${profiles}
|
|
73
|
+
.displayFunction=${(profile: interfaces.data.ISecurityProfile) => ({
|
|
74
|
+
Name: profile.name,
|
|
75
|
+
Description: profile.description || '-',
|
|
76
|
+
'IP Allow List': (profile.security?.ipAllowList || []).join(', ') || '-',
|
|
77
|
+
'IP Block List': (profile.security?.ipBlockList || []).join(', ') || '-',
|
|
78
|
+
'Max Connections': profile.security?.maxConnections ?? '-',
|
|
79
|
+
'Rate Limit': profile.security?.rateLimit?.enabled ? `${profile.security.rateLimit.maxRequests}/${profile.security.rateLimit.window}s` : '-',
|
|
80
|
+
Extends: (profile.extendsProfiles || []).length > 0
|
|
81
|
+
? profile.extendsProfiles!.map(id => {
|
|
82
|
+
const p = profiles.find(pp => pp.id === id);
|
|
83
|
+
return p ? p.name : id.slice(0, 8);
|
|
84
|
+
}).join(', ')
|
|
85
|
+
: '-',
|
|
86
|
+
})}
|
|
87
|
+
.dataActions=${[
|
|
88
|
+
{
|
|
89
|
+
name: 'Create Profile',
|
|
90
|
+
iconName: 'lucide:plus',
|
|
91
|
+
type: ['header' as const],
|
|
92
|
+
actionFunc: async (_: any, table: any) => {
|
|
93
|
+
await this.showCreateProfileDialog(table);
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'Refresh',
|
|
98
|
+
iconName: 'lucide:rotateCw',
|
|
99
|
+
type: ['header' as const],
|
|
100
|
+
actionFunc: async () => {
|
|
101
|
+
await appstate.profilesTargetsStatePart.dispatchAction(appstate.fetchProfilesAndTargetsAction, null);
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'Edit',
|
|
106
|
+
iconName: 'lucide:pencil',
|
|
107
|
+
type: ['contextmenu' as const],
|
|
108
|
+
actionFunc: async (profile: interfaces.data.ISecurityProfile, table: any) => {
|
|
109
|
+
await this.showEditProfileDialog(profile, table);
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'Delete',
|
|
114
|
+
iconName: 'lucide:trash2',
|
|
115
|
+
type: ['contextmenu' as const],
|
|
116
|
+
actionFunc: async (profile: interfaces.data.ISecurityProfile) => {
|
|
117
|
+
await this.deleteProfile(profile);
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
]}
|
|
121
|
+
></dees-table>
|
|
122
|
+
</div>
|
|
123
|
+
`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private async showCreateProfileDialog(table: any) {
|
|
127
|
+
const { DeesModal } = await import('@design.estate/dees-catalog');
|
|
128
|
+
DeesModal.createAndShow({
|
|
129
|
+
heading: 'Create Security Profile',
|
|
130
|
+
content: html`
|
|
131
|
+
<dees-form>
|
|
132
|
+
<dees-input-text .key=${'name'} .label=${'Name'} .required=${true}></dees-input-text>
|
|
133
|
+
<dees-input-text .key=${'description'} .label=${'Description'}></dees-input-text>
|
|
134
|
+
<dees-input-text .key=${'ipAllowList'} .label=${'IP Allow List (comma-separated)'}></dees-input-text>
|
|
135
|
+
<dees-input-text .key=${'ipBlockList'} .label=${'IP Block List (comma-separated)'}></dees-input-text>
|
|
136
|
+
<dees-input-text .key=${'maxConnections'} .label=${'Max Connections'}></dees-input-text>
|
|
137
|
+
</dees-form>
|
|
138
|
+
`,
|
|
139
|
+
menuOptions: [
|
|
140
|
+
{
|
|
141
|
+
name: 'Create',
|
|
142
|
+
action: async (modalArg: any) => {
|
|
143
|
+
const form = modalArg.shadowRoot!.querySelector('dees-form');
|
|
144
|
+
const data = await form.collectFormData();
|
|
145
|
+
const ipAllowList = data.ipAllowList
|
|
146
|
+
? String(data.ipAllowList).split(',').map((s: string) => s.trim()).filter(Boolean)
|
|
147
|
+
: undefined;
|
|
148
|
+
const ipBlockList = data.ipBlockList
|
|
149
|
+
? String(data.ipBlockList).split(',').map((s: string) => s.trim()).filter(Boolean)
|
|
150
|
+
: undefined;
|
|
151
|
+
const maxConnections = data.maxConnections ? parseInt(String(data.maxConnections)) : undefined;
|
|
152
|
+
|
|
153
|
+
await appstate.profilesTargetsStatePart.dispatchAction(appstate.createProfileAction, {
|
|
154
|
+
name: String(data.name),
|
|
155
|
+
description: data.description ? String(data.description) : undefined,
|
|
156
|
+
security: {
|
|
157
|
+
...(ipAllowList ? { ipAllowList } : {}),
|
|
158
|
+
...(ipBlockList ? { ipBlockList } : {}),
|
|
159
|
+
...(maxConnections ? { maxConnections } : {}),
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
modalArg.destroy();
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
|
166
|
+
],
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private async showEditProfileDialog(profile: interfaces.data.ISecurityProfile, table: any) {
|
|
171
|
+
const { DeesModal } = await import('@design.estate/dees-catalog');
|
|
172
|
+
DeesModal.createAndShow({
|
|
173
|
+
heading: `Edit Profile: ${profile.name}`,
|
|
174
|
+
content: html`
|
|
175
|
+
<dees-form>
|
|
176
|
+
<dees-input-text .key=${'name'} .label=${'Name'} .value=${profile.name}></dees-input-text>
|
|
177
|
+
<dees-input-text .key=${'description'} .label=${'Description'} .value=${profile.description || ''}></dees-input-text>
|
|
178
|
+
<dees-input-text .key=${'ipAllowList'} .label=${'IP Allow List (comma-separated)'} .value=${(profile.security?.ipAllowList || []).join(', ')}></dees-input-text>
|
|
179
|
+
<dees-input-text .key=${'ipBlockList'} .label=${'IP Block List (comma-separated)'} .value=${(profile.security?.ipBlockList || []).join(', ')}></dees-input-text>
|
|
180
|
+
<dees-input-text .key=${'maxConnections'} .label=${'Max Connections'} .value=${String(profile.security?.maxConnections || '')}></dees-input-text>
|
|
181
|
+
</dees-form>
|
|
182
|
+
`,
|
|
183
|
+
menuOptions: [
|
|
184
|
+
{
|
|
185
|
+
name: 'Save',
|
|
186
|
+
action: async (modalArg: any) => {
|
|
187
|
+
const form = modalArg.shadowRoot!.querySelector('dees-form');
|
|
188
|
+
const data = await form.collectFormData();
|
|
189
|
+
const ipAllowList = data.ipAllowList
|
|
190
|
+
? String(data.ipAllowList).split(',').map((s: string) => s.trim()).filter(Boolean)
|
|
191
|
+
: [];
|
|
192
|
+
const ipBlockList = data.ipBlockList
|
|
193
|
+
? String(data.ipBlockList).split(',').map((s: string) => s.trim()).filter(Boolean)
|
|
194
|
+
: [];
|
|
195
|
+
const maxConnections = data.maxConnections ? parseInt(String(data.maxConnections)) : undefined;
|
|
196
|
+
|
|
197
|
+
await appstate.profilesTargetsStatePart.dispatchAction(appstate.updateProfileAction, {
|
|
198
|
+
id: profile.id,
|
|
199
|
+
name: String(data.name),
|
|
200
|
+
description: data.description ? String(data.description) : undefined,
|
|
201
|
+
security: {
|
|
202
|
+
ipAllowList,
|
|
203
|
+
ipBlockList,
|
|
204
|
+
...(maxConnections ? { maxConnections } : {}),
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
modalArg.destroy();
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
|
211
|
+
],
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private async deleteProfile(profile: interfaces.data.ISecurityProfile) {
|
|
216
|
+
await appstate.profilesTargetsStatePart.dispatchAction(appstate.deleteProfileAction, {
|
|
217
|
+
id: profile.id,
|
|
218
|
+
force: false,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const currentState = appstate.profilesTargetsStatePart.getState()!;
|
|
222
|
+
if (currentState.error?.includes('in use')) {
|
|
223
|
+
const { DeesModal } = await import('@design.estate/dees-catalog');
|
|
224
|
+
DeesModal.createAndShow({
|
|
225
|
+
heading: 'Profile In Use',
|
|
226
|
+
content: html`<p>${currentState.error} Force delete?</p>`,
|
|
227
|
+
menuOptions: [
|
|
228
|
+
{
|
|
229
|
+
name: 'Force Delete',
|
|
230
|
+
action: async (modalArg: any) => {
|
|
231
|
+
await appstate.profilesTargetsStatePart.dispatchAction(appstate.deleteProfileAction, {
|
|
232
|
+
id: profile.id,
|
|
233
|
+
force: true,
|
|
234
|
+
});
|
|
235
|
+
modalArg.destroy();
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
|
239
|
+
],
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
package/ts_web/router.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as appstate from './appstate.js';
|
|
|
3
3
|
|
|
4
4
|
const SmartRouter = plugins.domtools.plugins.smartrouter.SmartRouter;
|
|
5
5
|
|
|
6
|
-
export const validViews = ['overview', 'network', 'emails', 'logs', 'routes', 'apitokens', 'configuration', 'security', 'certificates', 'remoteingress', 'vpn'] as const;
|
|
6
|
+
export const validViews = ['overview', 'network', 'emails', 'logs', 'routes', 'apitokens', 'configuration', 'security', 'certificates', 'remoteingress', 'vpn', 'securityprofiles', 'networktargets'] as const;
|
|
7
7
|
|
|
8
8
|
export type TValidView = typeof validViews[number];
|
|
9
9
|
|