@serve.zone/dcrouter 13.30.0 → 13.32.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.
Files changed (88) hide show
  1. package/dist_serve/bundle.js +1042 -1014
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/classes.dcrouter.d.ts +1 -1
  4. package/dist_ts/opsserver/classes.opsserver.d.ts +4 -2
  5. package/dist_ts/opsserver/classes.opsserver.js +2 -11
  6. package/dist_ts/opsserver/handlers/acme-config.handler.js +7 -24
  7. package/dist_ts/opsserver/handlers/admin.handler.d.ts +12 -0
  8. package/dist_ts/opsserver/handlers/admin.handler.js +129 -95
  9. package/dist_ts/opsserver/handlers/api-token.handler.js +28 -2
  10. package/dist_ts/opsserver/handlers/certificate.handler.js +7 -24
  11. package/dist_ts/opsserver/handlers/config.handler.js +3 -1
  12. package/dist_ts/opsserver/handlers/dns-provider.handler.js +7 -24
  13. package/dist_ts/opsserver/handlers/dns-record.handler.js +7 -24
  14. package/dist_ts/opsserver/handlers/domain.handler.js +7 -24
  15. package/dist_ts/opsserver/handlers/email-domain.handler.js +7 -24
  16. package/dist_ts/opsserver/handlers/email-ops.handler.js +8 -1
  17. package/dist_ts/opsserver/handlers/logs.handler.js +4 -1
  18. package/dist_ts/opsserver/handlers/network-target.handler.js +7 -24
  19. package/dist_ts/opsserver/handlers/radius.handler.js +32 -1
  20. package/dist_ts/opsserver/handlers/remoteingress.handler.js +24 -1
  21. package/dist_ts/opsserver/handlers/route-management.handler.js +7 -26
  22. package/dist_ts/opsserver/handlers/security.handler.js +32 -7
  23. package/dist_ts/opsserver/handlers/source-profile.handler.js +7 -24
  24. package/dist_ts/opsserver/handlers/stats.handler.js +8 -1
  25. package/dist_ts/opsserver/handlers/target-profile.handler.js +7 -24
  26. package/dist_ts/opsserver/handlers/users.handler.d.ts +1 -1
  27. package/dist_ts/opsserver/handlers/users.handler.js +35 -4
  28. package/dist_ts/opsserver/handlers/vpn.handler.js +34 -1
  29. package/dist_ts/opsserver/handlers/workhoster.handler.js +16 -35
  30. package/dist_ts/opsserver/helpers/auth.d.ts +21 -0
  31. package/dist_ts/opsserver/helpers/auth.js +63 -0
  32. package/dist_ts_interfaces/data/route-management.d.ts +2 -1
  33. package/dist_ts_interfaces/data/route-management.js +48 -2
  34. package/dist_ts_interfaces/requests/api-tokens.d.ts +10 -5
  35. package/dist_ts_interfaces/requests/combined.stats.d.ts +2 -1
  36. package/dist_ts_interfaces/requests/config.d.ts +2 -1
  37. package/dist_ts_interfaces/requests/email-ops.d.ts +6 -3
  38. package/dist_ts_interfaces/requests/logs.d.ts +4 -2
  39. package/dist_ts_interfaces/requests/radius.d.ts +24 -12
  40. package/dist_ts_interfaces/requests/remoteingress.d.ts +14 -7
  41. package/dist_ts_interfaces/requests/security-policy.d.ts +16 -8
  42. package/dist_ts_interfaces/requests/stats.d.ts +18 -9
  43. package/dist_ts_interfaces/requests/users.d.ts +39 -2
  44. package/dist_ts_interfaces/requests/vpn.d.ts +22 -11
  45. package/dist_ts_interfaces/requests/workhoster.d.ts +10 -5
  46. package/dist_ts_migrations/index.js +3 -1
  47. package/dist_ts_web/00_commitinfo_data.js +1 -1
  48. package/dist_ts_web/appstate.d.ts +8 -0
  49. package/dist_ts_web/appstate.js +52 -2
  50. package/dist_ts_web/elements/access/ops-view-apitokens.js +2 -21
  51. package/dist_ts_web/elements/access/ops-view-users.d.ts +2 -0
  52. package/dist_ts_web/elements/access/ops-view-users.js +133 -2
  53. package/dist_ts_web/elements/network/ops-view-routes.js +11 -1
  54. package/dist_ts_web/elements/ops-dashboard.js +2 -4
  55. package/package.json +3 -3
  56. package/readme.md +1 -1
  57. package/ts/00_commitinfo_data.ts +1 -1
  58. package/ts/classes.dcrouter.ts +1 -1
  59. package/ts/opsserver/classes.opsserver.ts +3 -14
  60. package/ts/opsserver/handlers/acme-config.handler.ts +6 -23
  61. package/ts/opsserver/handlers/admin.handler.ts +155 -111
  62. package/ts/opsserver/handlers/api-token.handler.ts +27 -1
  63. package/ts/opsserver/handlers/certificate.handler.ts +6 -23
  64. package/ts/opsserver/handlers/config.handler.ts +2 -0
  65. package/ts/opsserver/handlers/dns-provider.handler.ts +6 -23
  66. package/ts/opsserver/handlers/dns-record.handler.ts +6 -23
  67. package/ts/opsserver/handlers/domain.handler.ts +6 -23
  68. package/ts/opsserver/handlers/email-domain.handler.ts +6 -23
  69. package/ts/opsserver/handlers/email-ops.handler.ts +7 -0
  70. package/ts/opsserver/handlers/logs.handler.ts +3 -0
  71. package/ts/opsserver/handlers/network-target.handler.ts +6 -23
  72. package/ts/opsserver/handlers/radius.handler.ts +31 -0
  73. package/ts/opsserver/handlers/remoteingress.handler.ts +23 -0
  74. package/ts/opsserver/handlers/route-management.handler.ts +6 -25
  75. package/ts/opsserver/handlers/security.handler.ts +31 -6
  76. package/ts/opsserver/handlers/source-profile.handler.ts +6 -23
  77. package/ts/opsserver/handlers/stats.handler.ts +7 -0
  78. package/ts/opsserver/handlers/target-profile.handler.ts +6 -23
  79. package/ts/opsserver/handlers/users.handler.ts +46 -3
  80. package/ts/opsserver/handlers/vpn.handler.ts +33 -0
  81. package/ts/opsserver/handlers/workhoster.handler.ts +18 -33
  82. package/ts/opsserver/helpers/auth.ts +91 -0
  83. package/ts_web/00_commitinfo_data.ts +1 -1
  84. package/ts_web/appstate.ts +69 -1
  85. package/ts_web/elements/access/ops-view-apitokens.ts +1 -20
  86. package/ts_web/elements/access/ops-view-users.ts +139 -1
  87. package/ts_web/elements/network/ops-view-routes.ts +9 -0
  88. package/ts_web/elements/ops-dashboard.ts +1 -3
