130 lines
2.5 KiB
JavaScript
130 lines
2.5 KiB
JavaScript
import path from 'node:path';
|
|
import { Reader } from '@maxmind/geoip2-node';
|
|
import config from 'config';
|
|
|
|
import runtimeId from '../../utils/runtime-id.js';
|
|
import initLogger from '../logger.js';
|
|
|
|
const logger = initLogger();
|
|
const regions = config.restrictions.regions;
|
|
|
|
export default async function initRestrictionHandler() {
|
|
const reader = await Reader.open('assets/GeoLite2-City.mmdb');
|
|
|
|
function getRestriction(req) {
|
|
if (req.session.geo
|
|
&& Object.hasOwn(req.session.geo, 'country')
|
|
&& req.session.geo.ip === req.userIp
|
|
&& req.session.geo.runtimeId === runtimeId) {
|
|
const { country, subdivision } = req.session.geo;
|
|
|
|
if (!config.restrictions.enabled) {
|
|
return {
|
|
restriction: 0,
|
|
country,
|
|
subdivision,
|
|
};
|
|
}
|
|
|
|
if (Object.hasOwn(req.session.geo, 'restriction')) {
|
|
return {
|
|
restriction: req.session.geo.restriction,
|
|
country,
|
|
subdivision,
|
|
};
|
|
}
|
|
}
|
|
|
|
const location = reader.city(req.userIp);
|
|
const country = location.country.isoCode;
|
|
const subdivision = location.subdivisions?.[0]?.isoCode;
|
|
|
|
if (!config.restrictions.enabled) {
|
|
return {
|
|
restriction: 0,
|
|
country,
|
|
subdivision,
|
|
};
|
|
}
|
|
|
|
if (regions[country]?.[subdivision]) {
|
|
// state or province restriction
|
|
return {
|
|
restriction: config.restrictions.modes[regions[country][subdivision]],
|
|
country,
|
|
subdivision,
|
|
};
|
|
}
|
|
|
|
if (regions[country]) {
|
|
// country restriction
|
|
return {
|
|
restriction: config.restrictions.modes[regions[country]],
|
|
country,
|
|
subdivision,
|
|
};
|
|
}
|
|
|
|
return {
|
|
restriction: null,
|
|
country,
|
|
subdivision,
|
|
};
|
|
}
|
|
|
|
function restrictionHandler(req, res, next) {
|
|
try {
|
|
const {
|
|
restriction,
|
|
country,
|
|
subdivision,
|
|
} = getRestriction(req);
|
|
|
|
if (restriction === 'block' || req.path === '/sfw/') {
|
|
res.render(path.join(import.meta.dirname, '../../assets/sfw.ejs'), {
|
|
noVpn: config.restrictions.noVpn.includes(country),
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
if (req.session.geo?.restriction !== restriction) {
|
|
req.session.geo = {
|
|
ip: req.userIp,
|
|
runtimeId,
|
|
restriction,
|
|
country,
|
|
subdivision,
|
|
};
|
|
}
|
|
|
|
req.geo = {
|
|
restriction,
|
|
country,
|
|
subdivision,
|
|
};
|
|
}
|
|
catch (error) {
|
|
logger.error(`Failed Maxmind IP lookup for ${req.ip}: ${error.message}`);
|
|
|
|
req.session.geo = {
|
|
ip: req.userIp,
|
|
runtimeId,
|
|
restriction: 0,
|
|
country: null,
|
|
subdivision: null,
|
|
};
|
|
|
|
req.geo = {
|
|
restriction: 0,
|
|
country: null,
|
|
subdivision: null,
|
|
};
|
|
}
|
|
|
|
next();
|
|
}
|
|
|
|
return restrictionHandler;
|
|
}
|