@serve.zone/dcrouter 13.4.0 → 13.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.
Files changed (49) hide show
  1. package/dist_serve/bundle.js +699 -635
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/opsserver/classes.opsserver.d.ts +1 -0
  4. package/dist_ts/opsserver/classes.opsserver.js +3 -1
  5. package/dist_ts/opsserver/handlers/admin.handler.d.ts +9 -0
  6. package/dist_ts/opsserver/handlers/admin.handler.js +12 -1
  7. package/dist_ts/opsserver/handlers/index.d.ts +1 -0
  8. package/dist_ts/opsserver/handlers/index.js +2 -1
  9. package/dist_ts/opsserver/handlers/users.handler.d.ts +12 -0
  10. package/dist_ts/opsserver/handlers/users.handler.js +24 -0
  11. package/dist_ts_interfaces/requests/index.d.ts +1 -0
  12. package/dist_ts_interfaces/requests/index.js +2 -1
  13. package/dist_ts_interfaces/requests/users.d.ts +19 -0
  14. package/dist_ts_interfaces/requests/users.js +3 -0
  15. package/dist_ts_web/00_commitinfo_data.js +1 -1
  16. package/dist_ts_web/appstate.d.ts +13 -0
  17. package/dist_ts_web/appstate.js +32 -1
  18. package/dist_ts_web/elements/access/index.d.ts +1 -0
  19. package/dist_ts_web/elements/access/index.js +2 -1
  20. package/dist_ts_web/elements/access/ops-view-apitokens.js +1 -1
  21. package/dist_ts_web/elements/access/ops-view-users.d.ts +11 -0
  22. package/dist_ts_web/elements/access/ops-view-users.js +190 -0
  23. package/dist_ts_web/elements/email/ops-view-emails.js +1 -1
  24. package/dist_ts_web/elements/network/ops-view-network-activity.js +5 -1
  25. package/dist_ts_web/elements/ops-dashboard.js +3 -1
  26. package/dist_ts_web/elements/ops-view-certificates.js +1 -1
  27. package/dist_ts_web/elements/ops-view-logs.js +1 -1
  28. package/dist_ts_web/elements/overview/ops-view-config.js +1 -1
  29. package/dist_ts_web/elements/overview/ops-view-overview.js +1 -1
  30. package/dist_ts_web/router.js +2 -2
  31. package/package.json +1 -1
  32. package/ts/00_commitinfo_data.ts +1 -1
  33. package/ts/opsserver/classes.opsserver.ts +2 -0
  34. package/ts/opsserver/handlers/admin.handler.ts +12 -0
  35. package/ts/opsserver/handlers/index.ts +2 -1
  36. package/ts/opsserver/handlers/users.handler.ts +30 -0
  37. package/ts_web/00_commitinfo_data.ts +1 -1
  38. package/ts_web/appstate.ts +57 -0
  39. package/ts_web/elements/access/index.ts +1 -0
  40. package/ts_web/elements/access/ops-view-apitokens.ts +1 -1
  41. package/ts_web/elements/access/ops-view-users.ts +140 -0
  42. package/ts_web/elements/email/ops-view-emails.ts +1 -1
  43. package/ts_web/elements/network/ops-view-network-activity.ts +4 -0
  44. package/ts_web/elements/ops-dashboard.ts +2 -0
  45. package/ts_web/elements/ops-view-certificates.ts +1 -1
  46. package/ts_web/elements/ops-view-logs.ts +1 -1
  47. package/ts_web/elements/overview/ops-view-config.ts +1 -1
  48. package/ts_web/elements/overview/ops-view-overview.ts +1 -1
  49. package/ts_web/router.ts +1 -1
