identificacion, asignacion y seguimiento de conexion de dispositivos por usuario listo

This commit is contained in:
2025-09-26 17:58:40 -06:00
parent bcc475045d
commit 689f80d59c
2 changed files with 94 additions and 1 deletions

View File

@@ -3,12 +3,21 @@ import { VLAN_ID } from '../config/env.js';
import { buildAcceptPayload, normalizeAttributes } from '../utils/attrs.js';
import { pushRequest } from '../sse.js';
import { activeSessions, sendRadiusSelfTest } from '../services/radius.js';
import { addDeviceToUser, connectDeviceForUser, disconnectDeviceForUser, getOrCreateDevice } from '../services/db.js';
const router = Router();
router.post('/authorize', (req, res) => {
const attrs = normalizeAttributes(req.body);
const reply = buildAcceptPayload();
// Try to record device usage
const mac = attrs['Calling-Station-Id'] || attrs['Calling-Station-Id*0'] || '';
const username = attrs['User-Name'] || attrs['User-Name*0'] || '';
if (mac && username) {
getOrCreateDevice({ mac: String(mac) }).then(async (id) => {
await addDeviceToUser(String(username), id);
}).catch(() => {});
}
pushRequest({
id: Date.now() + ':' + Math.random().toString(16).slice(2),
ts: new Date().toISOString(),
@@ -37,8 +46,22 @@ router.post('/accounting', (req, res) => {
calledStationId: attrs['Called-Station-Id'] || '',
updatedAt: Date.now(),
});
// upsert device and link as connected
const mac = attrs['Calling-Station-Id'] || '';
if (mac) {
getOrCreateDevice({ mac: String(mac) }).then(async (id) => {
await addDeviceToUser(String(username), id);
await connectDeviceForUser(String(username), id);
}).catch(() => {});
}
} else if (st === 'STOP') {
activeSessions.delete(sessionId);
const mac = attrs['Calling-Station-Id'] || '';
if (mac) {
getOrCreateDevice({ mac: String(mac) }).then(async (id) => {
await disconnectDeviceForUser(String(username), id);
}).catch(() => {});
}
}
}
} catch {}
@@ -56,6 +79,13 @@ router.post('/authorize-inner', async (_req, res) => res.status(410).json({}));
router.post('/post-auth', async (req, res) => {
try {
const attrs = normalizeAttributes(req.body);
const mac = attrs['Calling-Station-Id'] || attrs['Calling-Station-Id*0'] || '';
const username = attrs['User-Name'] || attrs['User-Name*0'] || '';
if (mac && username) {
getOrCreateDevice({ mac: String(mac) }).then(async (id) => {
await addDeviceToUser(String(username), id);
}).catch(() => {});
}
pushRequest({
id: Date.now() + ':' + Math.random().toString(16).slice(2),
ts: new Date().toISOString(),
@@ -91,4 +121,3 @@ router.post('/test/radius', async (_req, res) => {
});
export default router;

View File

@@ -68,6 +68,70 @@ export async function ensureSchema() {
}
}
export async function getOrCreateDevice({ mac, nombre = null, vendor = null, descripcion = null }) {
if (!mac) throw new Error('mac required');
const client = await pool.connect();
try {
const up = await client.query(
`INSERT INTO dispositivos (mac, nombre, vendor, descripcion)
VALUES ($1, $2, $3, $4)
ON CONFLICT (mac) DO UPDATE SET
last_seen = NOW(),
nombre = COALESCE(dispositivos.nombre, EXCLUDED.nombre),
vendor = COALESCE(dispositivos.vendor, EXCLUDED.vendor),
descripcion = COALESCE(dispositivos.descripcion, EXCLUDED.descripcion)
RETURNING id`,
[String(mac), nombre, vendor, descripcion]
);
return up.rows[0].id;
} finally {
client.release();
}
}
export async function ensureUserRow(username) {
await pool.query('INSERT INTO users (username) VALUES ($1) ON CONFLICT (username) DO NOTHING', [username]);
}
export async function addDeviceToUser(username, deviceId) {
await ensureUserRow(username);
await pool.query(
`UPDATE users SET dispositivos_utilizados = (
SELECT ARRAY(
SELECT DISTINCT x FROM (
SELECT unnest(coalesce(dispositivos_utilizados, '{}'::int[])) AS x
UNION ALL SELECT $2::int
) AS t
)
) WHERE username = $1`,
[username, deviceId]
);
}
export async function connectDeviceForUser(username, deviceId) {
await ensureUserRow(username);
await pool.query(
`UPDATE users SET dispositivos_conectados = (
SELECT ARRAY(
SELECT DISTINCT x FROM (
SELECT unnest(coalesce(dispositivos_conectados, '{}'::int[])) AS x
UNION ALL SELECT $2::int
) AS t
)
) WHERE username = $1`,
[username, deviceId]
);
}
export async function disconnectDeviceForUser(username, deviceId) {
await ensureUserRow(username);
await pool.query(
`UPDATE users SET dispositivos_conectados = array_remove(coalesce(dispositivos_conectados, '{}'::int[]), $2::int)
WHERE username = $1`,
[username, deviceId]
);
}
export async function readUsersFromDb() {
const client = await pool.connect();
try {