This commit is contained in:
2026-02-24 17:53:43 -06:00
parent da6e0311d8
commit 06e021f8a1
21 changed files with 3144 additions and 77 deletions
+54 -41
View File
@@ -1,6 +1,7 @@
import { prisma, unifi, unifiUsername, unifiPassword } from "../constants";
import GenericError from "../Errors/GenericError";
import { UnifiSite } from "../../generated/prisma/client";
import { events } from "../modules/globalEvents";
let loggedIn = false;
@@ -16,6 +17,24 @@ async function ensureLoggedIn(): Promise<void> {
loggedIn = true;
}
/**
* Wraps a UniFi API call with automatic re-authentication on failure.
* If the call fails and we were previously logged in (i.e. session likely
* expired), resets the login state, re-authenticates, and retries once.
*/
async function withReauth<T>(fn: () => Promise<T>): Promise<T> {
await ensureLoggedIn();
try {
return await fn();
} catch (e) {
if (!loggedIn) throw e;
events.emit("unifi:reauth");
loggedIn = false;
await ensureLoggedIn();
return fn();
}
}
export const unifiSites = {
/**
* Fetch a UniFi site record from the database by its internal ID.
@@ -96,12 +115,14 @@ export const unifiSites = {
* Creates new records for sites not yet tracked, updates names for existing ones.
*/
async syncSites(): Promise<UnifiSite[]> {
await ensureLoggedIn();
events.emit("unifi:sites:sync:started");
// Fetch all sites from the controller
const allSites = await unifi.getAllSites();
const allSites = await withReauth(() => unifi.getAllSites());
const results: UnifiSite[] = [];
let created = 0;
let updated = 0;
for (const site of allSites) {
const existing = await prisma.unifiSite.findFirst({
@@ -109,22 +130,30 @@ export const unifiSites = {
});
if (existing) {
const updated = await prisma.unifiSite.update({
const updatedSite = await prisma.unifiSite.update({
where: { id: existing.id },
data: { name: site.description },
});
results.push(updated);
results.push(updatedSite);
updated++;
} else {
const created = await prisma.unifiSite.create({
const createdSite = await prisma.unifiSite.create({
data: {
name: site.description,
siteId: site.name,
},
});
results.push(created);
results.push(createdSite);
created++;
}
}
events.emit("unifi:sites:sync:completed", {
total: results.length,
created,
updated,
});
return results;
},
@@ -132,24 +161,21 @@ export const unifiSites = {
* Get live site overview from the UniFi controller.
*/
async getSiteOverview(siteId: string) {
await ensureLoggedIn();
return unifi.getSiteOverview(siteId);
return withReauth(() => unifi.getSiteOverview(siteId));
},
/**
* Get live devices from the UniFi controller for a site.
*/
async getDevices(siteId: string) {
await ensureLoggedIn();
return unifi.getDevices(siteId);
return withReauth(() => unifi.getDevices(siteId));
},
/**
* Get live WiFi networks (WLANs) from the UniFi controller for a site.
*/
async getWlanConf(siteId: string) {
await ensureLoggedIn();
return unifi.getWlanConf(siteId);
return withReauth(() => unifi.getWlanConf(siteId));
},
/**
@@ -160,25 +186,21 @@ export const unifiSites = {
wlanId: string,
updates: Parameters<typeof unifi.updateWlanConf>[2],
) {
await ensureLoggedIn();
return unifi.updateWlanConf(siteId, wlanId, updates);
return withReauth(() => unifi.updateWlanConf(siteId, wlanId, updates));
},
/**
* Get live network configurations from the UniFi controller for a site.
*/
async getNetworks(siteId: string) {
await ensureLoggedIn();
return unifi.getNetworks(siteId);
return withReauth(() => unifi.getNetworks(siteId));
},
/**
* Create a new site on the UniFi controller and track it in the database.
*/
async createSite(description: string): Promise<UnifiSite> {
await ensureLoggedIn();
const created = await unifi.createSite(description);
const created = await withReauth(() => unifi.createSite(description));
return prisma.unifiSite.create({
data: {
@@ -192,8 +214,7 @@ export const unifiSites = {
* Get WLAN groups from the UniFi controller for a site.
*/
async getWlanGroups(siteId: string) {
await ensureLoggedIn();
return unifi.getWlanGroups(siteId);
return withReauth(() => unifi.getWlanGroups(siteId));
},
/**
@@ -203,16 +224,14 @@ export const unifiSites = {
siteId: string,
input: Parameters<typeof unifi.createWlanGroup>[1],
) {
await ensureLoggedIn();
return unifi.createWlanGroup(siteId, input);
return withReauth(() => unifi.createWlanGroup(siteId, input));
},
/**
* Get user groups (speed profiles) from the UniFi controller for a site.
*/
async getUserGroups(siteId: string) {
await ensureLoggedIn();
return unifi.getUserGroups(siteId);
return withReauth(() => unifi.getUserGroups(siteId));
},
/**
@@ -222,16 +241,14 @@ export const unifiSites = {
siteId: string,
input: Parameters<typeof unifi.createUserGroup>[1],
) {
await ensureLoggedIn();
return unifi.createUserGroup(siteId, input);
return withReauth(() => unifi.createUserGroup(siteId, input));
},
/**
* Get AP groups from the UniFi controller for a site.
*/
async getApGroups(siteId: string) {
await ensureLoggedIn();
return unifi.getApGroups(siteId);
return withReauth(() => unifi.getApGroups(siteId));
},
/**
@@ -243,40 +260,37 @@ export const unifiSites = {
deviceMacs: string[],
forWlanconf: boolean = false,
) {
await ensureLoggedIn();
return unifi.createApGroup(siteId, name, deviceMacs, forWlanconf);
return withReauth(() =>
unifi.createApGroup(siteId, name, deviceMacs, forWlanconf),
);
},
/**
* Update an existing AP group's device MACs on the UniFi controller.
*/
async updateApGroup(siteId: string, groupId: string, deviceMacs: string[]) {
await ensureLoggedIn();
return unifi.updateApGroup(siteId, groupId, deviceMacs);
return withReauth(() => unifi.updateApGroup(siteId, groupId, deviceMacs));
},
/**
* Get access points only from the UniFi controller for a site.
*/
async getAccessPoints(siteId: string) {
await ensureLoggedIn();
return unifi.getAccessPoints(siteId);
return withReauth(() => unifi.getAccessPoints(siteId));
},
/**
* Get WiFi SSID limits per AP per radio band.
*/
async getWifiLimits(siteId: string) {
await ensureLoggedIn();
return unifi.getWifiLimits(siteId);
return withReauth(() => unifi.getWifiLimits(siteId));
},
/**
* Get private pre-shared keys for a specific WLAN.
*/
async getPrivatePSKs(siteId: string, wlanId: string) {
await ensureLoggedIn();
return unifi.getPrivatePSKs(siteId, wlanId);
return withReauth(() => unifi.getPrivatePSKs(siteId, wlanId));
},
/**
@@ -287,7 +301,6 @@ export const unifiSites = {
wlanId: string,
psk: Parameters<typeof unifi.createPrivatePSK>[2],
) {
await ensureLoggedIn();
return unifi.createPrivatePSK(siteId, wlanId, psk);
return withReauth(() => unifi.createPrivatePSK(siteId, wlanId, psk));
},
};