From cc62fd3cd7ed57e2c71f82e6dfa81666a2955bba Mon Sep 17 00:00:00 2001 From: undefined Date: Sun, 9 Aug 2020 11:41:45 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E4=B8=80=E4=BA=9Banyscript?= =?UTF-8?q?=E7=89=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/geoip/lib.ts | 10 +++- packages/hydrooj/package.json | 2 +- packages/hydrooj/src/handler/domain.ts | 3 +- packages/hydrooj/src/handler/judge.ts | 23 +++++---- packages/hydrooj/src/interface.ts | 3 +- packages/hydrooj/src/model/record.ts | 10 ++-- packages/login-with-osu/lib.ts | 65 ++++++++++++++++++++++++++ 7 files changed, 97 insertions(+), 19 deletions(-) create mode 100644 packages/login-with-osu/lib.ts diff --git a/packages/geoip/lib.ts b/packages/geoip/lib.ts index 35aa68fe8..fe6e3fbd3 100644 --- a/packages/geoip/lib.ts +++ b/packages/geoip/lib.ts @@ -6,10 +6,18 @@ import { Reader } from 'maxmind'; const buffer = fs.readFileSync(path.resolve(__dirname, 'GeoLite2-City.mmdb')); const reader = new Reader(buffer); +export interface Result { + location?: string, + continent?: string, + country?: string, + city?: string, + display: string +} + function lookup(ip: string, locale: string) { const res: any = reader.get(ip); if (!res) return {}; - const ret: any = {}; + 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) { diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 1fdca7824..2cab0f59a 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.12.7", + "version": "2.12.8", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/handler/domain.ts b/packages/hydrooj/src/handler/domain.ts index ba2d08fe4..4248939bf 100644 --- a/packages/hydrooj/src/handler/domain.ts +++ b/packages/hydrooj/src/handler/domain.ts @@ -1,4 +1,5 @@ import moment from 'moment-timezone'; +import { Dictionary } from 'lodash'; import { RoleAlreadyExistError, ValidationError, DomainJoinForbiddenError, DomainJoinAlreadyMemberError, InvalidJoinInvitationCodeError, @@ -170,7 +171,7 @@ class DomainRoleHandler extends ManageHandler { @param('role', Types.String) async postAdd(domainId: string, role: string) { const roles = await domain.getRoles(this.domain); - const rdict: any = {}; + const rdict: Dictionary = {}; for (const r of roles) rdict[r._id] = r.perm; if (rdict[role]) throw new RoleAlreadyExistError(role); await domain.addRole(domainId, role, rdict.default.perm); diff --git a/packages/hydrooj/src/handler/judge.ts b/packages/hydrooj/src/handler/judge.ts index 11c6a8b8d..5e0d69d6f 100644 --- a/packages/hydrooj/src/handler/judge.ts +++ b/packages/hydrooj/src/handler/judge.ts @@ -1,5 +1,5 @@ -import { ObjectID } from 'mongodb'; -import { JudgeResultBody, Rdoc } from '../interface'; +import { ObjectID, PushOperator, MatchKeysAndValues } from 'mongodb'; +import { JudgeResultBody, Rdoc, TestCase } from '../interface'; import * as record from '../model/record'; import * as problem from '../model/problem'; import * as builtin from '../model/builtin'; @@ -36,14 +36,15 @@ async function _postJudge(rdoc: Rdoc) { export async function next(body: JudgeResultBody) { if (body.rid) body.rid = new ObjectID(body.rid); let rdoc = await record.get(body.domainId, body.rid); - const $set: any = {}; + const $set: Partial = {}; const $push: any = {}; if (body.case) { - const c: any = {}; - c.memory = body.case.memory; - c.time = body.case.time; - c.message = body.case.message; - c.status = body.case.status; + const c: TestCase = { + memory: body.case.memory, + time: body.case.time, + message: body.case.message, + status: body.case.status, + }; rdoc.testCases.push(c); $push.testCases = c; } @@ -67,9 +68,9 @@ export async function next(body: JudgeResultBody) { export async function end(body: JudgeResultBody) { if (body.rid) body.rid = new ObjectID(body.rid); let rdoc = await record.get(body.domainId, body.rid); - const $set: any = {}; + const $set: Partial = {}; const $push: any = {}; - const $unset = { progress: '' }; + const $unset: { progress: '' } = { progress: '' }; if (body.message) { rdoc.judgeTexts.push(body.message); $push.judgeTexts = body.message; @@ -80,8 +81,6 @@ export async function end(body: JudgeResultBody) { } if (body.status) $set.status = body.status; if (body.score) $set.score = body.score; - if (body.stdout) $set.stdout = body.stdout; - if (body.stderr) $set.stderr = body.stderr; if (body.time) $set.time = body.time; if (body.memory) $set.memory = body.memory; $set.judgeAt = new Date(); diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 0d0fa8ec9..424c3c8b2 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -191,10 +191,11 @@ export interface Rdoc { compilerTexts: string[], testCases: TestCase[], rejudged: boolean, - judger: string, + judger: number, judgeAt: Date, status: number, hidden: boolean, + progress?: number, config?: PretestConfig, contest?: ContestInfo, } diff --git a/packages/hydrooj/src/model/record.ts b/packages/hydrooj/src/model/record.ts index 0860dd300..345ed5318 100644 --- a/packages/hydrooj/src/model/record.ts +++ b/packages/hydrooj/src/model/record.ts @@ -1,4 +1,6 @@ -import { ObjectID, Collection } from 'mongodb'; +import { + ObjectID, Collection, UpdateQuery, PushOperator, MatchKeysAndValues, OnlyFieldsOfType, +} from 'mongodb'; import { Dictionary } from 'lodash'; import { STATUS } from './builtin'; import * as task from './task'; @@ -109,9 +111,11 @@ export function getMulti(domainId: string, query: any) { export async function update( domainId: string, _id: ObjectID, - $set: any = {}, $push: any = {}, $unset: any = {}, + $set?: MatchKeysAndValues, + $push?: PushOperator, + $unset?: OnlyFieldsOfType, ): Promise { - const $update: any = {}; + const $update: UpdateQuery = {}; if ($set && Object.keys($set).length) $update.$set = $set; if ($push && Object.keys($push).length) $update.$push = $push; if ($unset && Object.keys($unset).length) $update.$unset = $unset; diff --git a/packages/login-with-osu/lib.ts b/packages/login-with-osu/lib.ts new file mode 100644 index 000000000..ae92e32d2 --- /dev/null +++ b/packages/login-with-osu/lib.ts @@ -0,0 +1,65 @@ +import 'hydrooj'; +import * as superagent from 'superagent'; +import superagentProxy from 'superagent-proxy'; + +superagentProxy(superagent); + +async function get() { + const { system, token } = global.Hydro.model; + const [[appid, url], [state]] = await Promise.all([ + system.getMany([ + 'login-with-osu.id', + 'server.url', + ]), + token.add(token.TYPE_OAUTH, 600, { redirect: this.request.referer }), + ]); + this.response.redirect = `https://osu.ppy.sh/oauth/authorize?client_id=${appid}&state=${state}&redirect_uri=${url}oauth/osu/callback&response_type=code`; +} + +async function callback({ state, code }) { + const { system, token } = global.Hydro.model; + const { UserFacingError } = global.Hydro.error; + const [[appid, secret, proxy, url], s] = await Promise.all([ + system.getMany([ + 'login-with-osu.id', + 'login-with-osu.secret', + 'login-with-osu.proxy', + 'server.url', + ]), + token.get(state, token.TYPE_OAUTH), + ]); + const res = await superagent.post('https://osu.ppy.sh/oauth/token') + .proxy(proxy) + .send({ + client_id: appid, + client_secret: secret, + code, + grant_type: 'authorization_code', + redirect_uri: `${url}oauth/github/callback`, + }) + .set('accept', 'application/json'); + if (res.body.error) { + throw new UserFacingError( + res.body.error, res.body.error_description, res.body.error_uri, + ); + } + const t = res.body.access_token; + const userInfo = await superagent.get('https://osu.ppy.sh/api/v2/me') + .proxy(proxy) + .set('User-Agent', 'Hydro-OAuth') + .set('Authorization', `Bearer ${t}`); + const ret = { + email: `${userInfo.body.id}@osu.local`, + bio: '', + uname: [userInfo.body.username], + }; + this.response.redirect = s.redirect; + await token.del(s._id, token.TYPE_OAUTH); + return ret; +} + +global.Hydro.lib.oauth_osu = { + text: 'Login with Osu', + callback, + get, +};