feat(admin): add geolocation information to user sessions and implement geo IP fetching
This commit is contained in:
57
apps/backend/src/lib/geoip.ts
Normal file
57
apps/backend/src/lib/geoip.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
type IpGeoInfo = {
|
||||
ip: string;
|
||||
city: string;
|
||||
country: string;
|
||||
countryCode: string;
|
||||
};
|
||||
|
||||
const cache = new Map<string, { data: IpGeoInfo; expiresAt: number }>();
|
||||
const CACHE_TTL_MS = 60 * 60 * 1000;
|
||||
|
||||
function getCached(ip: string): IpGeoInfo | undefined {
|
||||
const entry = cache.get(ip);
|
||||
if (!entry) return undefined;
|
||||
if (Date.now() > entry.expiresAt) {
|
||||
cache.delete(ip);
|
||||
return undefined;
|
||||
}
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
function setCache(ip: string, info: IpGeoInfo): void {
|
||||
cache.set(ip, { data: info, expiresAt: Date.now() + CACHE_TTL_MS });
|
||||
}
|
||||
|
||||
async function fetchGeoInfo(ip: string): Promise<IpGeoInfo | null> {
|
||||
if (ip === '127.0.0.1' || ip === '::1' || ip.startsWith('192.168.') || ip.startsWith('10.')) {
|
||||
return { ip, city: 'Red local', country: 'Red local', countryCode: 'LOCAL' };
|
||||
}
|
||||
|
||||
const cached = getCached(ip);
|
||||
if (cached) return cached;
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`http://ip-api.com/json/${ip}?fields=status,country,countryCode,city,query`
|
||||
);
|
||||
if (!response.ok) return null;
|
||||
|
||||
const data = await response.json();
|
||||
if (data.status !== 'success') return null;
|
||||
|
||||
const info: IpGeoInfo = {
|
||||
ip: data.query,
|
||||
city: data.city || 'Desconocida',
|
||||
country: data.country || 'Desconocido',
|
||||
countryCode: data.countryCode || '',
|
||||
};
|
||||
|
||||
setCache(ip, info);
|
||||
return info;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export type { IpGeoInfo };
|
||||
export { fetchGeoInfo };
|
||||
Reference in New Issue
Block a user