mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
bug fixes
This commit is contained in:
15 files changed
+23
-163
No files matched your search
@@ -15,7 +15,7 @@
|
|||||||
"koa-compress": "^5.1.1",
|
"koa-compress": "^5.1.1",
|
||||||
"koa-router": "^13.0.1",
|
"koa-router": "^13.0.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moment-timezone": "^0.5.47",
|
"moment-timezone": "^0.5.48",
|
||||||
"path-to-regexp": "^8.2.0",
|
"path-to-regexp": "^8.2.0",
|
||||||
"sanitize-filename": "^1.6.3",
|
"sanitize-filename": "^1.6.3",
|
||||||
"saslprep": "^1.0.3",
|
"saslprep": "^1.0.3",
|
||||||
|
|||||||
+4
-4
@@ -253,7 +253,7 @@ parallelism: ${Math.max(1, Math.floor(cpus().length / 4))}
|
|||||||
singleTaskParallelism: 2
|
singleTaskParallelism: 2
|
||||||
rate: 1.00
|
rate: 1.00
|
||||||
rerun: 2
|
rerun: 2
|
||||||
secret: Hydro-Judge-Secret
|
secret: ${String.random(32)}
|
||||||
env: |
|
env: |
|
||||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
HOME=/w
|
HOME=/w
|
||||||
@@ -711,7 +711,7 @@ async function main() {
|
|||||||
while (res.code && op[1].ignore !== true) {
|
while (res.code && op[1].ignore !== true) {
|
||||||
if (op[1].retry && retry < 30) {
|
if (op[1].retry && retry < 30) {
|
||||||
log.warn('Retry in 3 secs... (%s)', op[0]);
|
log.warn('Retry in 3 secs... (%s)', op[0]);
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await sleep(3000);
|
await sleep(3000);
|
||||||
res = exec(op[0], { stdio: 'inherit' });
|
res = exec(op[0], { stdio: 'inherit' });
|
||||||
retry++;
|
retry++;
|
||||||
@@ -723,9 +723,9 @@ async function main() {
|
|||||||
while (res === 'retry') {
|
while (res === 'retry') {
|
||||||
if (retry < 30) {
|
if (retry < 30) {
|
||||||
log.warn('Retry in 3 secs...');
|
log.warn('Retry in 3 secs...');
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await sleep(3000);
|
await sleep(3000);
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
res = await op[0](op[1]);
|
res = await op[0](op[1]);
|
||||||
retry++;
|
retry++;
|
||||||
} else log.fatal('Error installing');
|
} else log.fatal('Error installing');
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@
|
|||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/autocannon": "^7.12.6",
|
"@types/autocannon": "^7.12.6",
|
||||||
"@types/chai": "^5.2.0",
|
"@types/chai": "^5.2.1",
|
||||||
"@types/cross-spawn": "^6.0.6",
|
"@types/cross-spawn": "^6.0.6",
|
||||||
"@types/node": "22.13.8",
|
"@types/node": "22.13.8",
|
||||||
"@types/semver": "^7.5.8",
|
"@types/semver": "^7.5.8",
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
sandbox_host:
|
|
||||||
type: text
|
|
||||||
name: sandbox_host
|
|
||||||
desc: Sandbox Host
|
|
||||||
default: http://localhost:5050
|
|
||||||
tmp_dir:
|
|
||||||
type: text
|
|
||||||
name: tmp_dir
|
|
||||||
desc: Temp directory
|
|
||||||
default: $TEMP/hydro/judge
|
|
||||||
stdio_size:
|
|
||||||
type: text
|
|
||||||
name: stdio_size
|
|
||||||
desc: Stdout/Stderr size
|
|
||||||
default: 32m
|
|
||||||
processLimit:
|
|
||||||
type: number
|
|
||||||
name: processLimit
|
|
||||||
desc: Process Limit
|
|
||||||
default: 32
|
|
||||||
testcases_max:
|
|
||||||
type: number
|
|
||||||
name: testcases_max
|
|
||||||
desc: Max testcases per problem
|
|
||||||
default: 100
|
|
||||||
total_time_limit:
|
|
||||||
type: number
|
|
||||||
name: total_time_limit
|
|
||||||
desc: Total time limit per problem
|
|
||||||
default: 60
|
|
||||||
memoryMax:
|
|
||||||
type: text
|
|
||||||
name: memoryMax
|
|
||||||
default: 512m
|
|
||||||
cache_dir:
|
|
||||||
type: text
|
|
||||||
name: cache_dir
|
|
||||||
desc: Testdata cache directory
|
|
||||||
default: $HOME/.cache/hydro/judge
|
|
||||||
parallelism:
|
|
||||||
type: number
|
|
||||||
name: parallelism
|
|
||||||
desc: Runner parallelism
|
|
||||||
default: 2
|
|
||||||
singleTaskParallelism:
|
|
||||||
type: number
|
|
||||||
name: singleTaskParallelism
|
|
||||||
default: 2
|
|
||||||
rate:
|
|
||||||
type: float
|
|
||||||
name: rate
|
|
||||||
desc: (?)
|
|
||||||
default: 1
|
|
||||||
rerun:
|
|
||||||
type: number
|
|
||||||
name: rerun
|
|
||||||
desc: Re-Run testcase if time-limit-exceeded (max per submission)
|
|
||||||
default: 0
|
|
||||||
disable:
|
|
||||||
type: boolean
|
|
||||||
name: disable
|
|
||||||
desc: Disable builtin judge
|
|
||||||
default: false
|
|
||||||
strict_memory:
|
|
||||||
type: boolean
|
|
||||||
name: strict_memory
|
|
||||||
desc: Strict Memory Mode
|
|
||||||
default: false
|
|
||||||
env:
|
|
||||||
type: textarea
|
|
||||||
name: env
|
|
||||||
desc: Sandbox Env
|
|
||||||
default: |
|
|
||||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
||||||
HOME=/w
|
|
||||||
# modify to your python version installed
|
|
||||||
PYTHONPATH=/lib/python3.10/site-packages
|
|
||||||
secret:
|
|
||||||
type: text
|
|
||||||
name: secret
|
|
||||||
desc: Judge Token Secret
|
|
||||||
default: Hydro-Judge-Secret
|
|
||||||
detail:
|
|
||||||
type: boolean
|
|
||||||
name: detail
|
|
||||||
desc: Show diff detail
|
|
||||||
default: true
|
|
||||||
@@ -30,7 +30,7 @@ export const JudgeSettings = Schema.object({
|
|||||||
rate: Schema.number().default(1),
|
rate: Schema.number().default(1),
|
||||||
env: Schema.string().default(defaultEnv),
|
env: Schema.string().default(defaultEnv),
|
||||||
host: Schema.any(),
|
host: Schema.any(),
|
||||||
secret: Schema.string().description('Judge Token Secret').default('Hydro-Judge-Secret'),
|
secret: Schema.string().description('Judge Token Secret').default(String.random(32)),
|
||||||
disable: Schema.boolean().description('Disable builtin judge').default(false),
|
disable: Schema.boolean().description('Disable builtin judge').default(false),
|
||||||
detail: Schema.boolean().description('Show diff detail').default(true),
|
detail: Schema.boolean().description('Show diff detail').default(true),
|
||||||
performance: Schema.boolean().description('Performance mode').default(false),
|
performance: Schema.boolean().description('Performance mode').default(false),
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lru-cache": "^10.4.3",
|
"lru-cache": "^10.4.3",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
"moment-timezone": "^0.5.47",
|
"moment-timezone": "^0.5.48",
|
||||||
"mongodb": "^6.15.0",
|
"mongodb": "^6.15.0",
|
||||||
"mongodb-uri": "^0.9.7",
|
"mongodb-uri": "^0.9.7",
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.1.5",
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import type { EventMap } from './service/bus';
|
|||||||
import type CheckService from './service/check';
|
import type CheckService from './service/check';
|
||||||
import type { } from './service/migration';
|
import type { } from './service/migration';
|
||||||
|
|
||||||
// TODO: this is an broken declaration
|
|
||||||
export { EventMap as Events };
|
export { EventMap as Events };
|
||||||
|
|
||||||
function addScript<K>(name: string, description: string, validate: Schema<K>, run: (args: K, report: any) => boolean | Promise<boolean>) {
|
function addScript<K>(name: string, description: string, validate: Schema<K>, run: (args: K, report: any) => boolean | Promise<boolean>) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { load as loadOptions } from '../options';
|
|||||||
import { MongoService } from '../service/db';
|
import { MongoService } from '../service/db';
|
||||||
import { ConfigService } from '../settings';
|
import { ConfigService } from '../settings';
|
||||||
import {
|
import {
|
||||||
addon, builtinModel, model, service, setting,
|
addon, builtinModel, model, service,
|
||||||
} from './common';
|
} from './common';
|
||||||
|
|
||||||
const argv = cac().parse();
|
const argv = cac().parse();
|
||||||
@@ -125,7 +125,6 @@ export async function load(ctx: Context) {
|
|||||||
ctx.plugin(require('../service/worker'));
|
ctx.plugin(require('../service/worker'));
|
||||||
await builtinModel(ctx);
|
await builtinModel(ctx);
|
||||||
await model(pending, fail, ctx);
|
await model(pending, fail, ctx);
|
||||||
await setting(pending, fail, require('../model/setting'));
|
|
||||||
ctx.plugin(require('../service/server'));
|
ctx.plugin(require('../service/server'));
|
||||||
ctx = await new Promise((resolve) => {
|
ctx = await new Promise((resolve) => {
|
||||||
ctx.inject(['server', 'setting', 'worker'], (c) => {
|
ctx.inject(['server', 'setting', 'worker'], (c) => {
|
||||||
|
|||||||
@@ -79,44 +79,3 @@ export async function locale(pending: Record<string, string>, fail: string[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setting(pending: Record<string, string>, fail: string[], modelSetting: typeof import('../model/setting')) {
|
|
||||||
const map = {
|
|
||||||
system: modelSetting.SystemSetting,
|
|
||||||
account: modelSetting.AccountSetting,
|
|
||||||
preference: modelSetting.PreferenceSetting,
|
|
||||||
domain: modelSetting.DomainSetting,
|
|
||||||
};
|
|
||||||
for (const i of Object.values(pending)) {
|
|
||||||
let p = path.resolve(i, 'setting.yaml');
|
|
||||||
const t = i.split(path.sep);
|
|
||||||
// TODO: change this name setting to package name
|
|
||||||
const name = t[t.length - 1];
|
|
||||||
if (!fs.existsSync(p)) p = path.resolve(i, 'settings.yaml');
|
|
||||||
if (fs.existsSync(p) && !fail.includes(i)) {
|
|
||||||
try {
|
|
||||||
const cfg: any = yaml.load(await fs.readFile(p, 'utf-8'));
|
|
||||||
for (const key in cfg) {
|
|
||||||
let val = cfg[key].default || cfg[key].value;
|
|
||||||
if (typeof val === 'string') {
|
|
||||||
val = val
|
|
||||||
.replace(/\$TEMP/g, os.tmpdir())
|
|
||||||
.replace(/\$HOME/g, os.homedir());
|
|
||||||
}
|
|
||||||
const category = cfg[key].category || 'system';
|
|
||||||
map[category](
|
|
||||||
modelSetting.Setting(
|
|
||||||
cfg[key].family || name, category === 'system' ? `${name}.${key}` : key, val, cfg[key].type || 'text',
|
|
||||||
cfg[key].name || key, cfg[key].desc || '',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
logger.info('Config load: %s', i);
|
|
||||||
} catch (e) {
|
|
||||||
app.injectUI('Notification', 'Config load fail: {0}', { args: [i], type: 'warn' }, PRIV.PRIV_VIEW_SYSTEM_NOTIFICATION);
|
|
||||||
logger.error('Config Load Fail: %s', i);
|
|
||||||
logger.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,7 @@ import { load } from '../options';
|
|||||||
import { MongoService } from '../service/db';
|
import { MongoService } from '../service/db';
|
||||||
import { ConfigService } from '../settings';
|
import { ConfigService } from '../settings';
|
||||||
import {
|
import {
|
||||||
addon, builtinModel, locale, model, service, setting,
|
addon, builtinModel, locale, model, service,
|
||||||
} from './common';
|
} from './common';
|
||||||
|
|
||||||
const argv = cac().parse();
|
const argv = cac().parse();
|
||||||
@@ -53,11 +53,10 @@ export async function apply(ctx: Context) {
|
|||||||
require('../lib/index');
|
require('../lib/index');
|
||||||
|
|
||||||
ctx.plugin(require('../service/monitor'));
|
ctx.plugin(require('../service/monitor'));
|
||||||
ctx.plugin(require('../service/check'));
|
ctx.plugin(require('../service/check').default);
|
||||||
await service(pending, fail, ctx);
|
await service(pending, fail, ctx);
|
||||||
await builtinModel(ctx);
|
await builtinModel(ctx);
|
||||||
await model(pending, fail, ctx);
|
await model(pending, fail, ctx);
|
||||||
await setting(pending, fail, require('../model/setting'));
|
|
||||||
ctx = await new Promise((resolve) => {
|
ctx = await new Promise((resolve) => {
|
||||||
ctx.inject(['worker', 'setting'], (c) => {
|
ctx.inject(['worker', 'setting'], (c) => {
|
||||||
resolve(c);
|
resolve(c);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// TODO check more
|
// TODO check more
|
||||||
|
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { Dictionary } from 'lodash';
|
import { DisposableList } from '@cordisjs/core';
|
||||||
import { Context, Service } from '../context';
|
import { Context, Service } from '../context';
|
||||||
import * as system from '../model/system';
|
import * as system from '../model/system';
|
||||||
import db from './db';
|
import db from './db';
|
||||||
@@ -11,7 +11,7 @@ type ReportFunction = (message: string, ...args: any[]) => Promise<void>;
|
|||||||
type CheckItem = (context: any, log: ReportFunction, warn: ReportFunction, error: ReportFunction) => Promise<void>;
|
type CheckItem = (context: any, log: ReportFunction, warn: ReportFunction, error: ReportFunction) => Promise<void>;
|
||||||
|
|
||||||
export default class CheckService extends Service {
|
export default class CheckService extends Service {
|
||||||
checkers: Dictionary<CheckItem> = {};
|
checkers = new DisposableList<CheckItem>();
|
||||||
c = {};
|
c = {};
|
||||||
|
|
||||||
constructor(ctx: Context) {
|
constructor(ctx: Context) {
|
||||||
@@ -51,24 +51,19 @@ export default class CheckService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addChecker(type: string, checkFunc: CheckItem) {
|
addChecker(type: string, checkFunc: CheckItem) {
|
||||||
this.ctx.effect(() => {
|
this.checkers.push(checkFunc);
|
||||||
this.checkers[`check${type}`] = checkFunc;
|
|
||||||
return () => {
|
|
||||||
delete this.checkers[`check${type}`];
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async run(ctx, log, warn, error, cb: (id: string) => void) {
|
async run(ctx, log, warn, error, cb: (id: string) => void) {
|
||||||
const id = String.random(6);
|
const id = String.random(6);
|
||||||
cb(id);
|
cb(id);
|
||||||
for (const name in this.checkers) {
|
for (const check of this.checkers) {
|
||||||
if (this.c[id]) {
|
if (this.c[id]) {
|
||||||
delete this.c[id];
|
delete this.c[id];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await this.checkers[name](ctx, log, warn, error);
|
await check(ctx, log, warn, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ export default class LoginWithGithubService extends Service {
|
|||||||
ctx.provideModule('oauth', 'github', {
|
ctx.provideModule('oauth', 'github', {
|
||||||
text: 'Login with Github',
|
text: 'Login with Github',
|
||||||
callback: async function callback({ state, code }) {
|
callback: async function callback({ state, code }) {
|
||||||
const url = await SystemModel.get('server.url');
|
|
||||||
const s = await TokenModel.get(state, TokenModel.TYPE_OAUTH);
|
const s = await TokenModel.get(state, TokenModel.TYPE_OAUTH);
|
||||||
if (!s) throw new ValidationError('token');
|
if (!s) throw new ValidationError('token');
|
||||||
|
const url = SystemModel.get('server.url');
|
||||||
const res = await superagent.post(`${config.endpoint || 'https://github.com'}/login/oauth/access_token`)
|
const res = await superagent.post(`${config.endpoint || 'https://github.com'}/login/oauth/access_token`)
|
||||||
.send({
|
.send({
|
||||||
client_id: config.id,
|
client_id: config.id,
|
||||||
@@ -59,8 +59,7 @@ export default class LoginWithGithubService extends Service {
|
|||||||
},
|
},
|
||||||
get: async function get(this: Handler) {
|
get: async function get(this: Handler) {
|
||||||
const [state] = await TokenModel.add(TokenModel.TYPE_OAUTH, 600, { redirect: this.request.referer });
|
const [state] = await TokenModel.add(TokenModel.TYPE_OAUTH, 600, { redirect: this.request.referer });
|
||||||
// eslint-disable-next-line max-len
|
this.response.redirect = `https://github.com/login/oauth/authorize?client_id=${config.id}&state=${state}&scope=read:user,user:email`;
|
||||||
this.response.redirect = `https://github.com/login/oauth/authorize?client_id=${config.appid}&state=${state}&scope=read:user,user:email`;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
ctx.i18n.load('zh', {
|
ctx.i18n.load('zh', {
|
||||||
|
|||||||
@@ -64,14 +64,11 @@ export default class GoogleOAuthService extends Service {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
get: async function get(this: Handler) {
|
get: async function get(this: Handler) {
|
||||||
const [appid, url, [state]] = await Promise.all([
|
const [state] = await TokenModel.add(TokenModel.TYPE_OAUTH, 600, { redirect: this.request.referer });
|
||||||
config.id,
|
const url = SystemModel.get('server.url');
|
||||||
config.proxy,
|
|
||||||
TokenModel.add(TokenModel.TYPE_OAUTH, 600, { redirect: this.request.referer }),
|
|
||||||
]);
|
|
||||||
const scope = encodeURIComponent('https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile');
|
const scope = encodeURIComponent('https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile');
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
this.response.redirect = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${appid}&response_type=code&redirect_uri=${url}oauth/google/callback&scope=${scope}&state=${state}`;
|
this.response.redirect = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${config.id}&response_type=code&redirect_uri=${url}oauth/google/callback&scope=${scope}&state=${state}`;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
ctx.i18n.load('zh', {
|
ctx.i18n.load('zh', {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"@fontsource/source-code-pro": "^5.2.5",
|
"@fontsource/source-code-pro": "^5.2.5",
|
||||||
"@fontsource/ubuntu-mono": "^5.2.5",
|
"@fontsource/ubuntu-mono": "^5.2.5",
|
||||||
"@hydrooj/utils": "workspace:^",
|
"@hydrooj/utils": "workspace:^",
|
||||||
"@sentry/browser": "^9.8.0",
|
"@sentry/browser": "^9.9.0",
|
||||||
"@sentry/webpack-plugin": "^3.2.2",
|
"@sentry/webpack-plugin": "^3.2.2",
|
||||||
"@simplewebauthn/browser": "13.1.0",
|
"@simplewebauthn/browser": "13.1.0",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"cac": "^6.7.14",
|
"cac": "^6.7.14",
|
||||||
"fs-extra": "^11.3.0",
|
"fs-extra": "^11.3.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"moment-timezone": "^0.5.47",
|
"moment-timezone": "^0.5.48",
|
||||||
"mongodb": "^6.15.0",
|
"mongodb": "^6.15.0",
|
||||||
"reggol": "^2.1.0",
|
"reggol": "^2.1.0",
|
||||||
"search-query-parser": "^1.6.0",
|
"search-query-parser": "^1.6.0",
|
||||||
|
|||||||
Reference in new issue
Block a user