@@ -3,6 +3,7 @@ import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
4
  import { AcmeCertDoc, ProxyCertDoc } from '../../db/index.js';
5
5
  import { logger } from '../../logger.js';
6
+ import { requireOpsAuth } from '../helpers/auth.js';
6
7
 
7
8
  /**
8
9
  * Mirrors `SmartacmeCertMatcher.getCertificateDomainNameByDomainName` from
@@ -37,29 +38,11 @@ export class CertificateHandler {
37
38
  request: { identity?: interfaces.data.IIdentity; apiToken?: string },
38
39
  requiredScope?: interfaces.data.TApiTokenScope,
39
40
  ): Promise<string> {
40
- if (request.identity?.jwt) {
41
- try {
42
- const isAdmin = await this.opsServerRef.adminHandler.adminIdentityGuard.exec({
43
- identity: request.identity,
44
- });
45
- if (isAdmin) return request.identity.userId;
46
- } catch { /* fall through */ }
47
- }
48
-
49
- if (request.apiToken) {
50
- const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager;
51
- if (tokenManager) {
52
- const token = await tokenManager.validateToken(request.apiToken);
53
- if (token) {
54
- if (!requiredScope || tokenManager.hasScope(token, requiredScope)) {
55
- return token.createdBy;
56
- }
57
- throw new plugins.typedrequest.TypedResponseError('insufficient scope');
58
- }
59
- }
60
- }
61
-
62
- throw new plugins.typedrequest.TypedResponseError('unauthorized');
41
+ const auth = await requireOpsAuth(this.opsServerRef, request, {
42
+ scope: requiredScope,
43
+ requireAdminIdentity: requiredScope?.endsWith(':write'),
44
+ });
45
+ return auth.userId;
63
46
  }
