69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
import { Router } from 'express';
|
|
import { PrismaClient } from '@prisma/client';
|
|
|
|
const router = Router();
|
|
const prisma = new PrismaClient();
|
|
|
|
// Helper to generate a VPN IP for a new device
|
|
async function getNextVpnIp(): Promise<string> {
|
|
const baseIp = '10.10.0.';
|
|
// Find the highest VPN IP currently in use
|
|
const lastDevice = await prisma.device.findFirst({
|
|
where: { vpnIp: { startsWith: baseIp } },
|
|
orderBy: { vpnIp: 'desc' }
|
|
});
|
|
|
|
if (!lastDevice || !lastDevice.vpnIp) {
|
|
return `${baseIp}1`; // Start with 10.10.0.1
|
|
}
|
|
|
|
const lastOctet = parseInt(lastDevice.vpnIp.split('.')[3], 10);
|
|
if (lastOctet >= 254) {
|
|
throw new Error('VPN IP pool exhausted in this subnet');
|
|
}
|
|
|
|
return `${baseIp}${lastOctet + 1}`;
|
|
}
|
|
|
|
// Get all devices
|
|
router.get('/', async (req, res) => {
|
|
try {
|
|
const devices = await prisma.device.findMany({ include: { tenant: true } });
|
|
res.json(devices);
|
|
} catch (error) {
|
|
res.status(500).json({ error: 'Internal server error' });
|
|
}
|
|
});
|
|
|
|
// Create device for a tenant
|
|
router.post('/', async (req, res) => {
|
|
try {
|
|
const { tenantId, name, macAddress, opnsenseUrl, apiKey, apiSecret } = req.body;
|
|
|
|
// Automatically generate the VPN IP for this customer device
|
|
const nextVpnIp = await getNextVpnIp();
|
|
|
|
const newDevice = await prisma.device.create({
|
|
data: {
|
|
tenantId,
|
|
name,
|
|
macAddress,
|
|
vpnIp: nextVpnIp,
|
|
opnsenseUrl,
|
|
apiKey,
|
|
apiSecret
|
|
},
|
|
});
|
|
|
|
// TODO: Actually trigger OpenVPN config generation via SSH or scripts to the VPN Server (10.0.1.150)
|
|
// generateVpnConfig(nextVpnIp, macAddress);
|
|
|
|
res.status(201).json(newDevice);
|
|
} catch (error) {
|
|
console.error(error);
|
|
res.status(500).json({ error: 'Internal server error' });
|
|
}
|
|
});
|
|
|
|
export default router;
|