feat(radius): add RADIUS server with MAC authentication (MAB), VLAN assignment, accounting and OpsServer API handlers

This commit is contained in:
2026-02-01 19:21:37 +00:00
parent fcea194cf6
commit c2d3ace0dd
31 changed files with 2498 additions and 531 deletions

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@serve.zone/dcrouter',
version: '2.12.6',
version: '2.13.0',
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
}

View File

@@ -21,12 +21,12 @@ import { OpsViewSecurity } from './ops-view-security.js';
@customElement('ops-dashboard')
export class OpsDashboard extends DeesElement {
@state() private loginState: appstate.ILoginState = {
@state() accessor loginState: appstate.ILoginState = {
identity: null,
isLoggedIn: false,
};
@state() private uiState: appstate.IUiState = {
@state() accessor uiState: appstate.IUiState = {
activeView: 'overview',
sidebarCollapsed: false,
autoRefresh: true,

View File

@@ -14,17 +14,17 @@ import {
@customElement('ops-view-config')
export class OpsViewConfig extends DeesElement {
@state()
private configState: appstate.IConfigState = {
accessor configState: appstate.IConfigState = {
config: null,
isLoading: false,
error: null,
};
@state()
private editingSection: string | null = null;
accessor editingSection: string | null = null;
@state()
private editedConfig: any = null;
accessor editedConfig: any = null;
constructor() {
super();

View File

@@ -33,25 +33,25 @@ interface IEmail {
@customElement('ops-view-emails')
export class OpsViewEmails extends DeesElement {
@state()
private selectedFolder: 'inbox' | 'sent' | 'draft' | 'trash' = 'inbox';
accessor selectedFolder: 'inbox' | 'sent' | 'draft' | 'trash' = 'inbox';
@state()
private emails: IEmail[] = [];
accessor emails: IEmail[] = [];
@state()
private selectedEmail: IEmail | null = null;
accessor selectedEmail: IEmail | null = null;
@state()
private showCompose = false;
accessor showCompose = false;
@state()
private isLoading = false;
accessor isLoading = false;
@state()
private searchTerm = '';
accessor searchTerm = '';
@state()
private emailDomains: string[] = [];
accessor emailDomains: string[] = [];
constructor() {
super();

View File

@@ -14,7 +14,7 @@ import {
@customElement('ops-view-logs')
export class OpsViewLogs extends DeesElement {
@state()
private logState: appstate.ILogState = {
accessor logState: appstate.ILogState = {
recentLogs: [],
isStreaming: false,
filters: {},

View File

@@ -28,20 +28,20 @@ interface INetworkRequest {
@customElement('ops-view-network')
export class OpsViewNetwork extends DeesElement {
@state()
private statsState = appstate.statsStatePart.getState();
accessor statsState = appstate.statsStatePart.getState();
@state()
private networkState = appstate.networkStatePart.getState();
accessor networkState = appstate.networkStatePart.getState();
@state()
private networkRequests: INetworkRequest[] = [];
accessor networkRequests: INetworkRequest[] = [];
@state()
private trafficDataIn: Array<{ x: string | number; y: number }> = [];
accessor trafficDataIn: Array<{ x: string | number; y: number }> = [];
@state()
private trafficDataOut: Array<{ x: string | number; y: number }> = [];
accessor trafficDataOut: Array<{ x: string | number; y: number }> = [];
// Track if we need to update the chart to avoid unnecessary re-renders
private lastChartUpdate = 0;

View File

@@ -16,7 +16,7 @@ import { type IStatsTile } from '@design.estate/dees-catalog';
@customElement('ops-view-overview')
export class OpsViewOverview extends DeesElement {
@state()
private statsState: appstate.IStatsState = {
accessor statsState: appstate.IStatsState = {
serverStats: null,
emailStats: null,
dnsStats: null,

View File

@@ -15,7 +15,7 @@ import { type IStatsTile } from '@design.estate/dees-catalog';
@customElement('ops-view-security')
export class OpsViewSecurity extends DeesElement {
@state()
private statsState: appstate.IStatsState = {
accessor statsState: appstate.IStatsState = {
serverStats: null,
emailStats: null,
dnsStats: null,
@@ -26,7 +26,7 @@ export class OpsViewSecurity extends DeesElement {
};
@state()
private selectedTab: 'overview' | 'blocked' | 'authentication' | 'email-security' = 'overview';
accessor selectedTab: 'overview' | 'blocked' | 'authentication' | 'email-security' = 'overview';
constructor() {
super();