feat: add geolocation fields to session and implement geo stats endpoint

- Added country, city, countryCode, latitude, and longitude fields to the Session model.
- Updated geoip service to fetch and store geolocation data based on user IP.
- Created a new admin endpoint to retrieve geolocation statistics, including user counts by country and city.
- Enhanced admin page to display geolocation statistics with expandable city details.
- Introduced caching for geolocation data to optimize performance.
This commit is contained in:
Jose Selesan
2026-06-10 10:18:31 -03:00
parent 00f0cf511f
commit dc8a10a612
15 changed files with 389 additions and 30 deletions

View File

@@ -3,6 +3,8 @@ type IpGeoInfo = {
city: string;
country: string;
countryCode: string;
lat: number | null;
lon: number | null;
};
const cache = new Map<string, { data: IpGeoInfo; expiresAt: number }>();
@@ -24,7 +26,14 @@ function setCache(ip: string, info: IpGeoInfo): void {
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' };
return {
ip,
city: 'Red local',
country: 'Red local',
countryCode: 'LOCAL',
lat: null,
lon: null,
};
}
const cached = getCached(ip);
@@ -32,7 +41,7 @@ async function fetchGeoInfo(ip: string): Promise<IpGeoInfo | null> {
try {
const response = await fetch(
`http://ip-api.com/json/${ip}?fields=status,country,countryCode,city,query`
`http://ip-api.com/json/${ip}?fields=status,country,countryCode,city,lat,lon,query`
);
if (!response.ok) return null;
@@ -44,6 +53,8 @@ async function fetchGeoInfo(ip: string): Promise<IpGeoInfo | null> {
city: data.city || 'Desconocida',
country: data.country || 'Desconocido',
countryCode: data.countryCode || '',
lat: data.lat ?? null,
lon: data.lon ?? null,
};
setCache(ip, info);