mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
fix response pipe, remove multipart
This commit is contained in:
1 parent
65a50275b1
commit
af9a8fb206
12 files changed
+67
-43
No files matched your search
+1
-1
@@ -27,7 +27,7 @@
|
||||
"eslint-import-resolver-typescript": "^2.2.1",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
"globby": "^11.0.1",
|
||||
"jest": "^26.4.0",
|
||||
"jest": "^26.4.1",
|
||||
"latest-version": "^5.1.0",
|
||||
"ora": "^5.0.0",
|
||||
"semver": "^7.3.2",
|
||||
|
||||
@@ -138,8 +138,8 @@ Content: 内容
|
||||
Contest scoreboard is not visible.: 当前比赛成绩表隐藏,暂不可显示。
|
||||
Contest Scoreboard: 比赛成绩表
|
||||
contest_create: 创建比赛
|
||||
contest_detail: 比赛详情
|
||||
contest_detail_problem_submit: 递交比赛题目
|
||||
contest_detail: 比赛详情
|
||||
contest_edit: 编辑比赛
|
||||
contest_main: 比赛
|
||||
contest_scoreboard: 比赛成绩表
|
||||
@@ -238,6 +238,7 @@ Domain ID: 域 ID
|
||||
domain_dashboard: 管理域
|
||||
domain_discussion: 讨论节点
|
||||
domain_edit: 编辑域资料
|
||||
domain_file: 我的文件
|
||||
domain_join_applications: 加域申请
|
||||
domain_join: 加入域
|
||||
domain_main: 首页
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hydrooj",
|
||||
"version": "2.12.19",
|
||||
"version": "2.12.20",
|
||||
"bin": "bin/hydrooj.js",
|
||||
"main": "dist/loader.js",
|
||||
"typings": "dist/loader.d.ts",
|
||||
@@ -25,7 +25,7 @@
|
||||
"lodash": "^4.17.20",
|
||||
"lru-cache": "^6.0.0",
|
||||
"moment-timezone": "^0.5.31",
|
||||
"mongodb": "^3.5.9",
|
||||
"mongodb": "^3.6.0",
|
||||
"nodemailer": "^6.4.10",
|
||||
"ps-list": "^7.2.0",
|
||||
"serialize-javascript": "^4.0.0",
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
} from '../error';
|
||||
import * as user from '../model/user';
|
||||
import * as domain from '../model/domain';
|
||||
import * as system from '../model/system';
|
||||
import { DOMAIN_SETTINGS, DOMAIN_SETTINGS_BY_KEY } from '../model/setting';
|
||||
import { PERM, PERMS_BY_FAMILY, PRIV } from '../model/builtin';
|
||||
import { gravatar } from '../lib/misc';
|
||||
@@ -199,6 +200,7 @@ class DomainJoinApplicationsHandler extends ManageHandler {
|
||||
if (!this.response.body.joinSettings) {
|
||||
delete this.response.body.expirations[domain.JOIN_EXPIRATION_KEEP_CURRENT];
|
||||
}
|
||||
this.response.body.url_prefix = await system.get('server.url');
|
||||
this.response.body.path = [
|
||||
['Hydro', 'homepage'],
|
||||
['domain', null],
|
||||
@@ -207,7 +209,7 @@ class DomainJoinApplicationsHandler extends ManageHandler {
|
||||
this.response.template = 'domain_join_applications.html';
|
||||
}
|
||||
|
||||
@param('method', Types.Range(domain.JOIN_METHOD_RANGE))
|
||||
@param('method', Types.Range([domain.JOIN_METHOD_NONE, domain.JOIN_METHOD_ALL, domain.JOIN_METHOD_CODE]))
|
||||
@param('role', Types.String, true)
|
||||
@param('expire', Types.UnsignedInt, true)
|
||||
@param('invitationCode', Types.String, true)
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as file from '../model/file';
|
||||
import * as user from '../model/user';
|
||||
import * as db from '../service/db';
|
||||
import {
|
||||
Route, Handler, Types, param, multipart,
|
||||
Route, Handler, Types, param,
|
||||
} from '../service/server';
|
||||
import { BadRequestError } from '../error';
|
||||
|
||||
@@ -19,8 +19,8 @@ class FileDownloadHandler extends Handler {
|
||||
@param('name', Types.String, true)
|
||||
async get(domainId: string, fileId: ObjectID, secret: string, name: string) {
|
||||
if (name) name = Buffer.from(name, 'base64').toString();
|
||||
this.response.attachment(name || fileId.toHexString());
|
||||
this.response.body = await file.getWithSecret(fileId, secret);
|
||||
const doc = await file.getWithSecret(fileId, secret);
|
||||
this.response.attachment(name || fileId.toHexString(), doc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ class FileUploadHandler extends Handler {
|
||||
this.response.body = { fdoc: null, usage: this.user.usage, quota: await this.getQuota() };
|
||||
}
|
||||
|
||||
@multipart(256 * 1024)
|
||||
@param('title', Types.String)
|
||||
async post(domainId: string, title: string) {
|
||||
if (!this.request.files.file) throw new BadRequestError();
|
||||
|
||||
@@ -22,7 +22,7 @@ import * as solution from '../model/solution';
|
||||
import { PERM, PRIV, CONSTANT } from '../model/builtin';
|
||||
import * as bus from '../service/bus';
|
||||
import {
|
||||
Route, Connection, Handler, ConnectionHandler, Types, param, multipart,
|
||||
Route, Connection, Handler, ConnectionHandler, Types, param,
|
||||
} from '../service/server';
|
||||
|
||||
const parseCategory = (value: string) => flatten(value.split('+').map((e) => e.split(','))).map((e) => e.trim());
|
||||
@@ -422,7 +422,6 @@ class ProblemDataUploadHandler extends ProblemManageHandler {
|
||||
this.response.template = 'problem_upload.html';
|
||||
}
|
||||
|
||||
@multipart(256 * 1024)
|
||||
async post({ domainId }) {
|
||||
if (!this.request.files.file) throw new ValidationError('file');
|
||||
this.pdoc = await problem.setTestdata(
|
||||
|
||||
@@ -237,6 +237,7 @@ export interface DomainDoc extends Dictionary<any> {
|
||||
gravatar: string,
|
||||
bulletin: string,
|
||||
pidCounter: number,
|
||||
join?: any,
|
||||
}
|
||||
|
||||
// Message
|
||||
|
||||
@@ -74,7 +74,7 @@ export async function getList(domainIds: string[]): Promise<Dictionary<DomainDoc
|
||||
}
|
||||
|
||||
export function setUserRole(domainId: string, uid: number, role: string) {
|
||||
return collUser.updateOne({ uid, domainId }, { role }, { upsert: true });
|
||||
return collUser.updateOne({ uid, domainId }, { $set: { role } }, { upsert: true });
|
||||
}
|
||||
|
||||
export async function getRoles(domainId: string): Promise<any[]>
|
||||
|
||||
@@ -60,7 +60,7 @@ export async function getWithSecret(_id: ObjectID, secret: string, reject?: Func
|
||||
const stream = gridfs.openDownloadStream(_id);
|
||||
stream.on('error', (err) => {
|
||||
console.error(err);
|
||||
if (reject) reject();
|
||||
if (reject) reject(err);
|
||||
});
|
||||
return stream;
|
||||
}
|
||||
@@ -71,7 +71,7 @@ export async function get(_id: ObjectID, reject?: Function) {
|
||||
const stream = gridfs.openDownloadStream(_id);
|
||||
stream.on('error', (err) => {
|
||||
console.error(err);
|
||||
if (reject) reject();
|
||||
if (reject) reject(err);
|
||||
});
|
||||
return stream;
|
||||
}
|
||||
|
||||
@@ -10,17 +10,24 @@ mongourl += `${opts.host}:${opts.port}/${opts.name}`;
|
||||
|
||||
// eslint-disable-next-line import/no-mutable-exports
|
||||
export let db: mongodb.Db = null;
|
||||
// eslint-disable-next-line import/no-mutable-exports
|
||||
export let db2: mongodb.Db = null;
|
||||
|
||||
mongodb.MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopology: true })
|
||||
.then((Client) => {
|
||||
db = Client.db(opts.name);
|
||||
global.Hydro.service.db.db = db;
|
||||
mongodb.MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopology: true })
|
||||
.then((Client1) => {
|
||||
db2 = Client1.db(opts.name);
|
||||
global.Hydro.service.db.db2 = db2;
|
||||
bus.publish('system_database_connected', null);
|
||||
});
|
||||
});
|
||||
|
||||
export function collection(c: string) {
|
||||
if (opts.prefix) return db.collection(`${opts.prefix}.${c}`);
|
||||
return db.collection(c);
|
||||
}
|
||||
|
||||
global.Hydro.service.db = { collection, db };
|
||||
global.Hydro.service.db = { collection, db, db2 };
|
||||
@@ -1,8 +1,8 @@
|
||||
import { GridFSBucket } from 'mongodb';
|
||||
import { db } from './db';
|
||||
import { db2 } from './db';
|
||||
|
||||
export const fs = new GridFSBucket(db);
|
||||
const fs = new GridFSBucket(db2);
|
||||
|
||||
global.Hydro.service.gridfs = fs;
|
||||
|
||||
export default fs;
|
||||
export = fs;
|
||||
@@ -1,5 +1,6 @@
|
||||
/* eslint-disable prefer-destructuring */
|
||||
import assert from 'assert';
|
||||
import { PassThrough } from 'stream';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import http from 'http';
|
||||
@@ -99,7 +100,16 @@ export const Types: Types = {
|
||||
},
|
||||
],
|
||||
Range: (range) => [
|
||||
null,
|
||||
(v) => {
|
||||
if (range instanceof Array) {
|
||||
for (const item of range) {
|
||||
if (typeof item === 'number') {
|
||||
if (item === parseInt(v, 10)) return parseInt(v, 10);
|
||||
} else if (item === v) return v;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
},
|
||||
(v) => {
|
||||
if (range instanceof Array) {
|
||||
for (const item of range) {
|
||||
@@ -181,22 +191,6 @@ export function param(name: string, ...args: any): MethodDecorator {
|
||||
};
|
||||
}
|
||||
|
||||
export function multipart(maxSizeKiB: number): MethodDecorator {
|
||||
return function multipartDecorator(target: any, funcName: string, obj: any) {
|
||||
const originalMethod = obj.value;
|
||||
obj.value = async function checkCsrfToken(...args: any[]) {
|
||||
const body = Body({
|
||||
multipart: true,
|
||||
formidable: {
|
||||
maxFileSize: maxSizeKiB * 1024,
|
||||
},
|
||||
});
|
||||
return await body.call(this.ctx, this.ctx, () => originalMethod.call(this, ...args));
|
||||
};
|
||||
return obj;
|
||||
};
|
||||
}
|
||||
|
||||
export function requireCsrfToken(target: any, funcName: string, obj: any) {
|
||||
const originalMethod = obj.value;
|
||||
obj.value = async function checkCsrfToken(...args: any[]) {
|
||||
@@ -219,7 +213,12 @@ export async function prepare() {
|
||||
maxAge: 365 * 24 * 60 * 60,
|
||||
}));
|
||||
}
|
||||
app.use(Body());
|
||||
app.use(Body({
|
||||
multipart: true,
|
||||
formidable: {
|
||||
maxFileSize: 256 * 1024 * 1024,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
export class Handler {
|
||||
@@ -251,7 +250,7 @@ export class Handler {
|
||||
template?: string,
|
||||
redirect?: string,
|
||||
disposition?: string,
|
||||
attachment: (name: string) => void,
|
||||
attachment: (name: string, stream?: any) => void,
|
||||
};
|
||||
|
||||
session: any;
|
||||
@@ -288,7 +287,13 @@ export class Handler {
|
||||
status: null,
|
||||
template: null,
|
||||
redirect: null,
|
||||
attachment: (name) => ctx.attachment(name),
|
||||
attachment: (name, stream) => {
|
||||
ctx.attachment(name);
|
||||
if (stream) {
|
||||
this.response.body = null;
|
||||
ctx.body = stream.pipe(new PassThrough());
|
||||
}
|
||||
},
|
||||
disposition: null,
|
||||
};
|
||||
this.UIContext = {
|
||||
@@ -344,9 +349,13 @@ export class Handler {
|
||||
if (!this.user.hasPriv(...args)) throw new PrivilegeError(...args);
|
||||
}
|
||||
|
||||
url(name: string, kwargs = {}) {
|
||||
url(name: string, kwargs: any = {}) {
|
||||
let res = '#';
|
||||
const args: any = { ...kwargs };
|
||||
const args: any = {};
|
||||
for (const key in kwargs) {
|
||||
if (kwargs[key] instanceof ObjectID) args[key] = kwargs[key].toHexString();
|
||||
else args[key] = kwargs[key].toString();
|
||||
}
|
||||
try {
|
||||
if (this.args.domainId !== 'system' || args.domainId) {
|
||||
name += '_with_domainId';
|
||||
@@ -422,6 +431,7 @@ export class Handler {
|
||||
}
|
||||
|
||||
async finish() {
|
||||
if (!this.response.body) return;
|
||||
try {
|
||||
await this.renderBody();
|
||||
} catch (error) {
|
||||
@@ -468,6 +478,8 @@ export class Handler {
|
||||
|
||||
async putResponse() {
|
||||
if (this.response.disposition) this.ctx.set('Content-Disposition', this.response.disposition);
|
||||
console.log(this.response);
|
||||
if (!this.response.body) return;
|
||||
if (this.response.redirect && !this.request.json) {
|
||||
this.ctx.response.type = 'application/octet-stream';
|
||||
this.ctx.response.status = 302;
|
||||
@@ -677,9 +689,13 @@ export class ConnectionHandler {
|
||||
if (!this.user.hasPriv(...args)) throw new PrivilegeError(...args);
|
||||
}
|
||||
|
||||
url(name: string, kwargs = {}) {
|
||||
url(name: string, kwargs: any = {}) {
|
||||
let res = '#';
|
||||
const args: any = { ...kwargs };
|
||||
const args: any = {};
|
||||
for (const key in kwargs) {
|
||||
if (kwargs[key] instanceof ObjectID) args[key] = kwargs[key].toHexString();
|
||||
else args[key] = kwargs[key].toString();
|
||||
}
|
||||
try {
|
||||
if (this.args.domainId !== 'system' || args.domainId) {
|
||||
name += '_with_domainId';
|
||||
@@ -803,7 +819,6 @@ global.Hydro.service.server = {
|
||||
server,
|
||||
router,
|
||||
param,
|
||||
multipart,
|
||||
requireCsrfToken,
|
||||
Handler,
|
||||
ConnectionHandler,
|
||||
|
||||
Reference in new issue
Block a user