64
47
 
65
48
  private registerHandlers(): void {
@@ -2,6 +2,7 @@ import * as plugins from '../../plugins.js';
2
2
  import * as paths from '../../paths.js';
3
3
  import type { OpsServer } from '../classes.opsserver.js';
4
4
  import * as interfaces from '../../../ts_interfaces/index.js';
5
+ import { requireOpsAuth } from '../helpers/auth.js';
5
6
 
6
7
  export class ConfigHandler {
7
8
  constructor(private opsServerRef: OpsServer) {
@@ -17,6 +18,7 @@ export class ConfigHandler {
17
18
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetConfiguration>(
18
19
  'getConfiguration',
19
20
  async (dataArg, toolsArg) => {
21
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'config:read' });
20
22
  const config = await this.getConfiguration();
21
23
  return {
22
24
  config,
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireOpsAuth } from '../helpers/auth.js';
4
5
 
5
6
  /**
6
7
  * CRUD + connection-test handlers for DnsProviderDoc.
@@ -20,29 +21,11 @@ export class DnsProviderHandler {
20
21
  request: { identity?: interfaces.data.IIdentity; apiToken?: string },
21
22
  requiredScope?: interfaces.data.TApiTokenScope,
22
23
  ): Promise<string> {
23
- if (request.identity?.jwt) {
24
- try {
25
- const isAdmin = await this.opsServerRef.adminHandler.adminIdentityGuard.exec({
26
- identity: request.identity,
27
- });
28
- if (isAdmin) return request.identity.userId;
29
- } catch { /* fall through */ }
30
- }
31
-
32
- if (request.apiToken) {
33
- const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager;
34
- if (tokenManager) {
35
- const token = await tokenManager.validateToken(request.apiToken);
36
- if (token) {
37
- if (!requiredScope || tokenManager.hasScope(token, requiredScope)) {
38
- return token.createdBy;
39
- }
40
- throw new plugins.typedrequest.TypedResponseError('insufficient scope');
41
- }
42
- }
43
- }
44
-
45
- throw new plugins.typedrequest.TypedResponseError('unauthorized');
24
+ const auth = await requireOpsAuth(this.opsServerRef, request, {
25
+ scope: requiredScope,
26
+ requireAdminIdentity: requiredScope?.endsWith(':write'),
27
+ });
28
+ return auth.userId;
46
29
  }
47
30
 
48
31
  private registerHandlers(): void {
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireOpsAuth } from '../helpers/auth.js';
4
5
 
5
6
  /**
6
7
  * CRUD handlers for DnsRecordDoc.
@@ -17,29 +18,11 @@ export class DnsRecordHandler {
17
18
  request: { identity?: interfaces.data.IIdentity; apiToken?: string },
18
19
  requiredScope?: interfaces.data.TApiTokenScope,
19
20
  ): Promise<string> {
20
- if (request.identity?.jwt) {
21
- try {
22
- const isAdmin = await this.opsServerRef.adminHandler.adminIdentityGuard.exec({
23
- identity: request.identity,
24
- });
25
- if (isAdmin) return request.identity.userId;
26
- } catch { /* fall through */ }
27
- }
28
-
29
- if (request.apiToken) {
30
- const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager;
31
- if (tokenManager) {
32
- const token = await tokenManager.validateToken(request.apiToken);
33
- if (token) {
34
- if (!requiredScope || tokenManager.hasScope(token, requiredScope)) {
35
- return token.createdBy;
36
- }
37
- throw new plugins.typedrequest.TypedResponseError('insufficient scope');
38
- }
39
- }
40
- }
41
-
42
- throw new plugins.typedrequest.TypedResponseError('unauthorized');
21
+ const auth = await requireOpsAuth(this.opsServerRef, request, {
22
+ scope: requiredScope,
23
+ requireAdminIdentity: requiredScope?.endsWith(':write'),
24
+ });
25
+ return auth.userId;
43
26
  }
