mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-07 15:52:56 +03:00
Record each panel's own Xray IP observations under its panelGuid and merge each node's guid-keyed report on the master, so the panel can tell which node a client IP is connecting through (the flat inbound_client_ips union is pushed back to every node and cannot attribute). Adds the NodeClientIp model + migration, the clientIpsByGuid endpoint and node-sync merge, node-name labels in the client IP log, and cleanup on node deletion.
34 lines
1.1 KiB
TypeScript
34 lines
1.1 KiB
TypeScript
// Shape of one entry in a client's IP log, as returned by
|
|
// POST /panel/api/clients/ips/:email. `node` is the name of the node the IP is
|
|
// connecting through, or '' when it is on this local panel (or unattributed).
|
|
export type ClientIpInfo = {
|
|
ip: string;
|
|
time: string;
|
|
node: string;
|
|
};
|
|
|
|
// normalizeClientIps accepts the API payload and returns typed entries. It also
|
|
// tolerates the legacy shape (a plain array of "ip (time)" strings) so the UI
|
|
// keeps working against older panels.
|
|
export function normalizeClientIps(obj: unknown): ClientIpInfo[] {
|
|
if (!Array.isArray(obj)) return [];
|
|
const out: ClientIpInfo[] = [];
|
|
for (const x of obj) {
|
|
if (typeof x === 'string') {
|
|
if (x.length > 0) out.push({ ip: x, time: '', node: '' });
|
|
continue;
|
|
}
|
|
if (x && typeof x === 'object') {
|
|
const o = x as Record<string, unknown>;
|
|
const ip = typeof o.ip === 'string' ? o.ip : '';
|
|
if (!ip) continue;
|
|
out.push({
|
|
ip,
|
|
time: typeof o.time === 'string' ? o.time : '',
|
|
node: typeof o.node === 'string' ? o.node : '',
|
|
});
|
|
}
|
|
}
|
|
return out;
|
|
}
|