File network-module.js of Package PersistenceOS
/**
* PersistenceOS Network Management Module
* Handles network interface management, configuration, and network-related functionality
*
* Depends on: core-utils.js, auth-module.js
*/
// =============================================================================
// NETWORK STATE MANAGEMENT
// =============================================================================
const networkState = {
networkInterfaces: [],
networkConnections: [],
networkRoutes: [],
firewallStatus: {
firewalld: { active: false, default_zone: '', zones: [] },
nftables: { active: false, rules_count: 0 }
},
dnsConfig: {
nameservers: [],
search_domains: [],
resolv_conf: ''
},
networkSettings: {},
selectedInterface: null,
connectionForm: {
name: '',
type: 'ethernet',
interface: '',
ipv4: {
method: 'auto',
address: '',
netmask: '',
gateway: ''
},
dns: {
servers: [],
search: []
}
},
networkStats: {
totalInterfaces: 0,
activeInterfaces: 0,
totalConnections: 0,
activeConnections: 0
},
networkLoading: false,
interfaceSearchTerm: '',
refreshInterval: null,
lastUpdate: null
};
// =============================================================================
// NETWORK DATA FUNCTIONS
// =============================================================================
/**
* Refresh network data from API
* @returns {Promise<void>}
*/
async function refreshNetworkData() {
networkState.networkLoading = true;
console.log('đ Refreshing network data...');
try {
// Fetch network interfaces
const interfacesData = await PersistenceCore.apiGet('/network/interfaces');
console.log('â
Network interfaces loaded:', interfacesData.interfaces?.length || 0);
networkState.networkInterfaces = interfacesData.interfaces || [];
// Fetch network routes
const routesData = await PersistenceCore.apiGet('/network/routes');
console.log('â
Network routes loaded:', routesData.routes?.length || 0);
networkState.networkRoutes = routesData.routes || [];
// Fetch firewall status
const firewallData = await PersistenceCore.apiGet('/network/firewall/status');
console.log('â
Firewall status loaded:', firewallData);
networkState.firewallStatus = firewallData || networkState.firewallStatus;
// Fetch DNS configuration
const dnsData = await PersistenceCore.apiGet('/network/dns');
console.log('â
DNS configuration loaded:', dnsData);
networkState.dnsConfig = dnsData || networkState.dnsConfig;
// Update network statistics
updateNetworkStats();
networkState.lastUpdate = new Date();
// Trigger custom event for Vue.js reactivity
window.dispatchEvent(new CustomEvent('network-data-updated', {
detail: {
interfaces: networkState.networkInterfaces,
routes: networkState.networkRoutes,
firewall: networkState.firewallStatus,
dns: networkState.dnsConfig,
stats: networkState.networkStats
}
}));
PersistenceCore.showNotification('â
Network data refreshed successfully', 'success');
} catch (error) {
console.error('â Error refreshing network data:', error);
PersistenceCore.showNotification('â Error refreshing network data', 'error');
} finally {
networkState.networkLoading = false;
}
}
/**
* Update network statistics
*/
function updateNetworkStats() {
const interfaces = networkState.networkInterfaces;
networkState.networkStats = {
totalInterfaces: interfaces.length,
activeInterfaces: interfaces.filter(iface => iface.state === 'up').length,
totalConnections: networkState.networkConnections.length,
activeConnections: networkState.networkConnections.filter(conn => conn.active).length
};
}
/**
* Get filtered interfaces based on search term
* @returns {Array}
*/
function getFilteredInterfaces() {
if (!networkState.interfaceSearchTerm) {
return networkState.networkInterfaces;
}
const searchTerm = networkState.interfaceSearchTerm.toLowerCase();
return networkState.networkInterfaces.filter(iface =>
iface.name.toLowerCase().includes(searchTerm) ||
iface.type.toLowerCase().includes(searchTerm)
);
}
// =============================================================================
// NETWORK INTERFACE OPERATIONS
// =============================================================================
/**
* Configure network interface
* @param {string} interfaceName - Interface name
* @returns {Promise<void>}
*/
async function configureInterface(interfaceName) {
console.log(`âī¸ Configuring interface: ${interfaceName}`);
const iface = networkState.networkInterfaces.find(i => i.name === interfaceName);
if (!iface) {
PersistenceCore.showNotification('Interface not found', 'error');
return;
}
// Create interface configuration modal
const modalHtml = `
<div id="configureInterfaceModal" class="modal" style="display: block;">
<div class="modal-content" style="max-width: 600px;">
<div class="modal-header">
<h3><i class="fas fa-cog"></i> Configure Interface - ${interfaceName}</h3>
<button class="close-btn" onclick="closeConfigureInterfaceModal()">
<i class="fas fa-times"></i>
</button>
</div>
<div class="modal-body">
<form id="interfaceConfigForm">
<div class="form-group">
<label>Interface Name:</label>
<input type="text" value="${iface.name}" readonly>
</div>
<div class="form-group">
<label>Configuration Method:</label>
<select id="configMethod">
<option value="auto">Automatic (DHCP)</option>
<option value="manual">Manual (Static IP)</option>
</select>
</div>
<div id="manualConfig" style="display: none;">
<div class="form-group">
<label>IP Address:</label>
<input type="text" id="ipAddress" placeholder="192.168.1.100">
</div>
<div class="form-group">
<label>Subnet Mask:</label>
<input type="text" id="subnetMask" placeholder="255.255.255.0">
</div>
<div class="form-group">
<label>Gateway:</label>
<input type="text" id="gateway" placeholder="192.168.1.1">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button onclick="closeConfigureInterfaceModal()" class="btn btn-secondary">Cancel</button>
<button onclick="applyInterfaceConfig('${interfaceName}')" class="btn btn-primary">Apply</button>
</div>
</div>
</div>
`;
// Add modal to DOM
document.body.insertAdjacentHTML('beforeend', modalHtml);
document.body.classList.add('modal-open');
// Add event listeners
document.getElementById('configMethod').addEventListener('change', (e) => {
const manualConfig = document.getElementById('manualConfig');
manualConfig.style.display = e.target.value === 'manual' ? 'block' : 'none';
});
// Add modal functions
window.closeConfigureInterfaceModal = () => {
const modal = document.getElementById('configureInterfaceModal');
if (modal) {
modal.remove();
document.body.classList.remove('modal-open');
}
delete window.closeConfigureInterfaceModal;
delete window.applyInterfaceConfig;
};
window.applyInterfaceConfig = async (name) => {
const method = document.getElementById('configMethod').value;
const config = { method };
if (method === 'manual') {
config.ipAddress = document.getElementById('ipAddress').value;
config.subnetMask = document.getElementById('subnetMask').value;
config.gateway = document.getElementById('gateway').value;
if (!config.ipAddress || !config.subnetMask) {
PersistenceCore.showNotification('Please fill in required fields', 'error');
return;
}
}
try {
await PersistenceCore.apiPost(`/network/interfaces/${name}/configure`, config);
PersistenceCore.showNotification(`Interface "${name}" configured successfully`, 'success');
window.closeConfigureInterfaceModal();
await refreshNetworkData();
} catch (error) {
console.error('â Failed to configure interface:', error);
PersistenceCore.showNotification('Failed to configure interface', 'error');
}
};
}
/**
* Toggle interface state (up/down)
* @param {string} interfaceName - Interface name
* @returns {Promise<void>}
*/
async function toggleInterface(interfaceName) {
console.log(`đ Toggling interface: ${interfaceName}`);
const iface = networkState.networkInterfaces.find(i => i.name === interfaceName);
if (!iface) {
PersistenceCore.showNotification('Interface not found', 'error');
return;
}
const action = iface.state === 'up' ? 'down' : 'up';
try {
await PersistenceCore.apiPost(`/network/interfaces/${interfaceName}/${action}`);
PersistenceCore.showNotification(`Interface "${interfaceName}" ${action === 'up' ? 'enabled' : 'disabled'}`, 'success');
await refreshNetworkData();
} catch (error) {
console.error(`â Failed to ${action} interface:`, error);
PersistenceCore.showNotification(`Failed to ${action} interface`, 'error');
}
}
/**
* Show interface details
* @param {string} interfaceName - Interface name
*/
function showInterfaceDetails(interfaceName) {
console.log(`âšī¸ Showing details for interface: ${interfaceName}`);
const iface = networkState.networkInterfaces.find(i => i.name === interfaceName);
if (!iface) {
PersistenceCore.showNotification('Interface not found', 'error');
return;
}
// Create interface details modal
const modalHtml = `
<div id="interfaceDetailsModal" class="modal" style="display: block;">
<div class="modal-content" style="max-width: 600px;">
<div class="modal-header">
<h3><i class="fas fa-info-circle"></i> Interface Details - ${interfaceName}</h3>
<button class="close-btn" onclick="closeInterfaceDetailsModal()">
<i class="fas fa-times"></i>
</button>
</div>
<div class="modal-body">
<div class="interface-details">
<h4>Basic Information</h4>
<p><strong>Name:</strong> ${iface.name}</p>
<p><strong>Type:</strong> ${iface.type}</p>
<p><strong>State:</strong> <span class="status-${iface.state}">${iface.state.toUpperCase()}</span></p>
<p><strong>MAC Address:</strong> ${iface.mac_address || 'N/A'}</p>
<p><strong>MTU:</strong> ${iface.mtu || 'N/A'}</p>
<h4>IP Configuration</h4>
${iface.ip_addresses && iface.ip_addresses.length > 0 ?
iface.ip_addresses.map(ip =>
`<p><strong>${ip.family.toUpperCase()}:</strong> ${ip.address}/${ip.prefix}</p>`
).join('') :
'<p>No IP addresses assigned</p>'
}
<h4>Statistics</h4>
<p><strong>RX Bytes:</strong> ${PersistenceCore.formatBytes(iface.rx_bytes || 0)}</p>
<p><strong>TX Bytes:</strong> ${PersistenceCore.formatBytes(iface.tx_bytes || 0)}</p>
<p><strong>RX Packets:</strong> ${iface.rx_packets || 0}</p>
<p><strong>TX Packets:</strong> ${iface.tx_packets || 0}</p>
</div>
</div>
<div class="modal-footer">
<button onclick="closeInterfaceDetailsModal()" class="btn btn-secondary">Close</button>
</div>
</div>
</div>
`;
// Add modal to DOM
document.body.insertAdjacentHTML('beforeend', modalHtml);
document.body.classList.add('modal-open');
// Add modal function
window.closeInterfaceDetailsModal = () => {
const modal = document.getElementById('interfaceDetailsModal');
if (modal) {
modal.remove();
document.body.classList.remove('modal-open');
}
delete window.closeInterfaceDetailsModal;
};
}
// =============================================================================
// NETWORK MONITORING
// =============================================================================
/**
* Start network monitoring with automatic refresh
*/
function startNetworkMonitoring() {
console.log('đ Starting network monitoring...');
// Clear existing interval
if (networkState.refreshInterval) {
clearInterval(networkState.refreshInterval);
}
// Set up refresh interval
networkState.refreshInterval = setInterval(async () => {
if (!networkState.networkLoading) {
await refreshNetworkData();
}
}, PersistenceCore.config.REFRESH_INTERVALS.NETWORK_DATA);
// Initial refresh
refreshNetworkData();
}
/**
* Stop network monitoring
*/
function stopNetworkMonitoring() {
console.log('âšī¸ Stopping network monitoring...');
if (networkState.refreshInterval) {
clearInterval(networkState.refreshInterval);
networkState.refreshInterval = null;
}
}
// =============================================================================
// INITIALIZATION
// =============================================================================
/**
* Initialize network module
*/
function initializeNetworkModule() {
console.log('đ Initializing network management module...');
// Start monitoring if authenticated
if (PersistenceAuth.state.isAuthenticated) {
startNetworkMonitoring();
}
// Listen for authentication changes
window.addEventListener('auth-state-changed', (event) => {
if (event.detail.isAuthenticated) {
startNetworkMonitoring();
} else {
stopNetworkMonitoring();
}
});
}
// Initialize on DOM ready
document.addEventListener('DOMContentLoaded', initializeNetworkModule);
// =============================================================================
// EXPORT FOR MODULE SYSTEM
// =============================================================================
window.PersistenceNetwork = {
state: networkState,
refreshNetworkData,
updateNetworkStats,
getFilteredInterfaces,
configureInterface,
toggleInterface,
showInterfaceDetails,
startNetworkMonitoring,
stopNetworkMonitoring,
initializeNetworkModule
};
console.log('â
PersistenceOS Network Management Module loaded');