44
27
 
45
28
  private registerHandlers(): void {
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireOpsAuth } from '../helpers/auth.js';
4
5
 
5
6
  /**
6
7
  * CRUD handlers for DomainDoc.
@@ -17,29 +18,11 @@ export class DomainHandler {
17
18
  request: { identity?: interfaces.data.IIdentity; apiToken?: string },
18
19
  requiredScope?: interfaces.data.TApiTokenScope,
19
20
  ): Promise<string> {
20
- if (request.identity?.jwt) {
21
- try {
22
- const isAdmin = await this.opsServerRef.adminHandler.adminIdentityGuard.exec({
23
- identity: request.identity,
24
- });
25
- if (isAdmin) return request.identity.userId;
26
- } catch { /* fall through */ }
27
- }
28
-
29
- if (request.apiToken) {
30
- const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager;
31
- if (tokenManager) {
32
- const token = await tokenManager.validateToken(request.apiToken);
33
- if (token) {
34
- if (!requiredScope || tokenManager.hasScope(token, requiredScope)) {
35
- return token.createdBy;
36
- }
37
- throw new plugins.typedrequest.TypedResponseError('insufficient scope');
38
- }
39
- }
40
- }
41
-
42
- throw new plugins.typedrequest.TypedResponseError('unauthorized');
21
+ const auth = await requireOpsAuth(this.opsServerRef, request, {
22
+ scope: requiredScope,
23
+ requireAdminIdentity: requiredScope?.endsWith(':write'),
24
+ });
25
+ return auth.userId;
43
26
  }
44
27
 
45
28
  private registerHandlers(): void {
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireOpsAuth } from '../helpers/auth.js';
4
5
 
5
6
  /**
6
7
  * CRUD + DNS provisioning handler for email domains.
@@ -19,29 +20,11 @@ export class EmailDomainHandler {
19
20
  request: { identity?: interfaces.data.IIdentity; apiToken?: string },
20
21
  requiredScope?: interfaces.data.TApiTokenScope,
21
22
  ): 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');
23
+ const auth = await requireOpsAuth(this.opsServerRef, request, {
24
+ scope: requiredScope,
25
+ requireAdminIdentity: requiredScope?.endsWith(':write'),
26
+ });
27
+ return auth.userId;
45
28
  }
46
29
 
47
30
  private get manager() {
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireOpsAuth } from '../helpers/auth.js';
4
5
 
5
6
  export class EmailOpsHandler {
6
7
  constructor(private opsServerRef: OpsServer) {
@@ -18,6 +19,7 @@ export class EmailOpsHandler {
18
19
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetAllEmails>(
19
20
  'getAllEmails',
20
21
  async (dataArg) => {
22
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'emails:read' });
21
23
  const emails = this.getAllQueueEmails();
22
24
  return { emails };
23
25
  }
@@ -29,6 +31,7 @@ export class EmailOpsHandler {
29
31
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetEmailDetail>(
30
32
  'getEmailDetail',
31
33
  async (dataArg) => {
34
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'emails:read' });
32
35
  const email = this.getEmailDetail(dataArg.emailId);
33
36
  return { email };
34
37
  }
@@ -42,6 +45,10 @@ export class EmailOpsHandler {
42
45
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_ResendEmail>(
43
46
  'resendEmail',
44
47
  async (dataArg) => {
48
+ await requireOpsAuth(this.opsServerRef, dataArg, {
49
+ scope: 'emails:write',
50
+ requireAdminIdentity: true,
51
+ });
45
52
  const emailServer = this.opsServerRef.dcRouterRef.emailServer;
46
53
  if (!emailServer?.deliveryQueue) {
47
54
  return { success: false, error: 'Email server not available' };
@@ -2,6 +2,7 @@ import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
4
  import { logBuffer, baseLogger } from '../../logger.js';
5
+ import { requireOpsAuth } from '../helpers/auth.js';
5
6
 
6
7
  // Module-level singleton: the log push destination is added once and reuses
7
8
  // the current OpsServer reference so it survives OpsServer restarts without
@@ -40,6 +41,7 @@ export class LogsHandler {
40
41
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRecentLogs>(
41
42
  'getRecentLogs',
42
43
  async (dataArg, toolsArg) => {
44
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'logs:read' });
43
45
  const logs = await this.getRecentLogs(
44
46
  dataArg.level,
45
47
  dataArg.category,
@@ -63,6 +65,7 @@ export class LogsHandler {
63
65
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetLogStream>(
64
66
  'getLogStream',
65
67
  async (dataArg, toolsArg) => {
68
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'logs:read' });
66
69
  // Create a virtual stream for log streaming
67
70
  const virtualStream = new plugins.typedrequest.VirtualStream<Uint8Array>();
68
71
 
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireOpsAuth } from '../helpers/auth.js';
4
5
 
5
6
  export class NetworkTargetHandler {
6
7
  public typedrouter = new plugins.typedrequest.TypedRouter();
@@ -14,29 +15,11 @@ export class NetworkTargetHandler {
14
15
  request: { identity?: interfaces.data.IIdentity; apiToken?: string },
15
16
  requiredScope?: interfaces.data.TApiTokenScope,
16
17
  ): Promise<string> {
17
- if (request.identity?.jwt) {
18
- try {
19
- const isAdmin = await this.opsServerRef.adminHandler.adminIdentityGuard.exec({
20
- identity: request.identity,
21
- });
22
- if (isAdmin) return request.identity.userId;
23
- } catch { /* fall through */ }
24
- }
25
-
26
- if (request.apiToken) {
27
- const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager;
28
- if (tokenManager) {
29
- const token = await tokenManager.validateToken(request.apiToken);
30
- if (token) {
31
- if (!requiredScope || tokenManager.hasScope(token, requiredScope)) {
32
- return token.createdBy;
33
- }
34
- throw new plugins.typedrequest.TypedResponseError('insufficient scope');
35
- }
36
- }
37
- }
38
-
39
- throw new plugins.typedrequest.TypedResponseError('unauthorized');
18
+ const auth = await requireOpsAuth(this.opsServerRef, request, {
19
+ scope: requiredScope,
20
+ requireAdminIdentity: requiredScope?.endsWith(':write'),
21
+ });
22
+ return auth.userId;
40
23
  }
