From b9076cd5d38ba510b4f24af6acdb0f72b9fbf016 Mon Sep 17 00:00:00 2001 From: undefined Date: Fri, 31 Jul 2020 17:47:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=8D=A2socket=E9=89=B4=E6=9D=83?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hydro/handler/discussion.ts | 5 +-- hydro/handler/misc.ts | 7 ----- hydro/model/discussion.ts | 38 +++++++++++----------- hydro/model/token.ts | 2 -- hydro/service/server.ts | 63 ++++++++++++++++++++++--------------- package.json | 3 +- yarn.lock | 2 +- 7 files changed, 61 insertions(+), 59 deletions(-) diff --git a/hydro/handler/discussion.ts b/hydro/handler/discussion.ts index 05405b7d..b0806e99 100644 --- a/hydro/handler/discussion.ts +++ b/hydro/handler/discussion.ts @@ -62,10 +62,7 @@ class DiscussionHandler extends Handler { // TODO(twd2): exclude problem/contest discussions? // TODO(iceboy): continuation based pagination. if (ObjectID.isValid(name)) name = new ObjectID(name); - this.vnode = await discussion.getVnode(domainId, { - parentType: typeMapper[type], - parentId: name, - }, this); + this.vnode = await discussion.getVnode(domainId, typeMapper[type], name, this); if (this.ddoc) { this.ddoc.parentType = this.ddoc.parentType || this.vnode.type; this.ddoc.parentId = this.ddoc.parentId || this.vnode.id; diff --git a/hydro/handler/misc.ts b/hydro/handler/misc.ts index 0f97be20..217ab975 100644 --- a/hydro/handler/misc.ts +++ b/hydro/handler/misc.ts @@ -102,12 +102,6 @@ class SwitchLanguageHandler extends Handler { } } -class SockToken extends Handler { - async get() { - this.response.body = { token: this.UIContext.token }; - } -} - class UiSettingsHandler extends Handler { async get() { const [ @@ -143,7 +137,6 @@ export async function apply() { Route('status', '/status', StatusHandler); Route('status_update', '/status/update', StatusUpdateHandler); Route('switch_language', '/language/:lang', SwitchLanguageHandler); - Route('token', '/token', SockToken); Route('ui', '/extra.css', UiSettingsHandler); } diff --git a/hydro/model/discussion.ts b/hydro/model/discussion.ts index 91dab2b6..7bedfda7 100644 --- a/hydro/model/discussion.ts +++ b/hydro/model/discussion.ts @@ -158,33 +158,33 @@ export function getNode(domainId: string, _id: string) { return document.get(domainId, document.TYPE_DISCUSSION_NODE, _id); } -export async function getVnode(domainId: string, ddoc: any, handler: any) { - if (ddoc.parentType === document.TYPE_PROBLEM) { - const pdoc = await problem.get(domainId, ddoc.parentId); +export async function getVnode(domainId: string, type: number, id: string, handler: any) { + if (type === document.TYPE_PROBLEM) { + const pdoc = await problem.get(domainId, id); if (!pdoc) return null; if (pdoc.hidden && handler) handler.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN); - return { ...pdoc, type: ddoc.parentType, id: ddoc.parentId }; + return { ...pdoc, type, id }; } - if (ddoc.parentType === document.TYPE_CONTEST) { - const tdoc = await contest.get(domainId, ddoc.parentId); - return { ...tdoc, type: ddoc.parentType, id: ddoc.parentId }; + if (type === document.TYPE_CONTEST) { + const tdoc = await contest.get(domainId, new ObjectID(id)); + return { ...tdoc, type, id }; } - if (ddoc.parentType === document.TYPE_DISCUSSION_NODE) { - const ndoc = await getNode(domainId, ddoc.parentId); + if (type === document.TYPE_DISCUSSION_NODE) { + const ndoc = await getNode(domainId, id); return { ...ndoc, - title: ddoc.parentId, - type: ddoc.parentType, - id: ddoc.parentId, + title: id, + type, + id, }; } - if (ddoc.parentType === document.TYPE_TRAINING) { - const tdoc = await training.get(domainId, ddoc.parentId); - return { ...tdoc, type: ddoc.parentType, id: ddoc.parentId }; + if (type === document.TYPE_TRAINING) { + const tdoc = await training.get(domainId, id); + return { ...tdoc, type, id }; } - if (ddoc.parentType === document.TYPE_HOMEWORK) { - const tdoc = await contest.get(domainId, ddoc.parentId, document.TYPE_HOMEWORK); - return { ...tdoc, type: ddoc.parentType, id: ddoc.parentId }; + if (type === document.TYPE_HOMEWORK) { + const tdoc = await contest.get(domainId, new ObjectID(id), document.TYPE_HOMEWORK); + return { ...tdoc, type, id }; } return { title: 'Missing Node', @@ -201,7 +201,7 @@ export async function getListVnodes(domainId: string, ddocs: any, handler: any) const tasks = []; const res = {}; async function task(ddoc) { - const vnode = await getVnode(domainId, ddoc, handler); + const vnode = await getVnode(domainId, ddoc.parentType, ddoc.parentId, handler); if (!res[ddoc.parentType]) res[ddoc.parentType] = {}; res[ddoc.parentType][ddoc.parentId] = vnode; } diff --git a/hydro/model/token.ts b/hydro/model/token.ts index 93238bf1..670b0d0d 100644 --- a/hydro/model/token.ts +++ b/hydro/model/token.ts @@ -4,7 +4,6 @@ import * as db from '../service/db'; const coll = db.collection('token'); export const TYPE_SESSION = 0; -export const TYPE_TOKEN = 1; export const TYPE_REGISTRATION = 2; export const TYPE_CHANGEMAIL = 3; export const TYPE_OAUTH = 4; @@ -90,7 +89,6 @@ global.Hydro.postInit.push(ensureIndexes); global.Hydro.model.token = { TYPE_SESSION, TYPE_CHANGEMAIL, - TYPE_TOKEN, TYPE_OAUTH, TYPE_REGISTRATION, TYPE_LOSTPASS, diff --git a/hydro/service/server.ts b/hydro/service/server.ts index c84d2dfe..a975e22d 100644 --- a/hydro/service/server.ts +++ b/hydro/service/server.ts @@ -12,6 +12,7 @@ import Body from 'koa-body'; import Router from 'koa-router'; import cache from 'koa-static-cache'; import sockjs from 'sockjs'; +import { SetOption } from 'cookies'; import serialize, { SerializeJSOptions } from 'serialize-javascript'; import { argv } from 'yargs'; import { lrucache } from '../utils'; @@ -365,28 +366,14 @@ export class Handler { ]); if (!this.domain) { this.args.domainId = 'system'; - [this.user, this.UIContext.token] = await Promise.all([ - user.getById('system', this.session.uid), - token.createOrUpdate( - token.TYPE_TOKEN, 600, { uid: this.session.uid, domainId }, - ), - ]); + this.user = await user.getById('system', this.session.uid); + if (!this.user) this.user = await user.getById('system', 0); throw new NotFoundError(domainId); } - [this.user, this.UIContext.token] = await Promise.all([ - user.getById(domainId, this.session.uid), - token.createOrUpdate( - token.TYPE_TOKEN, 600, { uid: this.session.uid, domainId }, - ), - ]); + this.user = await user.getById(domainId, this.session.uid); if (!this.user) { this.session.uid = 0; - [this.user, this.UIContext.token] = await Promise.all([ - user.getById(domainId, this.session.uid), - token.createOrUpdate( - token.TYPE_TOKEN, 600, { uid: this.session.uid, domainId }, - ), - ]); + this.user = await user.getById(domainId, this.session.uid); } this.csrfToken = this.getCsrfToken(this.session._id || String.random(32)); this.UIContext.csrfToken = this.csrfToken; @@ -484,7 +471,10 @@ export class Handler { }, ); } - const cookie: any = { secure: await system.get('session.secure') }; + const cookie: SetOption = { + secure: await system.get('session.secure'), + httpOnly: false, + }; if (this.session.save) { cookie.expires = this.session.expireAt; cookie.maxAge = expireSeconds; @@ -492,7 +482,7 @@ export class Handler { this.ctx.cookies.set('sid', this.session._id, cookie); } - async onerror(error) { + async onerror(error: HydroError) { if (!error.msg) error.msg = () => error.message; console.error(error.msg(), error.params); console.error(error.stack); @@ -600,6 +590,8 @@ export class ConnectionHandler { user: any + domain: DomainDoc + constructor(conn: sockjs.Connection) { this.conn = conn; this.request = { @@ -683,10 +675,24 @@ export class ConnectionHandler { this.close(1001, err.toString()); } - async init({ domainId }) { - this.session = await token.get(this.request.params.token, token.TYPE_TOKEN); - this.session = this.session || { uid: 0, domainId: 'system' }; - this.args.domainId = this.session.domainId; + async getSession(cookieHeader: string) { + const cookies: any = {}; + const ref = cookieHeader.split(';'); + for (let j = 0; j < ref.length; j++) { + const cookie = ref[j]; + const parts = cookie.split('='); + cookies[parts[0].trim()] = (parts[1] || '').trim(); + } + this.session = await token.get(cookies.sid || '', token.TYPE_SESSION); + if (!this.session) this.session = { uid: 0, domainId: 'system' }; + } + + @param('cookie', Types.String) + async init(domainId: string, cookie: string) { + [this.domain] = await Promise.all([ + domain.get(domainId), + this.getSession(cookie), + ]); const bdoc = await blacklist.get(this.request.ip); if (bdoc) throw new BlacklistedError(this.request.ip); this.user = await user.getById(domainId, this.session.uid); @@ -699,14 +705,21 @@ export function Connection( RouteConnHandler: any, ...permPrivChecker: Array ) { - const sock = sockjs.createServer({ prefix }); + const sock = sockjs.createServer({ prefix, log: (a, b) => console.log(a, b) }); const checker = Checker(permPrivChecker); sock.on('connection', async (conn) => { const h: Dictionary = new RouteConnHandler(conn); try { const args = { domainId: 'system', ...h.request.params }; h.args = args; + const cookie = await new Promise((resolve) => { + conn.once('data', (c) => { + resolve(c); + }); + }); + args.cookie = cookie; await h.init(args); + conn.write(JSON.stringify({ event: 'auth' })); checker.call(h); if (h._prepare) await h._prepare(args); diff --git a/package.json b/package.json index 0c9d986a..8707358e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.11.2", + "version": "2.11.3", "main": "dist/loader.js", "bin": "bin/hydrooj.js", "repository": "https://github.com/hydro-dev/Hydro.git", @@ -12,6 +12,7 @@ "dependencies": { "adm-zip": "^0.4.16", "ansi_up": "^4.0.4", + "cookies": "^0.8.0", "detect-browser": "^5.1.1", "fs-extra": "^9.0.1", "html-to-text": "^5.1.1", diff --git a/yarn.lock b/yarn.lock index 46049437..a6ba3465 100644 --- a/yarn.lock +++ b/yarn.lock @@ -759,7 +759,7 @@ cookiejar@^2.1.2: resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== -cookies@~0.8.0: +cookies@^0.8.0, cookies@~0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==