import pkgPg from 'pg'; import { PGDATABASE, PGHOST, PGPASSWORD, PGPORT, PGUSER, SESSION_TIMEOUT, VLAN_ID, MAX_DOWN, MAX_UP } from '../config/env.js'; const { Pool } = pkgPg; export const pool = new Pool({ host: PGHOST, port: PGPORT, database: PGDATABASE, user: PGUSER, password: PGPASSWORD }); export async function readUsersFromDb() { const client = await pool.connect(); try { const q = ` SELECT rc.username, rc.value AS password, EXISTS ( SELECT 1 FROM radcheck r2 WHERE r2.username = rc.username AND r2.attribute = 'Auth-Type' AND r2.value = 'Reject' ) AS disabled, COALESCE(( SELECT rr.value FROM radreply rr WHERE rr.username = rc.username AND rr.attribute = 'Tunnel-Private-Group-Id' ORDER BY rr.id DESC LIMIT 1 ), $1) AS vlan FROM radcheck rc WHERE rc.attribute = 'Cleartext-Password' ORDER BY rc.username ASC`; const { rows } = await client.query(q, [String(VLAN_ID)]); return rows.map(r => ({ username: r.username, password: r.password, vlan: String(r.vlan), disabled: !!r.disabled })); } finally { client.release(); } } export async function upsertUserToDb(user) { const { username, password, vlan, disabled } = user; const client = await pool.connect(); try { await client.query('BEGIN'); await client.query("DELETE FROM radcheck WHERE username = $1 AND attribute = 'Cleartext-Password'", [username]); await client.query( "INSERT INTO radcheck (username, attribute, op, value) VALUES ($1,'Cleartext-Password',':=',$2)", [username, password] ); await client.query("DELETE FROM radcheck WHERE username = $1 AND attribute = 'Auth-Type'", [username]); if (disabled) { await client.query( "INSERT INTO radcheck (username, attribute, op, value) VALUES ($1,'Auth-Type',':=','Reject')", [username] ); } const attrs = [ ['Tunnel-Type', 'VLAN'], ['Tunnel-Medium-Type', 'IEEE-802'], ['Tunnel-Private-Group-Id', String(vlan || VLAN_ID)], ['WISPr-Bandwidth-Max-Down', String(MAX_DOWN)], ['WISPr-Bandwidth-Max-Up', String(MAX_UP)], ]; if (SESSION_TIMEOUT > 0) { attrs.push(['Session-Timeout', String(SESSION_TIMEOUT)]); } await client.query( "DELETE FROM radreply WHERE username = $1 AND attribute IN ('Tunnel-Type','Tunnel-Medium-Type','Tunnel-Private-Group-Id','WISPr-Bandwidth-Max-Down','WISPr-Bandwidth-Max-Up','Session-Timeout')", [username] ); for (const [attr, val] of attrs) { await client.query( "INSERT INTO radreply (username, attribute, op, value) VALUES ($1,$2,':=',$3)", [username, attr, String(val)] ); } await client.query('COMMIT'); } catch (e) { await client.query('ROLLBACK'); throw e; } finally { client.release(); } } export async function deleteUserFromDb(username) { const client = await pool.connect(); try { await client.query('BEGIN'); await client.query('DELETE FROM radcheck WHERE username = $1', [username]); await client.query('DELETE FROM radreply WHERE username = $1', [username]); await client.query('COMMIT'); } catch (e) { await client.query('ROLLBACK'); throw e; } finally { client.release(); } }