406 lines
13 KiB
TypeScript
406 lines
13 KiB
TypeScript
import * as plugins from '../../plugins.js';
|
|
import type { OpsServer } from '../classes.opsserver.js';
|
|
import * as interfaces from '../../../ts_interfaces/index.js';
|
|
|
|
export class RadiusHandler {
|
|
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
|
|
constructor(private opsServerRef: OpsServer) {
|
|
// Add this handler's router to the parent
|
|
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
this.registerHandlers();
|
|
}
|
|
|
|
private registerHandlers(): void {
|
|
// ========================================================================
|
|
// RADIUS Client Management
|
|
// ========================================================================
|
|
|
|
// Get all RADIUS clients
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRadiusClients>(
|
|
'getRadiusClients',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return { clients: [] };
|
|
}
|
|
|
|
const clients = radiusServer.getClients();
|
|
return {
|
|
clients: clients.map(c => ({
|
|
name: c.name,
|
|
ipRange: c.ipRange,
|
|
description: c.description,
|
|
enabled: c.enabled,
|
|
})),
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
// Add or update a RADIUS client
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_SetRadiusClient>(
|
|
'setRadiusClient',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return { success: false, message: 'RADIUS server not configured' };
|
|
}
|
|
|
|
try {
|
|
await radiusServer.addClient(dataArg.client);
|
|
return { success: true };
|
|
} catch (error) {
|
|
return { success: false, message: error.message };
|
|
}
|
|
}
|
|
)
|
|
);
|
|
|
|
// Remove a RADIUS client
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RemoveRadiusClient>(
|
|
'removeRadiusClient',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return { success: false, message: 'RADIUS server not configured' };
|
|
}
|
|
|
|
const removed = radiusServer.removeClient(dataArg.name);
|
|
return {
|
|
success: removed,
|
|
message: removed ? undefined : 'Client not found',
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
// ========================================================================
|
|
// VLAN Mapping Management
|
|
// ========================================================================
|
|
|
|
// Get all VLAN mappings
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetVlanMappings>(
|
|
'getVlanMappings',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return {
|
|
mappings: [],
|
|
config: { defaultVlan: 1, allowUnknownMacs: true },
|
|
};
|
|
}
|
|
|
|
const vlanManager = radiusServer.getVlanManager();
|
|
const mappings = vlanManager.getAllMappings();
|
|
const config = vlanManager.getConfig();
|
|
|
|
return {
|
|
mappings: mappings.map(m => ({
|
|
mac: m.mac,
|
|
vlan: m.vlan,
|
|
description: m.description,
|
|
enabled: m.enabled,
|
|
createdAt: m.createdAt,
|
|
updatedAt: m.updatedAt,
|
|
})),
|
|
config: {
|
|
defaultVlan: config.defaultVlan,
|
|
allowUnknownMacs: config.allowUnknownMacs,
|
|
},
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
// Add or update a VLAN mapping
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_SetVlanMapping>(
|
|
'setVlanMapping',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return { success: false, message: 'RADIUS server not configured' };
|
|
}
|
|
|
|
try {
|
|
const vlanManager = radiusServer.getVlanManager();
|
|
const mapping = await vlanManager.addMapping(dataArg.mapping);
|
|
return {
|
|
success: true,
|
|
mapping: {
|
|
mac: mapping.mac,
|
|
vlan: mapping.vlan,
|
|
description: mapping.description,
|
|
enabled: mapping.enabled,
|
|
createdAt: mapping.createdAt,
|
|
updatedAt: mapping.updatedAt,
|
|
},
|
|
};
|
|
} catch (error) {
|
|
return { success: false, message: error.message };
|
|
}
|
|
}
|
|
)
|
|
);
|
|
|
|
// Remove a VLAN mapping
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RemoveVlanMapping>(
|
|
'removeVlanMapping',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return { success: false, message: 'RADIUS server not configured' };
|
|
}
|
|
|
|
const vlanManager = radiusServer.getVlanManager();
|
|
const removed = await vlanManager.removeMapping(dataArg.mac);
|
|
return {
|
|
success: removed,
|
|
message: removed ? undefined : 'Mapping not found',
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
// Update VLAN configuration
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateVlanConfig>(
|
|
'updateVlanConfig',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return {
|
|
success: false,
|
|
config: { defaultVlan: 1, allowUnknownMacs: true },
|
|
};
|
|
}
|
|
|
|
const vlanManager = radiusServer.getVlanManager();
|
|
vlanManager.updateConfig({
|
|
defaultVlan: dataArg.defaultVlan,
|
|
allowUnknownMacs: dataArg.allowUnknownMacs,
|
|
});
|
|
|
|
const config = vlanManager.getConfig();
|
|
return {
|
|
success: true,
|
|
config: {
|
|
defaultVlan: config.defaultVlan,
|
|
allowUnknownMacs: config.allowUnknownMacs,
|
|
},
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
// Test VLAN assignment
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_TestVlanAssignment>(
|
|
'testVlanAssignment',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return { assigned: false, vlan: 0, isDefault: false };
|
|
}
|
|
|
|
const vlanManager = radiusServer.getVlanManager();
|
|
const result = vlanManager.assignVlan(dataArg.mac);
|
|
|
|
return {
|
|
assigned: result.assigned,
|
|
vlan: result.vlan,
|
|
isDefault: result.isDefault,
|
|
matchedRule: result.matchedRule
|
|
? {
|
|
mac: result.matchedRule.mac,
|
|
vlan: result.matchedRule.vlan,
|
|
description: result.matchedRule.description,
|
|
}
|
|
: undefined,
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
// ========================================================================
|
|
// Accounting / Session Management
|
|
// ========================================================================
|
|
|
|
// Get active sessions
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRadiusSessions>(
|
|
'getRadiusSessions',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return { sessions: [], totalCount: 0 };
|
|
}
|
|
|
|
const accountingManager = radiusServer.getAccountingManager();
|
|
let sessions = accountingManager.getActiveSessions();
|
|
|
|
// Apply filters
|
|
if (dataArg.filter) {
|
|
if (dataArg.filter.username) {
|
|
sessions = sessions.filter(s => s.username === dataArg.filter!.username);
|
|
}
|
|
if (dataArg.filter.nasIpAddress) {
|
|
sessions = sessions.filter(s => s.nasIpAddress === dataArg.filter!.nasIpAddress);
|
|
}
|
|
if (dataArg.filter.vlanId !== undefined) {
|
|
sessions = sessions.filter(s => s.vlanId === dataArg.filter!.vlanId);
|
|
}
|
|
}
|
|
|
|
return {
|
|
sessions: sessions.map(s => ({
|
|
sessionId: s.sessionId,
|
|
username: s.username,
|
|
macAddress: s.macAddress,
|
|
nasIpAddress: s.nasIpAddress,
|
|
nasIdentifier: s.nasIdentifier,
|
|
vlanId: s.vlanId,
|
|
framedIpAddress: s.framedIpAddress,
|
|
startTime: s.startTime,
|
|
lastUpdateTime: s.lastUpdateTime,
|
|
status: s.status,
|
|
inputOctets: s.inputOctets,
|
|
outputOctets: s.outputOctets,
|
|
sessionTime: s.sessionTime,
|
|
})),
|
|
totalCount: sessions.length,
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
// Disconnect a session
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DisconnectRadiusSession>(
|
|
'disconnectRadiusSession',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return { success: false, message: 'RADIUS server not configured' };
|
|
}
|
|
|
|
const accountingManager = radiusServer.getAccountingManager();
|
|
const disconnected = await accountingManager.disconnectSession(
|
|
dataArg.sessionId,
|
|
dataArg.reason || 'AdminReset'
|
|
);
|
|
|
|
return {
|
|
success: disconnected,
|
|
message: disconnected ? undefined : 'Session not found',
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
// Get accounting summary
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRadiusAccountingSummary>(
|
|
'getRadiusAccountingSummary',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return {
|
|
summary: {
|
|
periodStart: dataArg.startTime,
|
|
periodEnd: dataArg.endTime,
|
|
totalSessions: 0,
|
|
activeSessions: 0,
|
|
totalInputBytes: 0,
|
|
totalOutputBytes: 0,
|
|
totalSessionTime: 0,
|
|
averageSessionDuration: 0,
|
|
uniqueUsers: 0,
|
|
sessionsByVlan: {},
|
|
topUsersByTraffic: [],
|
|
},
|
|
};
|
|
}
|
|
|
|
const accountingManager = radiusServer.getAccountingManager();
|
|
const summary = await accountingManager.getSummary(dataArg.startTime, dataArg.endTime);
|
|
|
|
return { summary };
|
|
}
|
|
)
|
|
);
|
|
|
|
// ========================================================================
|
|
// Statistics
|
|
// ========================================================================
|
|
|
|
// Get RADIUS statistics
|
|
this.typedrouter.addTypedHandler(
|
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetRadiusStatistics>(
|
|
'getRadiusStatistics',
|
|
async (dataArg, toolsArg) => {
|
|
const radiusServer = this.opsServerRef.dcRouterRef.radiusServer;
|
|
|
|
if (!radiusServer) {
|
|
return {
|
|
stats: {
|
|
running: false,
|
|
uptime: 0,
|
|
authRequests: 0,
|
|
authAccepts: 0,
|
|
authRejects: 0,
|
|
accountingRequests: 0,
|
|
activeSessions: 0,
|
|
vlanMappings: 0,
|
|
clients: 0,
|
|
},
|
|
vlanStats: {
|
|
totalMappings: 0,
|
|
enabledMappings: 0,
|
|
exactMatches: 0,
|
|
ouiPatterns: 0,
|
|
wildcardPatterns: 0,
|
|
},
|
|
accountingStats: {
|
|
activeSessions: 0,
|
|
totalSessionsStarted: 0,
|
|
totalSessionsStopped: 0,
|
|
totalInputBytes: 0,
|
|
totalOutputBytes: 0,
|
|
interimUpdatesReceived: 0,
|
|
},
|
|
};
|
|
}
|
|
|
|
const stats = radiusServer.getStats();
|
|
const vlanStats = radiusServer.getVlanManager().getStats();
|
|
const accountingStats = radiusServer.getAccountingManager().getStats();
|
|
|
|
return {
|
|
stats,
|
|
vlanStats,
|
|
accountingStats,
|
|
};
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|