@serve.zone/dcrouter 13.27.1 → 13.29.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/.smartconfig.json +32 -10
- package/dist_serve/bundle.js +930 -799
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.d.ts +9 -1
- package/dist_ts/classes.dcrouter.js +22 -7
- package/dist_ts/config/classes.gateway-client-manager.d.ts +22 -0
- package/dist_ts/config/classes.gateway-client-manager.js +101 -0
- package/dist_ts/config/classes.route-config-manager.js +8 -7
- package/dist_ts/config/index.d.ts +1 -0
- package/dist_ts/config/index.js +2 -1
- package/dist_ts/db/documents/classes.gateway-client.doc.d.ts +18 -0
- package/dist_ts/db/documents/classes.gateway-client.doc.js +133 -0
- package/dist_ts/db/documents/index.d.ts +1 -0
- package/dist_ts/db/documents/index.js +2 -1
- package/dist_ts/opsserver/classes.opsserver.js +4 -1
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +21 -6
- package/dist_ts/opsserver/handlers/admin.handler.js +188 -29
- package/dist_ts/opsserver/handlers/certificate.handler.js +5 -1
- package/dist_ts/opsserver/handlers/target-profile.handler.js +3 -1
- package/dist_ts/opsserver/handlers/users.handler.js +2 -2
- package/dist_ts/opsserver/handlers/workhoster.handler.d.ts +4 -0
- package/dist_ts/opsserver/handlers/workhoster.handler.js +146 -16
- package/dist_ts/plugins.d.ts +2 -0
- package/dist_ts/plugins.js +4 -1
- package/dist_ts/vpn/classes.vpn-manager.d.ts +2 -0
- package/dist_ts/vpn/classes.vpn-manager.js +41 -20
- package/dist_ts_apiclient/classes.workhoster.d.ts +1 -0
- package/dist_ts_apiclient/classes.workhoster.js +5 -1
- package/dist_ts_interfaces/data/workhoster.d.ts +28 -3
- package/dist_ts_interfaces/requests/admin.d.ts +38 -0
- package/dist_ts_interfaces/requests/users.d.ts +2 -5
- package/dist_ts_interfaces/requests/workhoster.d.ts +83 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +46 -0
- package/dist_ts_web/appstate.js +105 -1
- package/dist_ts_web/elements/access/ops-view-apitokens.js +2 -1
- package/dist_ts_web/elements/access/ops-view-gatewayclients.d.ts +15 -0
- package/dist_ts_web/elements/access/ops-view-gatewayclients.js +293 -0
- package/dist_ts_web/elements/domains/ops-view-certificates.d.ts +6 -0
- package/dist_ts_web/elements/domains/ops-view-certificates.js +155 -13
- package/dist_ts_web/elements/network/ops-view-routes.js +2 -1
- package/dist_ts_web/elements/ops-dashboard.d.ts +4 -0
- package/dist_ts_web/elements/ops-dashboard.js +102 -3
- package/dist_ts_web/router.js +3 -3
- package/package.json +15 -22
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +30 -6
- package/ts/config/classes.gateway-client-manager.ts +117 -0
- package/ts/config/classes.route-config-manager.ts +8 -6
- package/ts/config/index.ts +2 -1
- package/ts/db/documents/classes.gateway-client.doc.ts +54 -0
- package/ts/db/documents/index.ts +1 -0
- package/ts/opsserver/classes.opsserver.ts +3 -0
- package/ts/opsserver/handlers/admin.handler.ts +244 -32
- package/ts/opsserver/handlers/certificate.handler.ts +5 -0
- package/ts/opsserver/handlers/target-profile.handler.ts +2 -0
- package/ts/opsserver/handlers/users.handler.ts +1 -1
- package/ts/opsserver/handlers/workhoster.handler.ts +191 -17
- package/ts/plugins.ts +7 -0
- package/ts/vpn/classes.vpn-manager.ts +56 -25
- package/ts_apiclient/classes.workhoster.ts +8 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +160 -0
- package/ts_web/elements/access/ops-view-apitokens.ts +1 -0
- package/ts_web/elements/access/ops-view-gatewayclients.ts +250 -0
- package/ts_web/elements/domains/ops-view-certificates.ts +166 -11
- package/ts_web/elements/network/ops-view-routes.ts +1 -0
- package/ts_web/elements/ops-dashboard.ts +102 -0
- package/ts_web/router.ts +2 -2
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { DcRouterDb } from '../classes.dcrouter-db.js';
|
|
3
|
+
import type { IApiTokenPolicy, TGatewayClientType } from '../../../ts_interfaces/data/route-management.js';
|
|
4
|
+
|
|
5
|
+
const getDb = () => DcRouterDb.getInstance().getDb();
|
|
6
|
+
|
|
7
|
+
@plugins.smartdata.Collection(() => getDb())
|
|
8
|
+
export class GatewayClientDoc extends plugins.smartdata.SmartDataDbDoc<GatewayClientDoc, GatewayClientDoc> {
|
|
9
|
+
@plugins.smartdata.unI()
|
|
10
|
+
@plugins.smartdata.svDb()
|
|
11
|
+
public id!: string;
|
|
12
|
+
|
|
13
|
+
@plugins.smartdata.svDb()
|
|
14
|
+
public type!: TGatewayClientType;
|
|
15
|
+
|
|
16
|
+
@plugins.smartdata.svDb()
|
|
17
|
+
public name: string = '';
|
|
18
|
+
|
|
19
|
+
@plugins.smartdata.svDb()
|
|
20
|
+
public description?: string;
|
|
21
|
+
|
|
22
|
+
@plugins.smartdata.svDb()
|
|
23
|
+
public hostnamePatterns: string[] = [];
|
|
24
|
+
|
|
25
|
+
@plugins.smartdata.svDb()
|
|
26
|
+
public allowedRouteTargets: NonNullable<IApiTokenPolicy['allowedRouteTargets']> = [];
|
|
27
|
+
|
|
28
|
+
@plugins.smartdata.svDb()
|
|
29
|
+
public capabilities: NonNullable<IApiTokenPolicy['capabilities']> = {};
|
|
30
|
+
|
|
31
|
+
@plugins.smartdata.svDb()
|
|
32
|
+
public enabled: boolean = true;
|
|
33
|
+
|
|
34
|
+
@plugins.smartdata.svDb()
|
|
35
|
+
public createdAt!: number;
|
|
36
|
+
|
|
37
|
+
@plugins.smartdata.svDb()
|
|
38
|
+
public updatedAt!: number;
|
|
39
|
+
|
|
40
|
+
@plugins.smartdata.svDb()
|
|
41
|
+
public createdBy!: string;
|
|
42
|
+
|
|
43
|
+
constructor() {
|
|
44
|
+
super();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public static async findById(id: string): Promise<GatewayClientDoc | null> {
|
|
48
|
+
return await GatewayClientDoc.getInstance({ id });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public static async findAll(): Promise<GatewayClientDoc[]> {
|
|
52
|
+
return await GatewayClientDoc.getInstances({});
|
|
53
|
+
}
|
|
54
|
+
}
|
package/ts/db/documents/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './classes.security-policy-audit.doc.js';
|
|
|
8
8
|
// Config document classes
|
|
9
9
|
export * from './classes.route.doc.js';
|
|
10
10
|
export * from './classes.api-token.doc.js';
|
|
11
|
+
export * from './classes.gateway-client.doc.js';
|
|
11
12
|
export * from './classes.source-profile.doc.js';
|
|
12
13
|
export * from './classes.target-profile.doc.js';
|
|
13
14
|
export * from './classes.network-target.doc.js';
|
|
@@ -113,6 +113,9 @@ export class OpsServer {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
public async stop() {
|
|
116
|
+
if (this.adminHandler) {
|
|
117
|
+
await this.adminHandler.stop();
|
|
118
|
+
}
|
|
116
119
|
// Clean up log handler streams and push destination before stopping the server
|
|
117
120
|
if (this.logsHandler) {
|
|
118
121
|
this.logsHandler.cleanup();
|
|
@@ -8,19 +8,33 @@ export interface IJwtData {
|
|
|
8
8
|
expiresAt: number;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
type TAdminUser = {
|
|
12
|
+
id: string;
|
|
13
|
+
username: string;
|
|
14
|
+
email?: string;
|
|
15
|
+
name?: string;
|
|
16
|
+
role: string;
|
|
17
|
+
status?: 'active' | 'disabled';
|
|
18
|
+
authSources?: Array<'local' | 'idp.global'>;
|
|
19
|
+
};
|
|
20
|
+
|
|
11
21
|
export class AdminHandler {
|
|
12
22
|
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
13
23
|
|
|
14
24
|
// JWT instance
|
|
15
25
|
public smartjwtInstance!: plugins.smartjwt.SmartJwt<IJwtData>;
|
|
16
26
|
|
|
17
|
-
//
|
|
27
|
+
// Ephemeral bootstrap users. Persisted accounts take over once an active admin exists.
|
|
18
28
|
private users = new Map<string, {
|
|
19
29
|
id: string;
|
|
20
30
|
username: string;
|
|
21
31
|
password: string;
|
|
22
32
|
role: string;
|
|
23
33
|
}>();
|
|
34
|
+
|
|
35
|
+
private accountStore?: plugins.idpSdkServer.SmartdataAccountStore;
|
|
36
|
+
private idpClient?: plugins.idpSdkServer.IdpGlobalServerClient;
|
|
37
|
+
private ownsIdpClient = false;
|
|
24
38
|
|
|
25
39
|
constructor(private opsServerRef: OpsServer) {
|
|
26
40
|
// Add this handler's router to the parent
|
|
@@ -32,6 +46,14 @@ export class AdminHandler {
|
|
|
32
46
|
this.initializeDefaultUsers();
|
|
33
47
|
this.registerHandlers();
|
|
34
48
|
}
|
|
49
|
+
|
|
50
|
+
public async stop(): Promise<void> {
|
|
51
|
+
if (this.ownsIdpClient) {
|
|
52
|
+
await this.idpClient?.stop();
|
|
53
|
+
}
|
|
54
|
+
this.idpClient = undefined;
|
|
55
|
+
this.ownsIdpClient = false;
|
|
56
|
+
}
|
|
35
57
|
|
|
36
58
|
private async initializeJwt(): Promise<void> {
|
|
37
59
|
this.smartjwtInstance = new plugins.smartjwt.SmartJwt();
|
|
@@ -61,54 +83,120 @@ export class AdminHandler {
|
|
|
61
83
|
}
|
|
62
84
|
|
|
63
85
|
/**
|
|
64
|
-
* Return a safe projection of the
|
|
86
|
+
* Return a safe projection of the active user source — excludes password fields.
|
|
65
87
|
* Used by UsersHandler to serve the admin-only listUsers endpoint.
|
|
66
88
|
*/
|
|
67
|
-
public listUsers():
|
|
89
|
+
public async listUsers(): Promise<interfaces.requests.IAdminUserProjection[]> {
|
|
90
|
+
if (await this.hasPersistentAdminAccount()) {
|
|
91
|
+
const store = this.getAccountStore();
|
|
92
|
+
const accounts = await store!.listAccounts();
|
|
93
|
+
return accounts.map((accountArg) => this.accountToUser(accountArg));
|
|
94
|
+
}
|
|
95
|
+
|
|
68
96
|
return Array.from(this.users.values()).map((user) => ({
|
|
69
97
|
id: user.id,
|
|
70
98
|
username: user.username,
|
|
71
99
|
role: user.role,
|
|
72
100
|
}));
|
|
73
101
|
}
|
|
102
|
+
|
|
103
|
+
public async getBootstrapStatus(): Promise<interfaces.requests.IReq_GetAdminBootstrapStatus['response']> {
|
|
104
|
+
const dbEnabled = this.opsServerRef.dcRouterRef.options.dbConfig?.enabled !== false;
|
|
105
|
+
const store = this.getAccountStore();
|
|
106
|
+
const dbReady = !!store;
|
|
107
|
+
const hasPersistentAdmin = dbReady ? await store.hasActiveAdminAccount() : false;
|
|
108
|
+
return {
|
|
109
|
+
dbEnabled,
|
|
110
|
+
dbReady,
|
|
111
|
+
hasPersistentAdmin,
|
|
112
|
+
needsBootstrap: dbEnabled && dbReady && !hasPersistentAdmin,
|
|
113
|
+
ephemeralAdminAvailable: !hasPersistentAdmin,
|
|
114
|
+
idpGlobalConfigured: this.isIdpGlobalConfigured(),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public async createInitialAdminUser(optionsArg: {
|
|
119
|
+
email: string;
|
|
120
|
+
name?: string;
|
|
121
|
+
password: string;
|
|
122
|
+
enableIdpGlobalAuth?: boolean;
|
|
123
|
+
}): Promise<interfaces.requests.IReq_CreateInitialAdminUser['response']> {
|
|
124
|
+
const store = this.getAccountStore();
|
|
125
|
+
if (!store) {
|
|
126
|
+
throw new plugins.typedrequest.TypedResponseError('database is not ready');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (await store.hasActiveAdminAccount()) {
|
|
130
|
+
throw new plugins.typedrequest.TypedResponseError('initial admin already exists');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const password = String(optionsArg.password || '');
|
|
134
|
+
if (!password) {
|
|
135
|
+
throw new plugins.typedrequest.TypedResponseError('password is required');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const email = String(optionsArg.email || '').trim();
|
|
139
|
+
const authSources: Array<'local' | 'idp.global'> = ['local'];
|
|
140
|
+
if (optionsArg.enableIdpGlobalAuth) {
|
|
141
|
+
authSources.push('idp.global');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
const account = await store.createAccount({
|
|
146
|
+
email,
|
|
147
|
+
name: String(optionsArg.name || '').trim() || email,
|
|
148
|
+
role: 'admin',
|
|
149
|
+
authSources,
|
|
150
|
+
password,
|
|
151
|
+
});
|
|
152
|
+
const user = this.accountToUser(account);
|
|
153
|
+
return {
|
|
154
|
+
success: true,
|
|
155
|
+
identity: await this.createIdentityForUser(user),
|
|
156
|
+
user,
|
|
157
|
+
};
|
|
158
|
+
} catch (error) {
|
|
159
|
+
throw new plugins.typedrequest.TypedResponseError((error as Error).message || 'failed to create initial admin');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
74
162
|
|
|
75
163
|
private registerHandlers(): void {
|
|
164
|
+
this.typedrouter.addTypedHandler(
|
|
165
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetAdminBootstrapStatus>(
|
|
166
|
+
'getAdminBootstrapStatus',
|
|
167
|
+
async (_dataArg) => this.getBootstrapStatus()
|
|
168
|
+
)
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
this.opsServerRef.adminRouter.addTypedHandler(
|
|
172
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateInitialAdminUser>(
|
|
173
|
+
'createInitialAdminUser',
|
|
174
|
+
async (dataArg) => this.createInitialAdminUser({
|
|
175
|
+
email: dataArg.email,
|
|
176
|
+
name: dataArg.name,
|
|
177
|
+
password: dataArg.password,
|
|
178
|
+
enableIdpGlobalAuth: dataArg.enableIdpGlobalAuth,
|
|
179
|
+
})
|
|
180
|
+
)
|
|
181
|
+
);
|
|
182
|
+
|
|
76
183
|
// Admin Login Handler
|
|
77
184
|
this.typedrouter.addTypedHandler(
|
|
78
185
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>(
|
|
79
186
|
'adminLoginWithUsernameAndPassword',
|
|
80
187
|
async (dataArg) => {
|
|
81
188
|
try {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
189
|
+
const user = await this.authenticateUser({
|
|
190
|
+
username: dataArg.username,
|
|
191
|
+
password: dataArg.password,
|
|
192
|
+
authSource: dataArg.authSource,
|
|
193
|
+
});
|
|
91
194
|
if (!user) {
|
|
92
195
|
throw new plugins.typedrequest.TypedResponseError('login failed');
|
|
93
196
|
}
|
|
94
|
-
|
|
95
|
-
const expiresAtTimestamp = Date.now() + 3600 * 1000 * 24; // 24 hours
|
|
96
|
-
|
|
97
|
-
const jwt = await this.smartjwtInstance.createJWT({
|
|
98
|
-
userId: user.id,
|
|
99
|
-
status: 'loggedIn',
|
|
100
|
-
expiresAt: expiresAtTimestamp,
|
|
101
|
-
});
|
|
102
|
-
|
|
197
|
+
|
|
103
198
|
return {
|
|
104
|
-
identity:
|
|
105
|
-
jwt,
|
|
106
|
-
userId: user.id,
|
|
107
|
-
name: user.username,
|
|
108
|
-
expiresAt: expiresAtTimestamp,
|
|
109
|
-
role: user.role,
|
|
110
|
-
type: 'user',
|
|
111
|
-
},
|
|
199
|
+
identity: await this.createIdentityForUser(user),
|
|
112
200
|
};
|
|
113
201
|
} catch (error) {
|
|
114
202
|
if (error instanceof plugins.typedrequest.TypedResponseError) {
|
|
@@ -162,8 +250,7 @@ export class AdminHandler {
|
|
|
162
250
|
};
|
|
163
251
|
}
|
|
164
252
|
|
|
165
|
-
|
|
166
|
-
const user = this.users.get(jwtData.userId);
|
|
253
|
+
const user = await this.resolveUser(jwtData.userId);
|
|
167
254
|
if (!user) {
|
|
168
255
|
return {
|
|
169
256
|
valid: false,
|
|
@@ -175,7 +262,7 @@ export class AdminHandler {
|
|
|
175
262
|
identity: {
|
|
176
263
|
jwt: dataArg.identity.jwt,
|
|
177
264
|
userId: user.id,
|
|
178
|
-
name: user.username,
|
|
265
|
+
name: user.name || user.username,
|
|
179
266
|
expiresAt: jwtData.expiresAt,
|
|
180
267
|
role: user.role,
|
|
181
268
|
type: 'user',
|
|
@@ -224,6 +311,15 @@ export class AdminHandler {
|
|
|
224
311
|
return false;
|
|
225
312
|
}
|
|
226
313
|
|
|
314
|
+
const user = await this.resolveUser(jwtData.userId);
|
|
315
|
+
if (!user) {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (dataArg.identity.role && dataArg.identity.role !== user.role) {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
|
|
227
323
|
return true;
|
|
228
324
|
} catch (error) {
|
|
229
325
|
return false;
|
|
@@ -256,4 +352,120 @@ export class AdminHandler {
|
|
|
256
352
|
name: 'adminIdentityGuard',
|
|
257
353
|
}
|
|
258
354
|
);
|
|
355
|
+
|
|
356
|
+
private async authenticateUser(optionsArg: {
|
|
357
|
+
username: string;
|
|
358
|
+
password: string;
|
|
359
|
+
authSource?: interfaces.requests.TAdminLoginAuthSource;
|
|
360
|
+
}): Promise<TAdminUser | null> {
|
|
361
|
+
if (await this.hasPersistentAdminAccount()) {
|
|
362
|
+
const store = this.getAccountStore();
|
|
363
|
+
const authService = new plugins.idpSdkServer.AccountAuthService({
|
|
364
|
+
store: store!,
|
|
365
|
+
idpClient: this.getIdpClient() as plugins.idpSdkServer.IdpGlobalServerClient | undefined,
|
|
366
|
+
});
|
|
367
|
+
const result = await authService.authenticate({
|
|
368
|
+
email: optionsArg.username,
|
|
369
|
+
password: optionsArg.password,
|
|
370
|
+
authSource: optionsArg.authSource || 'auto',
|
|
371
|
+
});
|
|
372
|
+
return result ? this.accountToUser(result.account) : null;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
for (const [_, userData] of this.users) {
|
|
376
|
+
if (userData.username === optionsArg.username && userData.password === optionsArg.password) {
|
|
377
|
+
return userData;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
private async resolveUser(userIdArg: string): Promise<TAdminUser | null> {
|
|
384
|
+
if (await this.hasPersistentAdminAccount()) {
|
|
385
|
+
const account = await this.getAccountStore()!.getAccountById(userIdArg);
|
|
386
|
+
if (!account || account.status !== 'active') {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
return this.accountToUser(account);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return this.users.get(userIdArg) || null;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private async hasPersistentAdminAccount(): Promise<boolean> {
|
|
396
|
+
const store = this.getAccountStore();
|
|
397
|
+
return store ? store.hasActiveAdminAccount() : false;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
private getAccountStore(): plugins.idpSdkServer.SmartdataAccountStore | null {
|
|
401
|
+
if (this.opsServerRef.dcRouterRef.options.dbConfig?.enabled === false) {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
const dcRouterDb = this.opsServerRef.dcRouterRef.dcRouterDb;
|
|
405
|
+
if (!dcRouterDb?.isReady()) {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
if (!this.accountStore) {
|
|
409
|
+
this.accountStore = new plugins.idpSdkServer.SmartdataAccountStore({
|
|
410
|
+
smartdataDb: dcRouterDb.getDb(),
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
return this.accountStore;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
private getIdpClient(): Pick<plugins.idpSdkServer.IdpGlobalServerClient, 'loginWithEmailAndPassword' | 'stop'> | undefined {
|
|
417
|
+
const configuredClient = this.opsServerRef.dcRouterRef.options.adminAuth?.idpClient;
|
|
418
|
+
if (configuredClient) {
|
|
419
|
+
return configuredClient;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const baseUrl = this.opsServerRef.dcRouterRef.options.adminAuth?.idpGlobalUrl || process.env.DCROUTER_IDP_GLOBAL_URL;
|
|
423
|
+
if (!baseUrl) {
|
|
424
|
+
return undefined;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (!this.idpClient) {
|
|
428
|
+
this.idpClient = new plugins.idpSdkServer.IdpGlobalServerClient({ baseUrl });
|
|
429
|
+
this.ownsIdpClient = true;
|
|
430
|
+
}
|
|
431
|
+
return this.idpClient;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private isIdpGlobalConfigured(): boolean {
|
|
435
|
+
return !!(
|
|
436
|
+
this.opsServerRef.dcRouterRef.options.adminAuth?.idpClient ||
|
|
437
|
+
this.opsServerRef.dcRouterRef.options.adminAuth?.idpGlobalUrl ||
|
|
438
|
+
process.env.DCROUTER_IDP_GLOBAL_URL
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
private accountToUser(accountArg: plugins.idpSdkServer.IIdpSdkAccount): TAdminUser {
|
|
443
|
+
return {
|
|
444
|
+
id: accountArg.id,
|
|
445
|
+
username: accountArg.email,
|
|
446
|
+
email: accountArg.email,
|
|
447
|
+
name: accountArg.name,
|
|
448
|
+
role: accountArg.role,
|
|
449
|
+
status: accountArg.status,
|
|
450
|
+
authSources: accountArg.authSources,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
private async createIdentityForUser(userArg: TAdminUser): Promise<interfaces.data.IIdentity> {
|
|
455
|
+
const expiresAtTimestamp = Date.now() + 3600 * 1000 * 24; // 24 hours
|
|
456
|
+
const jwt = await this.smartjwtInstance.createJWT({
|
|
457
|
+
userId: userArg.id,
|
|
458
|
+
status: 'loggedIn',
|
|
459
|
+
expiresAt: expiresAtTimestamp,
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
return {
|
|
463
|
+
jwt,
|
|
464
|
+
userId: userArg.id,
|
|
465
|
+
name: userArg.name || userArg.username,
|
|
466
|
+
expiresAt: expiresAtTimestamp,
|
|
467
|
+
role: userArg.role,
|
|
468
|
+
type: 'user',
|
|
469
|
+
};
|
|
470
|
+
}
|
|
259
471
|
}
|
|
@@ -307,6 +307,11 @@ export class CertificateHandler {
|
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
+
if (backoffInfo && status !== 'valid' && status !== 'expiring') {
|
|
311
|
+
status = 'failed';
|
|
312
|
+
error = error || backoffInfo.lastError;
|
|
313
|
+
}
|
|
314
|
+
|
|
310
315
|
certificates.push({
|
|
311
316
|
domain,
|
|
312
317
|
routeNames: info.routeNames,
|
|
@@ -88,6 +88,8 @@ export class TargetProfileHandler {
|
|
|
88
88
|
routeRefs: dataArg.routeRefs,
|
|
89
89
|
createdBy: userId,
|
|
90
90
|
});
|
|
91
|
+
await this.opsServerRef.dcRouterRef.routeConfigManager?.applyRoutes();
|
|
92
|
+
await this.opsServerRef.dcRouterRef.vpnManager?.refreshAllClientSecurity();
|
|
91
93
|
return { success: true, id };
|
|
92
94
|
},
|
|
93
95
|
),
|
|
@@ -21,7 +21,7 @@ export class UsersHandler {
|
|
|
21
21
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_ListUsers>(
|
|
22
22
|
'listUsers',
|
|
23
23
|
async (_dataArg) => {
|
|
24
|
-
const users = this.opsServerRef.adminHandler.listUsers();
|
|
24
|
+
const users = await this.opsServerRef.adminHandler.listUsers();
|
|
25
25
|
return { users };
|
|
26
26
|
},
|
|
27
27
|
),
|