Appearance
Shutdown Receiver
Initiates a controlled shutdown of the IPCom service. The shutdown process begins a few seconds after the request is received, allowing the API to respond before the service terminates.
Request
http
POST /api/shutdown-receiverAuthentication Required: Must include JWT token in Authorization header.
Required Scope: turnoff_receiver
Content-Type: application/json
Request Body: No request body required.
Request Examples
Basic Shutdown Request
bash
curl -X POST "http://your-server-ip:port/api/shutdown-receiver" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json"Using JavaScript
javascript
const response = await fetch('/api/shutdown-receiver', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});Response
Success (200 OK)
json
{
"success": true
}Error Responses
Standard HTTP error responses may be returned:
401 Unauthorized
json
{
"error": "NOT_LOGGED_IN"
}403 Forbidden
json
{
"error": "FORBIDDEN"
}405 Method Not Allowed
json
{
"error": "Method Not Allowed"
}Shutdown Process
Shutdown Sequence
- Request Received: API validates authentication and scope permissions
- Response Sent: Success response is immediately returned to client
- Delayed Shutdown: After a few seconds, the shutdown process begins
- Service Termination: IPCom service gracefully terminates
Usage Examples
Basic Shutdown
javascript
async function shutdownReceiver(token) {
try {
console.log('Initiating IPCom shutdown...');
const response = await fetch('/api/shutdown-receiver', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
const error = await response.json();
throw new Error(`HTTP ${response.status}: ${error.error}`);
}
const result = await response.json();
console.log('Shutdown initiated successfully');
console.log('IPCom service will terminate in a few seconds...');
return result;
} catch (error) {
console.error('Failed to initiate shutdown:', error);
throw error;
}
}Shutdown Manager Class
javascript
class ShutdownManager {
constructor(token) {
this.token = token;
}
async initiateShutdown(reason = 'Manual shutdown request') {
console.log(`Initiating shutdown: ${reason}`);
try {
// Log shutdown initiation
await this.logShutdownEvent('shutdown_initiated', reason);
const response = await fetch('/api/shutdown-receiver', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Shutdown failed: ${error.error}`);
}
const result = await response.json();
// Log successful shutdown request
await this.logShutdownEvent('shutdown_accepted', reason);
console.log('✓ Shutdown request accepted');
console.log('⚠ IPCom service will terminate shortly...');
return result;
} catch (error) {
// Log failed shutdown request
await this.logShutdownEvent('shutdown_failed', reason, error.message);
console.error('✗ Shutdown request failed:', error.message);
throw error;
}
}
async confirmAndShutdown(reason, confirmCallback = null) {
// Optional confirmation before shutdown
if (confirmCallback && !await confirmCallback(reason)) {
console.log('Shutdown cancelled by user');
return false;
}
return await this.initiateShutdown(reason);
}
async logShutdownEvent(event, reason, error = null) {
const logEntry = {
timestamp: new Date().toISOString(),
event: event,
reason: reason,
error: error,
user: this.getCurrentUser()
};
console.log('SHUTDOWN_EVENT:', JSON.stringify(logEntry));
// Log to local storage or external logging system
try {
const logs = JSON.parse(localStorage.getItem('shutdownLogs') || '[]');
logs.push(logEntry);
localStorage.setItem('shutdownLogs', JSON.stringify(logs));
} catch (storageError) {
console.warn('Could not save shutdown log locally:', storageError.message);
}
}
getCurrentUser() {
try {
const token = localStorage.getItem('authToken');
const payload = JSON.parse(atob(token.split('.')[1]));
return payload.username || payload.sub;
} catch {
return 'unknown';
}
}
}
// Usage
const shutdownManager = new ShutdownManager(authToken);
// Simple shutdown
await shutdownManager.initiateShutdown('Planned maintenance shutdown');
// Shutdown with confirmation
const confirmShutdown = async (reason) => {
return confirm(`Are you sure you want to shutdown IPCom?\nReason: ${reason}`);
};
await shutdownManager.confirmAndShutdown('Emergency shutdown', confirmShutdown);Maintenance Shutdown Workflow
javascript
class MaintenanceShutdown {
constructor(token) {
this.token = token;
this.shutdownManager = new ShutdownManager(token);
}
async performMaintenanceShutdown(maintenanceDetails) {
const shutdownPlan = {
reason: maintenanceDetails.reason || 'Scheduled maintenance',
scheduledTime: maintenanceDetails.scheduledTime || new Date(),
estimatedDowntime: maintenanceDetails.estimatedDowntime || 'Unknown',
contact: maintenanceDetails.contact || 'System Administrator'
};
console.log('=== MAINTENANCE SHUTDOWN INITIATED ===');
console.log(`Reason: ${shutdownPlan.reason}`);
console.log(`Scheduled: ${shutdownPlan.scheduledTime}`);
console.log(`Estimated Downtime: ${shutdownPlan.estimatedDowntime}`);
console.log(`Contact: ${shutdownPlan.contact}`);
console.log('==========================================');
try {
// Step 1: Notify about impending shutdown
await this.notifyActiveUsers(shutdownPlan);
// Step 2: Save current system state
await this.saveSystemState();
// Step 3: Log maintenance shutdown
await this.logMaintenanceShutdown(shutdownPlan, 'initiated');
// Step 4: Initiate shutdown
const result = await this.shutdownManager.initiateShutdown(shutdownPlan.reason);
// Step 5: Log successful shutdown request
await this.logMaintenanceShutdown(shutdownPlan, 'accepted');
console.log('✓ Maintenance shutdown initiated successfully');
console.log('⚠ System will be offline shortly');
return result;
} catch (error) {
await this.logMaintenanceShutdown(shutdownPlan, 'failed', error.message);
console.error('✗ Maintenance shutdown failed:', error.message);
throw error;
}
}
async notifyActiveUsers(shutdownPlan) {
console.log('Notifying active users about shutdown...');
// This would typically send notifications through WebSocket or other means
const notification = {
type: 'system_shutdown',
message: `System shutdown scheduled: ${shutdownPlan.reason}`,
estimatedDowntime: shutdownPlan.estimatedDowntime,
contact: shutdownPlan.contact,
timestamp: new Date().toISOString()
};
console.log('USER_NOTIFICATION:', JSON.stringify(notification));
// Simulate notification sending
try {
await fetch('/api/notifications/broadcast', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(notification)
});
} catch (error) {
console.warn('Could not send user notifications:', error.message);
}
}
async saveSystemState() {
console.log('Saving current system state...');
try {
// Get current system status
const statusResponse = await fetch('/api/status', {
headers: { 'Authorization': `Bearer ${this.token}` }
});
if (statusResponse.ok) {
const systemStatus = await statusResponse.json();
// Save to local storage or send to backup service
const stateSnapshot = {
timestamp: new Date().toISOString(),
systemStatus: systemStatus,
shutdownReason: 'Maintenance shutdown'
};
localStorage.setItem('lastSystemState', JSON.stringify(stateSnapshot));
console.log('✓ System state saved');
}
} catch (error) {
console.warn('Could not save system state:', error.message);
}
}
async logMaintenanceShutdown(shutdownPlan, status, error = null) {
const logEntry = {
timestamp: new Date().toISOString(),
action: 'maintenance_shutdown',
status: status,
plan: shutdownPlan,
error: error,
user: this.shutdownManager.getCurrentUser()
};
console.log('MAINTENANCE_LOG:', JSON.stringify(logEntry));
// Save to local storage or send to external logging system
try {
const logs = JSON.parse(localStorage.getItem('maintenanceLogs') || '[]');
logs.push(logEntry);
localStorage.setItem('maintenanceLogs', JSON.stringify(logs));
} catch (storageError) {
console.warn('Could not save maintenance log locally:', storageError.message);
}
}
}
// Usage
const maintenanceShutdown = new MaintenanceShutdown(authToken);
const maintenanceDetails = {
reason: 'Monthly system maintenance',
scheduledTime: new Date(),
estimatedDowntime: '2-4 hours',
contact: 'IT Support: +1-555-0123'
};
await maintenanceShutdown.performMaintenanceShutdown(maintenanceDetails);Emergency Shutdown
javascript
class EmergencyShutdown {
constructor(token) {
this.token = token;
this.shutdownManager = new ShutdownManager(token);
}
async performEmergencyShutdown(emergencyDetails) {
const emergency = {
reason: emergencyDetails.reason || 'Emergency shutdown',
severity: emergencyDetails.severity || 'HIGH',
reportedBy: emergencyDetails.reportedBy || 'System Monitor',
immediateAction: true
};
console.log('🚨 EMERGENCY SHUTDOWN INITIATED 🚨');
console.log(`Reason: ${emergency.reason}`);
console.log(`Severity: ${emergency.severity}`);
console.log(`Reported By: ${emergency.reportedBy}`);
console.log('=====================================');
try {
// Log emergency immediately
await this.logEmergencyEvent(emergency, 'initiated');
// Send emergency alert
await this.sendEmergencyAlert(emergency);
// Initiate immediate shutdown
const result = await this.shutdownManager.initiateShutdown(
`EMERGENCY: ${emergency.reason}`
);
// Log successful emergency shutdown
await this.logEmergencyEvent(emergency, 'shutdown_accepted');
console.log('🚨 Emergency shutdown initiated');
console.log('⚠ System terminating immediately');
return result;
} catch (error) {
await this.logEmergencyEvent(emergency, 'shutdown_failed', error.message);
console.error('🚨 Emergency shutdown failed:', error.message);
throw error;
}
}
async sendEmergencyAlert(emergency) {
const alert = {
type: 'EMERGENCY_SHUTDOWN',
severity: emergency.severity,
message: emergency.reason,
reportedBy: emergency.reportedBy,
timestamp: new Date().toISOString(),
requiresImmediate: true
};
console.log('EMERGENCY_ALERT:', JSON.stringify(alert));
// Send to emergency notification system
try {
await fetch('/api/emergency/alert', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(alert)
});
} catch (error) {
console.error('Could not send emergency alert:', error.message);
}
}
async logEmergencyEvent(emergency, status, error = null) {
const logEntry = {
timestamp: new Date().toISOString(),
action: 'emergency_shutdown',
status: status,
emergency: emergency,
error: error,
user: this.shutdownManager.getCurrentUser()
};
console.log('EMERGENCY_LOG:', JSON.stringify(logEntry));
// Save to local storage or send to external logging system
try {
const logs = JSON.parse(localStorage.getItem('emergencyLogs') || '[]');
logs.push(logEntry);
localStorage.setItem('emergencyLogs', JSON.stringify(logs));
} catch (storageError) {
console.warn('Could not save emergency log locally:', storageError.message);
}
}
}
// Usage
const emergencyShutdown = new EmergencyShutdown(authToken);
const emergencyDetails = {
reason: 'Critical system error detected',
severity: 'CRITICAL',
reportedBy: 'Automated Monitor'
};
await emergencyShutdown.performEmergencyShutdown(emergencyDetails);Error Handling and Validation
javascript
class ShutdownValidator {
static validateShutdownPermissions(token) {
try {
const payload = JSON.parse(atob(token.split('.')[1]));
const scopes = payload.scopes || [];
if (!scopes.includes('turnoff_receiver')) {
throw new Error('Insufficient permissions: turnoff_receiver scope required');
}
// Check token expiration
const now = Math.floor(Date.now() / 1000);
if (payload.exp && payload.exp < now) {
throw new Error('Token expired: Please log in again');
}
return true;
} catch (error) {
throw new Error(`Token validation failed: ${error.message}`);
}
}
static validateShutdownRequest(reason, userContext) {
// Validate reason
if (!reason || reason.trim().length === 0) {
throw new Error('Shutdown reason is required');
}
if (reason.length > 200) {
throw new Error('Shutdown reason too long (max 200 characters)');
}
// Validate user context
if (!userContext || !userContext.username) {
throw new Error('User context required for shutdown');
}
return true;
}
}
// Usage with validation
async function safeShutdown(token, reason, userContext) {
try {
// Validate permissions and request
ShutdownValidator.validateShutdownPermissions(token);
ShutdownValidator.validateShutdownRequest(reason, userContext);
// Proceed with shutdown
const shutdownManager = new ShutdownManager(token);
return await shutdownManager.initiateShutdown(reason);
} catch (error) {
console.error('Shutdown validation failed:', error.message);
throw error;
}
}Shutdown Status Monitor
javascript
class ShutdownStatusMonitor {
constructor(token) {
this.token = token;
this.shutdownHistory = [];
}
async monitoredShutdown(reason) {
const shutdownEvent = {
id: Date.now(),
reason: reason,
startTime: new Date(),
status: 'initiated'
};
this.shutdownHistory.push(shutdownEvent);
try {
// Capture pre-shutdown system state
const preShutdownStatus = await this.getSystemStatus();
shutdownEvent.preShutdownStatus = preShutdownStatus;
console.log(`Monitored shutdown initiated: ${reason}`);
// Perform shutdown
const shutdownManager = new ShutdownManager(this.token);
const result = await shutdownManager.initiateShutdown(reason);
// Update shutdown event
shutdownEvent.responseTime = new Date();
shutdownEvent.status = 'accepted';
shutdownEvent.success = true;
shutdownEvent.response = result;
console.log('✓ Shutdown request accepted and logged');
// Note: We cannot monitor actual shutdown completion since the service will terminate
console.log('⚠ Service will terminate - no further monitoring possible');
return shutdownEvent;
} catch (error) {
shutdownEvent.responseTime = new Date();
shutdownEvent.status = 'failed';
shutdownEvent.error = error.message;
shutdownEvent.success = false;
console.error('✗ Monitored shutdown failed:', error.message);
throw error;
}
}
async getSystemStatus() {
try {
const response = await fetch('/api/status', {
headers: { 'Authorization': `Bearer ${this.token}` }
});
if (response.ok) {
return await response.json();
}
} catch (error) {
console.warn('Could not fetch system status:', error.message);
}
return null;
}
getShutdownHistory() {
return this.shutdownHistory;
}
getLastShutdown() {
return this.shutdownHistory[this.shutdownHistory.length - 1];
}
}
// Usage
const shutdownMonitor = new ShutdownStatusMonitor(authToken);
// Perform monitored shutdown
const shutdownEvent = await shutdownMonitor.monitoredShutdown('Planned maintenance');
// Check shutdown history
const history = shutdownMonitor.getShutdownHistory();
console.log('Shutdown history:', history);Security Considerations
Access Control
- Critical Scope:
turnoff_receiverscope should be highly restricted - Admin Only: Typically only system administrators should have shutdown access
- Audit Requirements: All shutdown attempts must be logged for security audit
Shutdown Safety
- Confirmation Required: Always implement confirmation dialogs for shutdown
- Reason Logging: Require and log reasons for all shutdown requests
- Emergency Procedures: Have clear procedures for emergency vs planned shutdowns
Monitoring and Recovery
javascript
async function secureShutdown(token, reason, userContext, requireConfirmation = true) {
// Validate user and permissions
if (!userContext.isAdmin) {
throw new Error('Only administrators can initiate system shutdown');
}
// Require confirmation for non-emergency shutdowns
if (requireConfirmation && !reason.toLowerCase().includes('emergency')) {
const confirmed = confirm(
`CRITICAL ACTION: This will shutdown the entire IPCom system.\n\n` +
`Reason: ${reason}\n\n` +
`Are you absolutely sure you want to proceed?`
);
if (!confirmed) {
console.log('Shutdown cancelled by user');
return false;
}
}
// Log shutdown attempt locally
const shutdownLog = {
action: 'system_shutdown_initiated',
user: userContext.username,
reason: reason,
timestamp: new Date().toISOString(),
userAgent: navigator.userAgent,
ipAddress: userContext.ipAddress
};
console.log('SHUTDOWN_AUDIT:', JSON.stringify(shutdownLog));
try {
const shutdownManager = new ShutdownManager(token);
const result = await shutdownManager.initiateShutdown(reason);
// Log successful shutdown request
const successLog = {
action: 'system_shutdown_accepted',
user: userContext.username,
reason: reason,
success: true,
timestamp: new Date().toISOString()
};
console.log('SHUTDOWN_SUCCESS:', JSON.stringify(successLog));
return result;
} catch (error) {
// Log failed shutdown request
const errorLog = {
action: 'system_shutdown_failed',
user: userContext.username,
reason: reason,
success: false,
error: error.message,
timestamp: new Date().toISOString()
};
console.log('SHUTDOWN_ERROR:', JSON.stringify(errorLog));
throw error;
}
}Important Notes
- Critical Operation: This endpoint terminates the entire IPCom service
- Scope Required: Users must have the
turnoff_receiverscope (highly restricted) - Delayed Execution: Shutdown begins a few seconds after API response
- No Rollback: Once initiated, shutdown cannot be cancelled
- Service Unavailable: All API endpoints become unavailable after shutdown
- Manual Restart: IPCom service must be manually restarted after shutdown
- Data Safety: Ensure all critical data is saved before shutdown
- User Notification: Consider notifying active users before shutdown
- Emergency Use: Should be used only for planned maintenance or emergencies
- Audit Trail: All shutdown attempts should be logged for security and compliance
- Recovery Planning: Have clear procedures for restarting services after shutdown