mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: problem.del, ignore upgrade on fresh install
This commit is contained in:
1 parent
1543a374e3
commit
1d3bdacde9
12 files changed
+66
-119
No files matched your search
@@ -1,3 +1,4 @@
|
|||||||
|
__id: en
|
||||||
__langname: English
|
__langname: English
|
||||||
Can be Extended For: Extension
|
Can be Extended For: Extension
|
||||||
contest_create: Contest Create
|
contest_create: Contest Create
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
__id: ko
|
||||||
__langname: 한국어
|
__langname: 한국어
|
||||||
'"{data}" copied to clipboard!': “{data}”복사 완료
|
'"{data}" copied to clipboard!': “{data}”복사 완료
|
||||||
'{} is a moderator of this domain.': '{}가 그룹의 관리자입니다.'
|
'{} is a moderator of this domain.': '{}가 그룹의 관리자입니다.'
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
__id: zh
|
||||||
__langname: 简体中文
|
__langname: 简体中文
|
||||||
'"{data}" copied to clipboard!': “{data}”已复制到剪贴板!
|
'"{data}" copied to clipboard!': “{data}”已复制到剪贴板!
|
||||||
'{} is a moderator of this domain.': '{}是这个域的管理者之一。'
|
'{} is a moderator of this domain.': '{}是这个域的管理者之一。'
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
__id: zh_TW
|
||||||
__langname: 正體中文
|
__langname: 正體中文
|
||||||
'{0} comments': '{0} 條評論'
|
'{0} comments': '{0} 條評論'
|
||||||
'{0} discussions': '{0} 條討論'
|
'{0} discussions': '{0} 條討論'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.15.17",
|
"version": "2.15.18",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "dist/loader.js",
|
"main": "dist/loader.js",
|
||||||
"typings": "dist/loader.d.ts",
|
"typings": "dist/loader.d.ts",
|
||||||
|
|||||||
@@ -69,9 +69,14 @@ export async function load(call: Entry) {
|
|||||||
for (const i of builtinModel) require(`../model/${i}`);
|
for (const i of builtinModel) require(`../model/${i}`);
|
||||||
const scripts = require('../upgrade');
|
const scripts = require('../upgrade');
|
||||||
let dbVer = (await modelSystem.get('db.ver')) ?? 0;
|
let dbVer = (await modelSystem.get('db.ver')) ?? 0;
|
||||||
|
const isFresh = !dbVer;
|
||||||
const expected = scripts.length;
|
const expected = scripts.length;
|
||||||
while (dbVer < expected) {
|
while (dbVer < expected) {
|
||||||
logger.info('Upgrading database: from %d to %d', dbVer, expected);
|
logger.info('Upgrading database: from %d to %d', dbVer, expected);
|
||||||
|
if (isFresh) {
|
||||||
|
const func = scripts[dbVer].toString();
|
||||||
|
if (func.includes('_FRESH_INSTALL_IGNORE')) continue;
|
||||||
|
}
|
||||||
const result = await scripts[dbVer]();
|
const result = await scripts[dbVer]();
|
||||||
if (!result) break;
|
if (!result) break;
|
||||||
dbVer++;
|
dbVer++;
|
||||||
|
|||||||
@@ -329,6 +329,7 @@ export interface DomainDoc extends Dictionary<any> {
|
|||||||
bulletin: string,
|
bulletin: string,
|
||||||
pidCounter: number,
|
pidCounter: number,
|
||||||
join?: any,
|
join?: any,
|
||||||
|
hostname?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message
|
// Message
|
||||||
|
|||||||
@@ -46,12 +46,8 @@ String.prototype.translate = function translate(...languages: string[]) {
|
|||||||
languages.push(global.Hydro.model.system.get('server.language'));
|
languages.push(global.Hydro.model.system.get('server.language'));
|
||||||
for (const language of languages) {
|
for (const language of languages) {
|
||||||
if (!language) continue;
|
if (!language) continue;
|
||||||
if (locales[language]) {
|
const curr = (locales[language] || {})[this] || (locales[language.split('_')[0]] || {})[this];
|
||||||
if (locales[language][this] !== undefined) return locales[language][this];
|
if (curr) return curr;
|
||||||
}
|
|
||||||
if (locales[language.split('_')[0]]) {
|
|
||||||
if (locales[language.split('_')[0]][this] !== undefined) return locales[language.split('_')[0]][this];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -137,6 +137,14 @@ export function count(domainId: string, query: FilterQuery<Pdoc>) {
|
|||||||
return document.count(domainId, document.TYPE_PROBLEM, query);
|
return document.count(domainId, document.TYPE_PROBLEM, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function del(domainId: string, docId: number) {
|
||||||
|
return Promise.all([
|
||||||
|
document.deleteOne(domainId, document.TYPE_PROBLEM, docId),
|
||||||
|
document.deleteMultiStatus(domainId, document.TYPE_PROBLEM, { docId }),
|
||||||
|
bus.parallel('problem/delete', domainId, docId),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
export async function addTestdata(domainId: string, pid: number, name: string, f: Readable | Buffer | string) {
|
export async function addTestdata(domainId: string, pid: number, name: string, f: Readable | Buffer | string) {
|
||||||
await storage.put(`problem/${domainId}/${pid}/testdata/${name}`, f);
|
await storage.put(`problem/${domainId}/${pid}/testdata/${name}`, f);
|
||||||
const meta = await storage.getMeta(`problem/${domainId}/${pid}/testdata/${name}`);
|
const meta = await storage.getMeta(`problem/${domainId}/${pid}/testdata/${name}`);
|
||||||
@@ -208,11 +216,6 @@ export function setStar(domainId: string, pid: number, uid: number, star: boolea
|
|||||||
return document.setStatus(domainId, document.TYPE_PROBLEM, pid, uid, { star });
|
return document.setStatus(domainId, document.TYPE_PROBLEM, pid, uid, { star });
|
||||||
}
|
}
|
||||||
|
|
||||||
bus.on('problem/delete', (domainId, docId) => Promise.all([
|
|
||||||
document.deleteOne(domainId, document.TYPE_PROBLEM, docId),
|
|
||||||
document.deleteMultiStatus(domainId, document.TYPE_PROBLEM, { docId }),
|
|
||||||
]));
|
|
||||||
|
|
||||||
global.Hydro.model.problem = {
|
global.Hydro.model.problem = {
|
||||||
Pdoc,
|
Pdoc,
|
||||||
|
|
||||||
@@ -227,6 +230,7 @@ global.Hydro.model.problem = {
|
|||||||
add,
|
add,
|
||||||
inc,
|
inc,
|
||||||
get,
|
get,
|
||||||
|
del,
|
||||||
edit,
|
edit,
|
||||||
count,
|
count,
|
||||||
push,
|
push,
|
||||||
|
|||||||
@@ -194,69 +194,17 @@ function _descriptor(v: ParamOption) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get(
|
type DescriptorBuilder =
|
||||||
name: string, type: Type, validate: null, convert: Converter
|
((name: string, type: Type) => MethodDecorator)
|
||||||
): MethodDecorator;
|
& ((name: string, type: Type, validate: null, convert: Converter) => MethodDecorator)
|
||||||
export function get(
|
& ((name: string, type: Type, validate?: Validator, convert?: Converter) => MethodDecorator)
|
||||||
name: string, type: Type, validate?: Validator, convert?: Converter,
|
& ((name: string, type?: Type, isOptional?: boolean, validate?: Validator, convert?: Converter) => MethodDecorator)
|
||||||
): MethodDecorator;
|
& ((name: string, ...args: Array<Type | boolean | Validator | Converter>) => MethodDecorator)
|
||||||
export function get(
|
|
||||||
name: string, type?: Type, isOptional?: boolean, validate?: Validator, convert?: Converter,
|
|
||||||
): MethodDecorator;
|
|
||||||
export function get(
|
|
||||||
name: string, ...args: Array<Type | boolean | Validator | Converter>
|
|
||||||
): MethodDecorator;
|
|
||||||
export function get(name: string, ...args: any): MethodDecorator {
|
|
||||||
return _descriptor(_buildParam(name, 'get', ...args));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function post(
|
export const get: DescriptorBuilder = (name, ...args) => _descriptor(_buildParam(name, 'get', ...args));
|
||||||
name: string, type: Type, validate: null, convert: Converter
|
export const post: DescriptorBuilder = (name, ...args) => _descriptor(_buildParam(name, 'post', ...args));
|
||||||
): MethodDecorator;
|
export const route: DescriptorBuilder = (name, ...args) => _descriptor(_buildParam(name, 'route', ...args));
|
||||||
export function post(
|
export const param: DescriptorBuilder = (name, ...args) => _descriptor(_buildParam(name, 'all', ...args));
|
||||||
name: string, type?: Type, validate?: Validator, convert?: Converter,
|
|
||||||
): MethodDecorator;
|
|
||||||
export function post(
|
|
||||||
name: string, type?: Type, isOptional?: boolean, validate?: Validator, convert?: Converter,
|
|
||||||
): MethodDecorator;
|
|
||||||
export function post(
|
|
||||||
name: string, ...args: Array<Type | boolean | Converter | Validator>
|
|
||||||
): MethodDecorator;
|
|
||||||
export function post(name: string, ...args: any): MethodDecorator {
|
|
||||||
return _descriptor(_buildParam(name, 'post', ...args));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function route(
|
|
||||||
name: string, type: Type, validate: null, convert: Converter
|
|
||||||
): MethodDecorator;
|
|
||||||
export function route(
|
|
||||||
name: string, type?: Type, validate?: Validator, convert?: Converter,
|
|
||||||
): MethodDecorator;
|
|
||||||
export function route(
|
|
||||||
name: string, type?: Type, isOptional?: boolean, validate?: Validator, convert?: Converter,
|
|
||||||
): MethodDecorator;
|
|
||||||
export function route(
|
|
||||||
name: string, ...args: Array<Type | boolean | Converter | Validator>
|
|
||||||
): MethodDecorator;
|
|
||||||
export function route(name: string, ...args: any): MethodDecorator {
|
|
||||||
return _descriptor(_buildParam(name, 'route', ...args));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function param(
|
|
||||||
name: string, type: Type, validate: null, convert: Converter
|
|
||||||
): MethodDecorator;
|
|
||||||
export function param(
|
|
||||||
name: string, type?: Type, validate?: Validator, convert?: Converter,
|
|
||||||
): MethodDecorator;
|
|
||||||
export function param(
|
|
||||||
name: string, type?: Type, isOptional?: boolean, validate?: Validator, convert?: Converter,
|
|
||||||
): MethodDecorator;
|
|
||||||
export function param(
|
|
||||||
name: string, ...args: Array<Type | boolean | Converter | Validator>
|
|
||||||
): MethodDecorator;
|
|
||||||
export function param(name: string, ...args: any): MethodDecorator {
|
|
||||||
return _descriptor(_buildParam(name, 'all', ...args));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function requireCsrfToken(target: any, funcName: string, obj: any) {
|
export function requireCsrfToken(target: any, funcName: string, obj: any) {
|
||||||
const originalMethod = obj.value;
|
const originalMethod = obj.value;
|
||||||
@@ -323,6 +271,24 @@ export class HandlerCommon {
|
|||||||
if (!this.user.hasPriv(...args)) throw new PrivilegeError(...args);
|
if (!this.user.hasPriv(...args)) throw new PrivilegeError(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async renderHTML(name: string, context: any): Promise<string> {
|
||||||
|
const UserContext: any = {
|
||||||
|
...this.user,
|
||||||
|
gravatar: misc.gravatar(this.user.gravatar || '', 128),
|
||||||
|
perm: this.user.perm.toString(),
|
||||||
|
};
|
||||||
|
UserContext.viewLang = this.translate('__id');
|
||||||
|
if (!global.Hydro.lib.template) return JSON.stringify(context);
|
||||||
|
const res = await global.Hydro.lib.template.render(name, {
|
||||||
|
handler: this,
|
||||||
|
UserContext,
|
||||||
|
url: this.url.bind(this),
|
||||||
|
_: this.translate.bind(this),
|
||||||
|
...context,
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
url(name: string, kwargs: any = {}) {
|
url(name: string, kwargs: any = {}) {
|
||||||
let res = '#';
|
let res = '#';
|
||||||
const args: any = {};
|
const args: any = {};
|
||||||
@@ -395,9 +361,7 @@ export class Handler extends HandlerCommon {
|
|||||||
ip: ctx.request.ip,
|
ip: ctx.request.ip,
|
||||||
headers: ctx.request.headers,
|
headers: ctx.request.headers,
|
||||||
cookies: ctx.cookies,
|
cookies: ctx.cookies,
|
||||||
// @ts-ignore
|
|
||||||
body: ctx.request.body,
|
body: ctx.request.body,
|
||||||
// @ts-ignore
|
|
||||||
files: ctx.request.files,
|
files: ctx.request.files,
|
||||||
query: ctx.query,
|
query: ctx.query,
|
||||||
path: ctx.path,
|
path: ctx.path,
|
||||||
@@ -428,6 +392,8 @@ export class Handler extends HandlerCommon {
|
|||||||
url_prefix: '/',
|
url_prefix: '/',
|
||||||
};
|
};
|
||||||
this.session = {};
|
this.session = {};
|
||||||
|
const xff = system.get('server.xff');
|
||||||
|
if (xff) this.request.ip = this.request.headers[xff.toLowerCase()] || this.request.ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@lrucache
|
@lrucache
|
||||||
@@ -436,23 +402,6 @@ export class Handler extends HandlerCommon {
|
|||||||
return hash('csrf_token', id);
|
return hash('csrf_token', id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async renderHTML(name: string, context: any): Promise<string> {
|
|
||||||
const UserContext = {
|
|
||||||
...this.user,
|
|
||||||
gravatar: misc.gravatar(this.user.gravatar || '', 128),
|
|
||||||
perm: this.user.perm.toString(),
|
|
||||||
};
|
|
||||||
if (!global.Hydro.lib.template) return JSON.stringify(context);
|
|
||||||
const res = await global.Hydro.lib.template.render(name, {
|
|
||||||
handler: this,
|
|
||||||
UserContext,
|
|
||||||
url: this.url.bind(this),
|
|
||||||
_: this.translate.bind(this),
|
|
||||||
...context,
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
async render(name: string, context: any) {
|
async render(name: string, context: any) {
|
||||||
this.response.body = await this.renderHTML(name, context);
|
this.response.body = await this.renderHTML(name, context);
|
||||||
this.response.type = 'text/html';
|
this.response.type = 'text/html';
|
||||||
@@ -482,10 +431,9 @@ export class Handler extends HandlerCommon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init({ domainId }) {
|
async init({ domainId }) {
|
||||||
const xff = system.get('server.xff') as string;
|
|
||||||
if (xff) this.request.ip = this.request.headers[xff.toLowerCase()];
|
|
||||||
[this.domain] = await Promise.all([
|
[this.domain] = await Promise.all([
|
||||||
domain.get(domainId),
|
domain.get(domainId),
|
||||||
|
this.limitRate('global', 10, 100),
|
||||||
this.getSession(),
|
this.getSession(),
|
||||||
this.getBdoc(),
|
this.getBdoc(),
|
||||||
]);
|
]);
|
||||||
@@ -733,15 +681,6 @@ export class ConnectionHandler extends HandlerCommon {
|
|||||||
for (const i in p) this.request.params[p[i][0]] = decodeURIComponent(p[i][1]);
|
for (const i in p) this.request.params[p[i][0]] = decodeURIComponent(p[i][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async renderHTML(name: string, context: any): Promise<string> {
|
|
||||||
const res = await global.Hydro.lib.template.render(name, Object.assign(context, {
|
|
||||||
handler: this,
|
|
||||||
url: this.url.bind(this),
|
|
||||||
_: this.translate.bind(this),
|
|
||||||
}));
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
send(data: any) {
|
send(data: any) {
|
||||||
this.conn.write(JSON.stringify(data));
|
this.conn.write(JSON.stringify(data));
|
||||||
}
|
}
|
||||||
@@ -782,10 +721,13 @@ export class ConnectionHandler extends HandlerCommon {
|
|||||||
domain.get(domainId),
|
domain.get(domainId),
|
||||||
this.getSession(cookie),
|
this.getSession(cookie),
|
||||||
]);
|
]);
|
||||||
const bdoc = await blacklist.get(this.request.ip);
|
const [bdoc, udoc] = await Promise.all([
|
||||||
|
blacklist.get(this.request.ip),
|
||||||
|
user.getById(domainId, this.session.uid, this.session.scope),
|
||||||
|
]);
|
||||||
if (bdoc) throw new BlacklistedError(this.request.ip);
|
if (bdoc) throw new BlacklistedError(this.request.ip);
|
||||||
this.user = await user.getById(domainId, this.session.uid, this.session.scope);
|
if (!udoc) throw new UserNotFoundError(this.session.uid);
|
||||||
if (!this.user) throw new UserNotFoundError(this.session.uid);
|
this.user = udoc;
|
||||||
if (this.user._id === 0 && this.session.viewLang) this.user.viewLang = this.session.viewLang;
|
if (this.user._id === 0 && this.session.viewLang) this.user.viewLang = this.session.viewLang;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -844,17 +786,6 @@ export function start() {
|
|||||||
logger.debug(`${ctx.request.method} ${ctx.request.path} ${ctx.response.status} ${endTime - startTime}ms ${ctx.response.length}`);
|
logger.debug(`${ctx.request.method} ${ctx.request.path} ${ctx.response.status} ${endTime - startTime}ms ${ctx.response.length}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
app.use(async (ctx, next) => {
|
|
||||||
const xff = system.get('server.xff');
|
|
||||||
const ip = xff ? ctx.request.headers[xff] : ctx.request.ip;
|
|
||||||
try {
|
|
||||||
await opcount.inc('global', ip, 10, 100);
|
|
||||||
} catch (e) {
|
|
||||||
ctx.status = 429;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return await next();
|
|
||||||
});
|
|
||||||
app.use(router.routes()).use(router.allowedMethods());
|
app.use(router.routes()).use(router.allowedMethods());
|
||||||
server.listen(argv.port || port);
|
server.listen(argv.port || port);
|
||||||
logger.success('Server listening at: %d', argv.port || port);
|
logger.success('Server listening at: %d', argv.port || port);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ declare module 'terminal-kit/Terminal' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const useTerminal = cluster.isMaster && process.stdout.isTTY && !argv.legacy;
|
const useTerminal = cluster.isMaster && process.stdout.isTTY && !argv.legacy && !argv._.length;
|
||||||
|
|
||||||
export namespace Progress {
|
export namespace Progress {
|
||||||
export class Progress {
|
export class Progress {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
import { ObjectID, Collection } from 'mongodb';
|
import { ObjectID, Collection } from 'mongodb';
|
||||||
import AdmZip from 'adm-zip';
|
import AdmZip from 'adm-zip';
|
||||||
@@ -28,6 +29,7 @@ const scripts: UpgradeScript[] = [
|
|||||||
},
|
},
|
||||||
// Add history column to ddoc,drdoc,psdoc
|
// Add history column to ddoc,drdoc,psdoc
|
||||||
async function _1_2() {
|
async function _1_2() {
|
||||||
|
const _FRESH_INSTALL_IGNORE = 1;
|
||||||
const domains = await domain.getMulti().project({ _id: 1 }).toArray();
|
const domains = await domain.getMulti().project({ _id: 1 }).toArray();
|
||||||
for (const d of domains) {
|
for (const d of domains) {
|
||||||
const bulk = document.coll.initializeUnorderedBulkOp();
|
const bulk = document.coll.initializeUnorderedBulkOp();
|
||||||
@@ -46,10 +48,12 @@ const scripts: UpgradeScript[] = [
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
async function _2_3() {
|
async function _2_3() {
|
||||||
|
const _FRESH_INSTALL_IGNORE = 1;
|
||||||
await db.collection('document').updateMany({ pid: /^\d+$/i }, { $unset: { pid: '' } });
|
await db.collection('document').updateMany({ pid: /^\d+$/i }, { $unset: { pid: '' } });
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
async function _3_4() {
|
async function _3_4() {
|
||||||
|
const _FRESH_INSTALL_IGNORE = 1;
|
||||||
if (storage.error) {
|
if (storage.error) {
|
||||||
logger.error('Cannot upgrade. Please change storage config.');
|
logger.error('Cannot upgrade. Please change storage config.');
|
||||||
return false;
|
return false;
|
||||||
@@ -133,6 +137,7 @@ const scripts: UpgradeScript[] = [
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
async function _4_5() {
|
async function _4_5() {
|
||||||
|
const _FRESH_INSTALL_IGNORE = 1;
|
||||||
const domains = await domain.getMulti().project({ _id: 1 }).toArray();
|
const domains = await domain.getMulti().project({ _id: 1 }).toArray();
|
||||||
for (const d of domains) {
|
for (const d of domains) {
|
||||||
const bulk = document.coll.initializeUnorderedBulkOp();
|
const bulk = document.coll.initializeUnorderedBulkOp();
|
||||||
@@ -147,6 +152,7 @@ const scripts: UpgradeScript[] = [
|
|||||||
},
|
},
|
||||||
async function _5_6() {
|
async function _5_6() {
|
||||||
// Issue #58
|
// Issue #58
|
||||||
|
const _FRESH_INSTALL_IGNORE = 1;
|
||||||
await domain.edit('system', { owner: 1 });
|
await domain.edit('system', { owner: 1 });
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in new issue
Block a user