Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
554d245c0c | |||
e3cb35a036 | |||
3a95ea9f4e | |||
99f57dba76 | |||
415e28038d | |||
7bda406624 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -19,5 +19,5 @@ dist_*/
|
|||||||
|
|
||||||
# custom
|
# custom
|
||||||
**/.claude/settings.local.json
|
**/.claude/settings.local.json
|
||||||
data/
|
.nogit/data/
|
||||||
readme.plan.md
|
readme.plan.md
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@serve.zone/dcrouter",
|
"name": "@serve.zone/dcrouter",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "2.12.1",
|
"version": "2.12.4",
|
||||||
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
@ -44,7 +44,7 @@
|
|||||||
"@push.rocks/smartnetwork": "^4.0.2",
|
"@push.rocks/smartnetwork": "^4.0.2",
|
||||||
"@push.rocks/smartpath": "^5.0.5",
|
"@push.rocks/smartpath": "^5.0.5",
|
||||||
"@push.rocks/smartpromise": "^4.0.3",
|
"@push.rocks/smartpromise": "^4.0.3",
|
||||||
"@push.rocks/smartproxy": "^19.5.25",
|
"@push.rocks/smartproxy": "^19.5.26",
|
||||||
"@push.rocks/smartrequest": "^2.1.0",
|
"@push.rocks/smartrequest": "^2.1.0",
|
||||||
"@push.rocks/smartrule": "^2.0.1",
|
"@push.rocks/smartrule": "^2.0.1",
|
||||||
"@push.rocks/smartrx": "^3.0.10",
|
"@push.rocks/smartrx": "^3.0.10",
|
||||||
|
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@ -69,8 +69,8 @@ importers:
|
|||||||
specifier: ^4.0.3
|
specifier: ^4.0.3
|
||||||
version: 4.2.3
|
version: 4.2.3
|
||||||
'@push.rocks/smartproxy':
|
'@push.rocks/smartproxy':
|
||||||
specifier: ^19.5.25
|
specifier: ^19.5.26
|
||||||
version: 19.5.25(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)
|
version: 19.5.26(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)
|
||||||
'@push.rocks/smartrequest':
|
'@push.rocks/smartrequest':
|
||||||
specifier: ^2.1.0
|
specifier: ^2.1.0
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
@ -1052,8 +1052,8 @@ packages:
|
|||||||
'@push.rocks/smartpromise@4.2.3':
|
'@push.rocks/smartpromise@4.2.3':
|
||||||
resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==}
|
resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==}
|
||||||
|
|
||||||
'@push.rocks/smartproxy@19.5.25':
|
'@push.rocks/smartproxy@19.5.26':
|
||||||
resolution: {integrity: sha512-YkqTYWD4vda/zLKqf+wMMUBPeesacJvP0Owa0tddZvE+dn6eFwEgcFC/dzWbgX/esOAR/TMc/7NV6DsXcXRSHA==}
|
resolution: {integrity: sha512-hCQcIZWX6wjKuom7HYYeGhuRijgU+R958WACDauKfQEDTTzF00STH4GB5KcL7kbaF+20Tx5IBR7pvzHTRjJmQg==}
|
||||||
|
|
||||||
'@push.rocks/smartpuppeteer@2.0.5':
|
'@push.rocks/smartpuppeteer@2.0.5':
|
||||||
resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==}
|
resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==}
|
||||||
@ -6180,7 +6180,7 @@ snapshots:
|
|||||||
|
|
||||||
'@push.rocks/smartpromise@4.2.3': {}
|
'@push.rocks/smartpromise@4.2.3': {}
|
||||||
|
|
||||||
'@push.rocks/smartproxy@19.5.25(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)':
|
'@push.rocks/smartproxy@19.5.26(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/lik': 6.2.2
|
'@push.rocks/lik': 6.2.2
|
||||||
'@push.rocks/smartacme': 8.0.0(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)
|
'@push.rocks/smartacme': 8.0.0(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)
|
||||||
|
8
ts_interfaces/data/auth.ts
Normal file
8
ts_interfaces/data/auth.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export interface IIdentity {
|
||||||
|
jwt: string;
|
||||||
|
userId: string;
|
||||||
|
name: string;
|
||||||
|
expiresAt: number;
|
||||||
|
role?: string;
|
||||||
|
type?: string;
|
||||||
|
}
|
2
ts_interfaces/data/index.ts
Normal file
2
ts_interfaces/data/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './auth.js';
|
||||||
|
export * from './stats.js';
|
101
ts_interfaces/data/stats.ts
Normal file
101
ts_interfaces/data/stats.ts
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
export interface IServerStats {
|
||||||
|
uptime: number;
|
||||||
|
startTime: number;
|
||||||
|
memoryUsage: {
|
||||||
|
heapUsed: number;
|
||||||
|
heapTotal: number;
|
||||||
|
external: number;
|
||||||
|
rss: number;
|
||||||
|
};
|
||||||
|
cpuUsage: {
|
||||||
|
user: number;
|
||||||
|
system: number;
|
||||||
|
};
|
||||||
|
activeConnections: number;
|
||||||
|
totalConnections: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IEmailStats {
|
||||||
|
sent: number;
|
||||||
|
received: number;
|
||||||
|
bounced: number;
|
||||||
|
queued: number;
|
||||||
|
failed: number;
|
||||||
|
averageDeliveryTime: number;
|
||||||
|
deliveryRate: number;
|
||||||
|
bounceRate: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDnsStats {
|
||||||
|
totalQueries: number;
|
||||||
|
cacheHits: number;
|
||||||
|
cacheMisses: number;
|
||||||
|
cacheHitRate: number;
|
||||||
|
activeDomains: number;
|
||||||
|
averageResponseTime: number;
|
||||||
|
queryTypes: {
|
||||||
|
[key: string]: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRateLimitInfo {
|
||||||
|
domain: string;
|
||||||
|
currentRate: number;
|
||||||
|
limit: number;
|
||||||
|
remaining: number;
|
||||||
|
resetTime: number;
|
||||||
|
blocked: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISecurityMetrics {
|
||||||
|
blockedIPs: string[];
|
||||||
|
reputationScores: {
|
||||||
|
[domain: string]: number;
|
||||||
|
};
|
||||||
|
spamDetected: number;
|
||||||
|
malwareDetected: number;
|
||||||
|
phishingDetected: number;
|
||||||
|
authenticationFailures: number;
|
||||||
|
suspiciousActivities: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILogEntry {
|
||||||
|
timestamp: number;
|
||||||
|
level: 'debug' | 'info' | 'warn' | 'error';
|
||||||
|
category: 'smtp' | 'dns' | 'security' | 'system' | 'email';
|
||||||
|
message: string;
|
||||||
|
metadata?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IConnectionInfo {
|
||||||
|
id: string;
|
||||||
|
remoteAddress: string;
|
||||||
|
localAddress: string;
|
||||||
|
startTime: number;
|
||||||
|
protocol: 'smtp' | 'smtps' | 'http' | 'https';
|
||||||
|
state: 'connecting' | 'connected' | 'authenticated' | 'transmitting' | 'closing';
|
||||||
|
bytesReceived: number;
|
||||||
|
bytesSent: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IQueueStatus {
|
||||||
|
name: string;
|
||||||
|
size: number;
|
||||||
|
processing: number;
|
||||||
|
failed: number;
|
||||||
|
retrying: number;
|
||||||
|
averageProcessingTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IHealthStatus {
|
||||||
|
healthy: boolean;
|
||||||
|
uptime: number;
|
||||||
|
services: {
|
||||||
|
[service: string]: {
|
||||||
|
status: 'healthy' | 'degraded' | 'unhealthy';
|
||||||
|
message?: string;
|
||||||
|
lastCheck: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
version?: string;
|
||||||
|
}
|
@ -50,7 +50,7 @@ export const loginStatePart = await appState.getStatePart<ILoginState>(
|
|||||||
identity: null,
|
identity: null,
|
||||||
isLoggedIn: false,
|
isLoggedIn: false,
|
||||||
},
|
},
|
||||||
'persistent' // Login state persists across sessions
|
'soft' // Login state persists across sessions
|
||||||
);
|
);
|
||||||
|
|
||||||
export const statsStatePart = await appState.getStatePart<IStatsState>(
|
export const statsStatePart = await appState.getStatePart<IStatsState>(
|
||||||
@ -73,8 +73,7 @@ export const configStatePart = await appState.getStatePart<IConfigState>(
|
|||||||
config: null,
|
config: null,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
},
|
}
|
||||||
'soft'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const uiStatePart = await appState.getStatePart<IUiState>(
|
export const uiStatePart = await appState.getStatePart<IUiState>(
|
||||||
@ -86,7 +85,6 @@ export const uiStatePart = await appState.getStatePart<IUiState>(
|
|||||||
refreshInterval: 30000, // 30 seconds
|
refreshInterval: 30000, // 30 seconds
|
||||||
theme: 'light',
|
theme: 'light',
|
||||||
},
|
},
|
||||||
'persistent' // UI preferences persist
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const logStatePart = await appState.getStatePart<ILogState>(
|
export const logStatePart = await appState.getStatePart<ILogState>(
|
||||||
|
@ -75,13 +75,6 @@ export class OpsDashboard extends DeesElement {
|
|||||||
<div class="maincontainer">
|
<div class="maincontainer">
|
||||||
<dees-simple-login
|
<dees-simple-login
|
||||||
name="DCRouter OpsServer"
|
name="DCRouter OpsServer"
|
||||||
.loginAction=${async (username: string, password: string) => {
|
|
||||||
await appstate.loginStatePart.dispatchAction(appstate.loginAction, {
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
});
|
|
||||||
return this.loginState.isLoggedIn;
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<dees-simple-appdash
|
<dees-simple-appdash
|
||||||
name="DCRouter OpsServer"
|
name="DCRouter OpsServer"
|
||||||
@ -121,4 +114,52 @@ export class OpsDashboard extends DeesElement {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async firstUpdated() {
|
||||||
|
const simpleLogin = this.shadowRoot.querySelector('dees-simple-login');
|
||||||
|
simpleLogin.addEventListener('login', (e: CustomEvent) => {
|
||||||
|
console.log(e.detail);
|
||||||
|
this.login(e.detail.data.username, e.detail.data.password);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle initial state
|
||||||
|
const loginState = appstate.loginStatePart.getState();
|
||||||
|
console.log('Initial login state:', loginState);
|
||||||
|
if (loginState.identity) {
|
||||||
|
this.loginState = loginState;
|
||||||
|
await simpleLogin.switchToSlottedContent();
|
||||||
|
await appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null);
|
||||||
|
await appstate.configStatePart.dispatchAction(appstate.fetchConfigurationAction, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async login(username: string, password: string) {
|
||||||
|
const domtools = await this.domtoolsPromise;
|
||||||
|
console.log(`Attempting to login...`);
|
||||||
|
const simpleLogin = this.shadowRoot.querySelector('dees-simple-login');
|
||||||
|
const form = simpleLogin.shadowRoot.querySelector('dees-form');
|
||||||
|
form.setStatus('pending', 'Logging in...');
|
||||||
|
|
||||||
|
const state = await appstate.loginStatePart.dispatchAction(appstate.loginAction, {
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (state.identity) {
|
||||||
|
console.log('Login successful');
|
||||||
|
this.loginState = state;
|
||||||
|
form.setStatus('success', 'Logged in!');
|
||||||
|
await simpleLogin.switchToSlottedContent();
|
||||||
|
await appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null);
|
||||||
|
await appstate.configStatePart.dispatchAction(appstate.fetchConfigurationAction, null);
|
||||||
|
} else {
|
||||||
|
form.setStatus('error', 'Login failed!');
|
||||||
|
await domtools.convenience.smartdelay.delayFor(2000);
|
||||||
|
form.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async logout() {
|
||||||
|
await appstate.loginStatePart.dispatchAction(appstate.logoutAction, null);
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user