41
24
 
42
25
  private registerHandlers(): void {
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireOpsAuth } from '../helpers/auth.js';
4
5
 
5
6
  export class RadiusHandler {
6
7
  constructor(private opsServerRef: OpsServer) {
@@ -19,6 +20,7 @@ export class RadiusHandler {
19
20
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRadiusClients>(
20
21
  'getRadiusClients',
21
22
  async (dataArg, toolsArg) => {
23
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'radius:read' });
22
24
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
23
25
 
24
26
  if (!radiusServer) {
@@ -43,6 +45,10 @@ export class RadiusHandler {
43
45
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_SetRadiusClient>(
44
46
  'setRadiusClient',
45
47
  async (dataArg, toolsArg) => {
48
+ await requireOpsAuth(this.opsServerRef, dataArg, {
49
+ scope: 'radius:write',
50
+ requireAdminIdentity: true,
51
+ });
46
52
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
47
53
 
48
54
  if (!radiusServer) {
@@ -64,6 +70,10 @@ export class RadiusHandler {
64
70
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RemoveRadiusClient>(
65
71
  'removeRadiusClient',
66
72
  async (dataArg, toolsArg) => {
73
+ await requireOpsAuth(this.opsServerRef, dataArg, {
74
+ scope: 'radius:write',
75
+ requireAdminIdentity: true,
76
+ });
67
77
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
68
78
 
69
79
  if (!radiusServer) {
@@ -88,6 +98,7 @@ export class RadiusHandler {
88
98
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetVlanMappings>(
89
99
  'getVlanMappings',
90
100
  async (dataArg, toolsArg) => {
101
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'radius:read' });
91
102
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
92
103
 
93
104
  if (!radiusServer) {
@@ -124,6 +135,10 @@ export class RadiusHandler {
124
135
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_SetVlanMapping>(
125
136
  'setVlanMapping',
126
137
  async (dataArg, toolsArg) => {
138
+ await requireOpsAuth(this.opsServerRef, dataArg, {
139
+ scope: 'radius:write',
140
+ requireAdminIdentity: true,
141
+ });
127
142
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
128
143
 
129
144
  if (!radiusServer) {
@@ -156,6 +171,10 @@ export class RadiusHandler {
156
171
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RemoveVlanMapping>(
157
172
  'removeVlanMapping',
158
173
  async (dataArg, toolsArg) => {
174
+ await requireOpsAuth(this.opsServerRef, dataArg, {
175
+ scope: 'radius:write',
176
+ requireAdminIdentity: true,
177
+ });
159
178
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
160
179
 
161
180
  if (!radiusServer) {
@@ -177,6 +196,10 @@ export class RadiusHandler {
177
196
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateVlanConfig>(
178
197
  'updateVlanConfig',
179
198
  async (dataArg, toolsArg) => {
199
+ await requireOpsAuth(this.opsServerRef, dataArg, {
200
+ scope: 'radius:write',
201
+ requireAdminIdentity: true,
202
+ });
180
203
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
181
204
 
182
205
  if (!radiusServer) {
@@ -209,6 +232,7 @@ export class RadiusHandler {
209
232
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_TestVlanAssignment>(
210
233
  'testVlanAssignment',
211
234
  async (dataArg, toolsArg) => {
235
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'radius:read' });
212
236
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
213
237
 
214
238
  if (!radiusServer) {
@@ -243,6 +267,7 @@ export class RadiusHandler {
243
267
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRadiusSessions>(
244
268
  'getRadiusSessions',
245
269
  async (dataArg, toolsArg) => {
270
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'radius:read' });
246
271
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
247
272
 
248
273
  if (!radiusServer) {
@@ -292,6 +317,10 @@ export class RadiusHandler {
292
317
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DisconnectRadiusSession>(
293
318
  'disconnectRadiusSession',
294
319
  async (dataArg, toolsArg) => {
320
+ await requireOpsAuth(this.opsServerRef, dataArg, {
321
+ scope: 'radius:write',
322
+ requireAdminIdentity: true,
323
+ });
295
324
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
296
325
 
297
326
  if (!radiusServer) {
@@ -317,6 +346,7 @@ export class RadiusHandler {
317
346
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRadiusAccountingSummary>(
318
347
  'getRadiusAccountingSummary',
319
348
  async (dataArg, toolsArg) => {
349
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'radius:read' });
320
350
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
321
351
 
322
352
  if (!radiusServer) {
@@ -354,6 +384,7 @@ export class RadiusHandler {
354
384
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRadiusStatistics>(
355
385
  'getRadiusStatistics',
356
386
  async (dataArg, toolsArg) => {
387
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'radius:read' });
357
388
  const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
358
389
 
359
390
  if (!radiusServer) {
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireOpsAuth } from '../helpers/auth.js';
4
5
 
5
6
  export class RemoteIngressHandler {
6
7
  constructor(private opsServerRef: OpsServer) {
@@ -18,6 +19,7 @@ export class RemoteIngressHandler {
18
19
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRemoteIngresses>(
19
20
  'getRemoteIngresses',
20
21
  async (dataArg, toolsArg) => {
22
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'remote-ingress:read' });
21
23
  const manager = this.opsServerRef.dcRouterRef.remoteIngressManager;
22
24
  if (!manager) {
23
25
  return { edges: [] };
@@ -46,6 +48,10 @@ export class RemoteIngressHandler {
46
48
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateRemoteIngress>(
47
49
  'createRemoteIngress',
48
50
  async (dataArg, toolsArg) => {
51
+ await requireOpsAuth(this.opsServerRef, dataArg, {
52
+ scope: 'remote-ingress:write',
53
+ requireAdminIdentity: true,
54
+ });
49
55
  const manager = this.opsServerRef.dcRouterRef.remoteIngressManager;
50
56
  const tunnelManager = this.opsServerRef.dcRouterRef.tunnelManager;
51
57
 
@@ -78,6 +84,10 @@ export class RemoteIngressHandler {
78
84
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteRemoteIngress>(
79
85
  'deleteRemoteIngress',
80
86
  async (dataArg, toolsArg) => {
87
+ await requireOpsAuth(this.opsServerRef, dataArg, {
88
+ scope: 'remote-ingress:write',
89
+ requireAdminIdentity: true,
90
+ });
81
91
  const manager = this.opsServerRef.dcRouterRef.remoteIngressManager;
82
92
  const tunnelManager = this.opsServerRef.dcRouterRef.tunnelManager;
83
93
 
@@ -103,6 +113,10 @@ export class RemoteIngressHandler {
103
113
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateRemoteIngress>(
104
114
  'updateRemoteIngress',
105
115
  async (dataArg, toolsArg) => {
116
+ await requireOpsAuth(this.opsServerRef, dataArg, {
117
+ scope: 'remote-ingress:write',
118
+ requireAdminIdentity: true,
119
+ });
106
120
  const manager = this.opsServerRef.dcRouterRef.remoteIngressManager;
107
121
  const tunnelManager = this.opsServerRef.dcRouterRef.tunnelManager;
108
122
 
@@ -148,6 +162,10 @@ export class RemoteIngressHandler {
148
162
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RegenerateRemoteIngressSecret>(
149
163
  'regenerateRemoteIngressSecret',
150
164
  async (dataArg, toolsArg) => {
165
+ await requireOpsAuth(this.opsServerRef, dataArg, {
166
+ scope: 'remote-ingress:write',
167
+ requireAdminIdentity: true,
168
+ });
151
169
  const manager = this.opsServerRef.dcRouterRef.remoteIngressManager;
152
170
  const tunnelManager = this.opsServerRef.dcRouterRef.tunnelManager;
153
171
 
@@ -175,6 +193,7 @@ export class RemoteIngressHandler {
175
193
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRemoteIngressStatus>(
176
194
  'getRemoteIngressStatus',
177
195
  async (dataArg, toolsArg) => {
196
+ await requireOpsAuth(this.opsServerRef, dataArg, { scope: 'remote-ingress:read' });
178
197
  const tunnelManager = this.opsServerRef.dcRouterRef.tunnelManager;
179
198
  if (!tunnelManager) {
180
199
  return { statuses: [] };
@@ -189,6 +208,10 @@ export class RemoteIngressHandler {
189
208
  new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRemoteIngressConnectionToken>(
190
209
  'getRemoteIngressConnectionToken',
191
210
  async (dataArg, toolsArg) => {
211
+ await requireOpsAuth(this.opsServerRef, dataArg, {
212
+ scope: 'remote-ingress:write',
213
+ requireAdminIdentity: true,
214
+ });
192
215
  const manager = this.opsServerRef.dcRouterRef.remoteIngressManager;
193
216
  if (!manager) {
194
217
  return { success: false, message: 'RemoteIngress not configured' };
@@ -1,6 +1,7 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { OpsServer } from '../classes.opsserver.js';
3
3
  import * as interfaces from '../../../ts_interfaces/index.js';
4
+ import { requireOpsAuth } from '../helpers/auth.js';
4
5
 
5
6
  export class RouteManagementHandler {
6
7
  public typedrouter = new plugins.typedrequest.TypedRouter();
@@ -18,31 +19,11 @@ export class RouteManagementHandler {
18
19
  request: { identity?: interfaces.data.IIdentity; apiToken?: string },
19
20
  requiredScope?: interfaces.data.TApiTokenScope,
20
21
  ): Promise<string> {
21
- // Try JWT identity first
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
- // Try API token
32
- if (request.apiToken) {
33
- const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager;
34
- if (tokenManager) {
35
- const token = await tokenManager.validateToken(request.apiToken);
36
- if (token) {
37
- if (!requiredScope || tokenManager.hasScope(token, requiredScope)) {
38
- return token.createdBy;
39
- }
40
- throw new plugins.typedrequest.TypedResponseError('insufficient scope');
41
- }
42
- }
43
- }
44
-
45
- throw new plugins.typedrequest.TypedResponseError('unauthorized');
22
+ const auth = await requireOpsAuth(this.opsServerRef, request, {
23
+ scope: requiredScope,
24
+ requireAdminIdentity: requiredScope?.endsWith(':write'),
25
+ });
26
+ return auth.userId;
46
27
  }
47
28
 
48
29
  private registerHandlers(): void {