@@ -0,0 +1,140 @@
1
+ import * as appstate from '../../appstate.js';
2
+ import { viewHostCss } from '../shared/css.js';
3
+
4
+ import {
5
+ DeesElement,
6
+ css,
7
+ cssManager,
8
+ customElement,
9
+ html,
10
+ state,
11
+ type TemplateResult,
12
+ } from '@design.estate/dees-element';
13
+
14
+ @customElement('ops-view-users')
15
+ export class OpsViewUsers extends DeesElement {
16
+ @state() accessor usersState: appstate.IUsersState = {
17
+ users: [],
18
+ isLoading: false,
19
+ error: null,
20
+ lastUpdated: 0,
21
+ };
22
+
23
+ @state() accessor loginState: appstate.ILoginState = {
24
+ identity: null,
25
+ isLoggedIn: false,
26
+ };
27
+
28
+ constructor() {
29
+ super();
30
+ const usersSub = appstate.usersStatePart
31
+ .select((s) => s)
32
+ .subscribe((usersState) => {
33
+ this.usersState = usersState;
34
+ });
35
+ this.rxSubscriptions.push(usersSub);
36
+
37
+ const loginSub = appstate.loginStatePart
38
+ .select((s) => s)
39
+ .subscribe((loginState) => {
40
+ this.loginState = loginState;
41
+ // Re-fetch users when user logs in (fixes race condition where
42
+ // the view is created before authentication completes)
43
+ if (loginState.isLoggedIn) {
44
+ appstate.usersStatePart.dispatchAction(appstate.fetchUsersAction, null);
45
+ }
46
+ });
47
+ this.rxSubscriptions.push(loginSub);
48
+ }
49
+
50
+ public static styles = [
51
+ cssManager.defaultStyles,
52
+ viewHostCss,
53
+ css`
54
+ .usersContainer {
55
+ display: flex;
56
+ flex-direction: column;
57
+ gap: 24px;
58
+ }
59
+
60
+ .roleBadge {
61
+ display: inline-flex;
62
+ align-items: center;
63
+ padding: 3px 10px;
64
+ border-radius: 12px;
65
+ font-size: 12px;
66
+ font-weight: 600;
67
+ letter-spacing: 0.02em;
68
+ text-transform: uppercase;
69
+ }
70
+
71
+ .roleBadge.admin {
72
+ background: ${cssManager.bdTheme('#fef3c7', '#451a03')};
73
+ color: ${cssManager.bdTheme('#92400e', '#fbbf24')};
74
+ }
75
+
76
+ .roleBadge.user {
77
+ background: ${cssManager.bdTheme('#e0f2fe', '#0c4a6e')};
78
+ color: ${cssManager.bdTheme('#075985', '#7dd3fc')};
79
+ }
80
+
81
+ .sessionBadge {
82
+ display: inline-flex;
83
+ align-items: center;
84
+ padding: 3px 10px;
85
+ border-radius: 12px;
86
+ font-size: 12px;
87
+ font-weight: 600;
88
+ letter-spacing: 0.02em;
89
+ text-transform: uppercase;
90
+ background: ${cssManager.bdTheme('#dcfce7', '#14532d')};
91
+ color: ${cssManager.bdTheme('#166534', '#4ade80')};
92
+ }
93
+
94
+ .userIdCell {
95
+ font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
96
+ font-size: 11px;
97
+ color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};
98
+ }
99
+ `,
100
+ ];
101
+
102
+ public render(): TemplateResult {
103
+ const { users } = this.usersState;
104
+ const currentUserId = this.loginState.identity?.userId;
105
+
106
+ return html`
107
+ <dees-heading level="2">Users</dees-heading>
108
+
109
+ <div class="usersContainer">
110
+ <dees-table
111
+ .heading1=${'Users'}
112
+ .heading2=${'OpsServer user accounts'}
113
+ .data=${users}
114
+ .dataName=${'user'}
115
+ .searchable=${true}
116
+ .showColumnFilters=${true}
117
+ .displayFunction=${(user: appstate.IUser) => ({
118
+ ID: html`<span class="userIdCell">${user.id}</span>`,
119
+ Username: user.username,
120
+ Role: this.renderRoleBadge(user.role),
121
+ Session: user.id === currentUserId
122
+ ? html`<span class="sessionBadge">current</span>`
123
+ : '',
124
+ })}
125
+ ></dees-table>
126
+ </div>
127
+ `;
128
+ }
129
+
130
+ private renderRoleBadge(role: string): TemplateResult {
131
+ const cls = role === 'admin' ? 'admin' : 'user';
132
+ return html`<span class="roleBadge ${cls}">${role}</span>`;
133
+ }
134
+
135
+ async firstUpdated() {
136
+ if (this.loginState.isLoggedIn) {
137
+ await appstate.usersStatePart.dispatchAction(appstate.fetchUsersAction, null);
138
+ }
139
+ }
140
+ }
@@ -60,7 +60,7 @@ export class OpsViewEmails extends DeesElement {
60
60
 
61
61
  public render() {
62
62
  return html`
63
- <dees-heading level="2">Email Operations</dees-heading>
63
+ <dees-heading level="hr">Email Log</dees-heading>
64
64
  <div class="viewContainer">
65
65
  ${this.currentView === 'detail' && this.selectedEmail
66
66
  ? html`
@@ -347,6 +347,7 @@ export class OpsViewNetworkActivity extends DeesElement {
347
347
  heading1="Recent Network Activity"
348
348
  heading2="Recent network requests"
349
349
  searchable
350
+ .showColumnFilters=${true}
350
351
  .pagination=${true}
351
352
  .paginationSize=${50}
352
353
  dataName="request"
@@ -606,6 +607,8 @@ export class OpsViewNetworkActivity extends DeesElement {
606
607
  }}
607
608
  heading1="Top Connected IPs"
608
609
  heading2="IPs with most active connections and bandwidth"
610
+ searchable
611
+ .showColumnFilters=${true}
609
612
  .pagination=${false}
610
613
  dataName="ip"
611
614
  ></dees-table>
@@ -656,6 +659,7 @@ export class OpsViewNetworkActivity extends DeesElement {
656
659
  heading1="Backend Protocols"
657
660
  heading2="Auto-detected backend protocols and connection pool health"
658
661
  searchable
662
+ .showColumnFilters=${true}
659
663
  .pagination=${false}
660
664
  dataName="backend"
661
665
  ></dees-table>
@@ -36,6 +36,7 @@ import { OpsViewEmailSecurity } from './email/ops-view-email-security.js';
36
36
 
37
37
  // Access group
38
38
  import { OpsViewApiTokens } from './access/ops-view-apitokens.js';
39
+ import { OpsViewUsers } from './access/ops-view-users.js';
39
40
 
40
41
  // Security group
41
42
  import { OpsViewSecurityOverview } from './security/ops-view-security-overview.js';
@@ -114,6 +115,7 @@ export class OpsDashboard extends DeesElement {
114
115
  iconName: 'lucide:keyRound',
115
116
  subViews: [
116
117
  { slug: 'apitokens', name: 'API Tokens', iconName: 'lucide:key', element: OpsViewApiTokens },
118
+ { slug: 'users', name: 'Users', iconName: 'lucide:users', element: OpsViewUsers },
117
119
  ],
118
120
  },
119
121
  {
@@ -159,7 +159,7 @@ export class OpsViewCertificates extends DeesElement {
159
159
  const { summary } = this.certState;
160
160
 
161
161
  return html`
162
- <dees-heading level="2">Certificates</dees-heading>
162
+ <dees-heading level="hr">Certificates</dees-heading>
163
163
 
164
164
  <div class="certificatesContainer">
165
165
  ${this.renderStatsTiles(summary)}
@@ -39,7 +39,7 @@ export class OpsViewLogs extends DeesElement {
39
39
 
40
40
  public render() {
41
41
  return html`
42
- <dees-heading level="2">Logs</dees-heading>
42
+ <dees-heading level="hr">Logs</dees-heading>
43
43
 
44
44
  <dees-chart-log
45
45
  .label=${'Application Logs'}
@@ -57,7 +57,7 @@ export class OpsViewConfig extends DeesElement {
57
57
 
58
58
  public render() {
59
59
  return html`
60
- <dees-heading level="2">Configuration</dees-heading>
60
+ <dees-heading level="hr">Configuration</dees-heading>
61
61
 
62
62
  ${this.configState.isLoading
63
63
  ? html`
@@ -94,7 +94,7 @@ export class OpsViewOverview extends DeesElement {
94
94
 
95
95
  public render() {
96
96
  return html`
97
- <dees-heading level="2">Overview</dees-heading>
97
+ <dees-heading level="hr">Stats</dees-heading>
98
98
 
99
99
  ${this.statsState.isLoading ? html`
100
100
  <div class="loadingMessage">
package/ts_web/router.ts CHANGED
@@ -11,7 +11,7 @@ const subviewMap: Record<string, readonly string[]> = {
11
11
  overview: ['stats', 'configuration'] as const,
12
12
  network: ['activity', 'routes', 'sourceprofiles', 'networktargets', 'targetprofiles', 'remoteingress', 'vpn'] as const,
13
13
  email: ['log', 'security'] as const,
14
- access: ['apitokens'] as const,
14
+ access: ['apitokens', 'users'] as const,
15
15
  security: ['overview', 'blocked', 'authentication'] as const,
16
16
  };
17
17