geoip: use context.service

This commit is contained in:
undefined committed 2022-10-04 23:54:25 +08:00
1 parent 63c9c00d1d
commit d94e3e650a
6 files changed
+65 -64

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
import fs from 'fs';
import { Reader } from 'maxmind';
import { Context, findFileSync, Service } from 'hydrooj';
const buffer = fs.readFileSync(findFileSync('@hydrooj/geoip/GeoLite2-City.mmdb'));
const reader = new Reader(buffer);
export interface Result {
location?: string,
continent?: string,
country?: string,
city?: string,
display: string
}
export function apply() {
Context.service('geoip', class GeoIPService extends Service {
provider = '<a href="http://www.maxmind.com" target="_blank">MaxMind</a>';
lookup(ip: string, locale: string): Result {
const res: any = reader.get(ip);
if (!res) return { display: 'Unknown address'.translate(locale) };
const ret: Result = { display: '' };
if (res.location) ret.location = res.location;
if (res.continent) ret.continent = res.continent.names[locale] || res.continent.names.en;
if (res.country || res.registered_country) {
ret.country = (res.country || res.registered_country).names[locale]
|| (res.country || res.registered_country).names.en;
}
if (res.city) ret.city = res.city.names[locale] || res.city.names.en;
ret.display = `${ret.continent} ${ret.country}${ret.city ? ` ${ret.city}` : ''}`;
return ret;
}
});
}
-35
View File
@@ -1,35 +0,0 @@
import 'hydrooj';
import fs from 'fs';
import { Reader } from 'maxmind';
import { findFileSync } from '@hydrooj/utils/lib/utils';
const buffer = fs.readFileSync(findFileSync('@hydrooj/geoip/GeoLite2-City.mmdb'));
const reader = new Reader(buffer);
export interface Result {
location?: string,
continent?: string,
country?: string,
city?: string,
display: string
}
export function lookup(ip: string, locale: string): Result {
const res: any = reader.get(ip);
if (!res) return { display: 'Unknown address'.translate(locale) };
const ret: Result = { display: '' };
if (res.location) ret.location = res.location;
if (res.continent) ret.continent = res.continent.names[locale] || res.continent.names.en;
if (res.country || res.registered_country) {
ret.country = (res.country || res.registered_country).names[locale]
|| (res.country || res.registered_country).names.en;
}
if (res.city) ret.city = res.city.names[locale] || res.city.names.en;
ret.display = `${ret.continent} ${ret.country}${ret.city ? ` ${ret.city}` : ''}`;
return ret;
}
export const provider = '<a href="http://www.maxmind.com" target="_blank">MaxMind</a>';
global.Hydro.lib.geoip = { provider, lookup };
+1 -4
View File
@@ -1,7 +1,7 @@
{ {
"name": "@hydrooj/geoip", "name": "@hydrooj/geoip",
"version": "1.2.3", "version": "1.2.3",
"main": "package.json", "main": "index.ts",
"repository": "git@github.com:hydro-dev/Hydro.git", "repository": "git@github.com:hydro-dev/Hydro.git",
"author": "undefined <i@undefined.moe>", "author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
@@ -11,8 +11,5 @@
"preferUnplugged": true, "preferUnplugged": true,
"scripts": { "scripts": {
"prepublish": "./download.sh" "prepublish": "./download.sh"
},
"peerDependencies": {
"hydrooj": "*"
} }
} }
+2 -1
View File
@@ -1,6 +1,6 @@
import * as cordis from 'cordis'; import * as cordis from 'cordis';
import Schema from 'schemastery'; import Schema from 'schemastery';
import { ModuleInterfaces } from './interface'; import { GeoIP, ModuleInterfaces } from './interface';
import { inject } from './lib/ui'; import { inject } from './lib/ui';
import { Loader } from './loader'; import { Loader } from './loader';
import { EventMap } from './service/bus'; import { EventMap } from './service/bus';
@@ -33,6 +33,7 @@ export interface Context {
inject: typeof inject; inject: typeof inject;
api: ApiMixin; api: ApiMixin;
broadcast: Context['emit']; broadcast: Context['emit'];
geoip?: GeoIP;
} }
export class Context extends cordis.Context { export class Context extends cordis.Context {
+17 -12
View File
@@ -1,6 +1,7 @@
import yaml from 'js-yaml'; import yaml from 'js-yaml';
import { ObjectID } from 'mongodb'; import { ObjectID } from 'mongodb';
import { camelCase } from '@hydrooj/utils/lib/utils'; import { camelCase } from '@hydrooj/utils/lib/utils';
import { Context } from '../context';
import { import {
BlacklistedError, DomainAlreadyExistsError, InvalidTokenError, BlacklistedError, DomainAlreadyExistsError, InvalidTokenError,
NotFoundError, PermissionError, UserAlreadyExistError, NotFoundError, PermissionError, UserAlreadyExistError,
@@ -9,6 +10,7 @@ import {
import { DomainDoc, MessageDoc, Setting } from '../interface'; import { DomainDoc, MessageDoc, Setting } from '../interface';
import avatar from '../lib/avatar'; import avatar from '../lib/avatar';
import * as mail from '../lib/mail'; import * as mail from '../lib/mail';
import * as useragent from '../lib/useragent';
import { isDomainId, isEmail, isPassword } from '../lib/validator'; import { isDomainId, isEmail, isPassword } from '../lib/validator';
import BlackListModel from '../model/blacklist'; import BlackListModel from '../model/blacklist';
import { PERM, PRIV } from '../model/builtin'; import { PERM, PRIV } from '../model/builtin';
@@ -28,8 +30,6 @@ import {
} from '../service/server'; } from '../service/server';
import { md5 } from '../utils'; import { md5 } from '../utils';
const { geoip, useragent } = global.Hydro.lib;
export class HomeHandler extends Handler { export class HomeHandler extends Handler {
uids = new Set<number>(); uids = new Set<number>();
@@ -147,6 +147,7 @@ export class HomeHandler extends Handler {
} }
} }
let geoip: Context['geoip'] = null;
class HomeSecurityHandler extends Handler { class HomeSecurityHandler extends Handler {
async get() { async get() {
// TODO(iceboy): pagination? or limit session count for uid? // TODO(iceboy): pagination? or limit session count for uid?
@@ -154,17 +155,18 @@ class HomeSecurityHandler extends Handler {
for (const session of sessions) { for (const session of sessions) {
session.isCurrent = session._id === this.session._id; session.isCurrent = session._id === this.session._id;
session._id = md5(session._id); session._id = md5(session._id);
if (useragent) session.updateUa = useragent.parse(session.updateUa || session.createUa || ''); session.updateUa = useragent.parse(session.updateUa || session.createUa || '');
if (geoip) { session.updateGeoip = geoip?.lookup?.(
session.updateGeoip = geoip.lookup( session.updateIp || session.createIp,
session.updateIp || session.createIp, this.translate('geoip_locale'),
this.translate('geoip_locale'), );
);
}
} }
this.response.template = 'home_security.html'; this.response.template = 'home_security.html';
this.response.body = { sessions, geoipProvider: geoip?.provider }; this.response.body = {
if (useragent) this.response.body.icon = useragent.icon; sessions,
geoipProvider: geoip?.provider,
icon: useragent.icon,
};
} }
@param('current', Types.String) @param('current', Types.String)
@@ -432,7 +434,10 @@ class HomeMessagesConnectionHandler extends ConnectionHandler {
} }
} }
export async function apply(ctx) { export async function apply(ctx: Context) {
ctx.using(['geoip'], (g) => {
geoip = g.geoip;
});
ctx.Route('homepage', '/', HomeHandler); ctx.Route('homepage', '/', HomeHandler);
ctx.Route('home_security', '/home/security', HomeSecurityHandler, PRIV.PRIV_USER_PROFILE); ctx.Route('home_security', '/home/security', HomeSecurityHandler, PRIV.PRIV_USER_PROFILE);
ctx.Route('user_changemail_with_code', '/home/changeMail/:code', UserChangemailWithCodeHandler, PRIV.PRIV_USER_PROFILE); ctx.Route('user_changemail_with_code', '/home/changeMail/:code', UserChangemailWithCodeHandler, PRIV.PRIV_USER_PROFILE);
+11 -12
View File
@@ -671,18 +671,17 @@ export interface ProblemSearchOptions {
export type ProblemSearch = (domainId: string, q: string, options?: ProblemSearchOptions) => Promise<ProblemSearchResponse>; export type ProblemSearch = (domainId: string, q: string, options?: ProblemSearchOptions) => Promise<ProblemSearchResponse>;
export interface Lib extends Record<string, any> { export interface Lib extends Record<string, any> {
difficulty: typeof import('./lib/difficulty'), difficulty: typeof import('./lib/difficulty');
buildContent: typeof import('./lib/content').buildContent, buildContent: typeof import('./lib/content').buildContent;
i18n: typeof import('./lib/i18n'), i18n: typeof import('./lib/i18n');
mail: typeof import('./lib/mail'), mail: typeof import('./lib/mail');
paginate: typeof import('./lib/paginate'), paginate: typeof import('./lib/paginate');
rank: typeof import('./lib/rank'), rank: typeof import('./lib/rank');
rating: typeof import('./lib/rating'), rating: typeof import('./lib/rating');
testdataConfig: typeof import('./lib/testdataConfig'), testdataConfig: typeof import('./lib/testdataConfig');
useragent: typeof import('./lib/useragent'), useragent: typeof import('./lib/useragent');
validator: typeof import('./lib/validator'), validator: typeof import('./lib/validator');
template?: any, template?: any;
geoip?: GeoIP,
problemSearch: ProblemSearch; problemSearch: ProblemSearch;
} }