101 lines
3.1 KiB
TypeScript
101 lines
3.1 KiB
TypeScript
import axios from 'axios';
|
|
import https from 'https';
|
|
|
|
export class OpnsenseService {
|
|
private baseUrl: string;
|
|
private apiKey: string;
|
|
private apiSecret: string;
|
|
private client: any;
|
|
|
|
constructor(ipAddress: string, apiKey: string, apiSecret: string) {
|
|
// Assuming HTTPS access to OPNsense, might need to adjust port if custom
|
|
this.baseUrl = `https://${ipAddress}/api`;
|
|
this.apiKey = apiKey;
|
|
this.apiSecret = apiSecret;
|
|
|
|
// OPNsense uses basic auth with API Key and Secret
|
|
// We ignore SSL errors because OPNsense often has self-signed certs
|
|
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
|
|
|
this.client = axios.create({
|
|
baseURL: this.baseUrl,
|
|
auth: {
|
|
username: this.apiKey,
|
|
password: this.apiSecret,
|
|
},
|
|
httpsAgent,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Health check to test API connectivity
|
|
*/
|
|
async testConnection(): Promise<boolean> {
|
|
try {
|
|
// Fetching core firmware info as a simple ping
|
|
const response = await this.client.get('/core/firmware/info');
|
|
return response.status === 200;
|
|
} catch (error) {
|
|
console.error('OPNsense API Connection Error:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Captive Portal: Add or update a voucher/user session
|
|
* This allows the hotspot system to authenticate a user automatically via API
|
|
*/
|
|
async authHotspotUser(zoneId: string, username: string, ipAddress: string): Promise<any> {
|
|
try {
|
|
// POST /api/captiveportal/session/connect/
|
|
const payload = {
|
|
zoneid: zoneId,
|
|
user: username,
|
|
ip: ipAddress,
|
|
};
|
|
|
|
// OPNsense expects URL encoded form data or specific JSON structure depending on the endpoint
|
|
// Using generic captiveportal session connect endpoint
|
|
const response = await this.client.post(`/captiveportal/session/connect`, payload);
|
|
return response.data;
|
|
} catch (error) {
|
|
console.error('Error authenticating hotspot user:', error);
|
|
throw new Error('Could not authenticate hotspot user on OPNsense');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Captive Portal: Disconnect a user
|
|
*/
|
|
async disconnectHotspotUser(zoneId: string, sessionId: string): Promise<any> {
|
|
try {
|
|
const payload = {
|
|
zoneid: zoneId,
|
|
sessionid: sessionId
|
|
};
|
|
const response = await this.client.post(`/captiveportal/session/disconnect`, payload);
|
|
return response.data;
|
|
} catch (error) {
|
|
console.error('Error disconnecting hotspot user:', error);
|
|
throw new Error('Could not disconnect hotspot user on OPNsense');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Traffic Shaper: Add a rule (e.g. for speed limits)
|
|
*/
|
|
async addShaperRule(ruleData: any): Promise<any> {
|
|
try {
|
|
const response = await this.client.post('/trafficshaper/rule/addRule', { rule: ruleData });
|
|
|
|
// Apply the changes (shaper requires an explicit apply call)
|
|
await this.client.post('/trafficshaper/service/reconfigure');
|
|
|
|
return response.data;
|
|
} catch (error) {
|
|
console.error('Error adding shaper rule:', error);
|
|
throw new Error('Could not add traffic shaper rule on OPNsense');
|
|
}
|
|
}
|
|
}
|