mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
bump version
This commit is contained in:
3 files changed
+12
-75
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "4.14.0",
|
"version": "4.14.1",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "src/plugin-api",
|
"main": "src/plugin-api",
|
||||||
"module": "src/plugin-api",
|
"module": "src/plugin-api",
|
||||||
|
|||||||
@@ -91,6 +91,11 @@ export class ContestDetailBaseHandler extends Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tsdocAsPublic() {
|
||||||
|
if (!this.tsdoc) return null;
|
||||||
|
return pick(this.tsdoc, ['attend', 'startAt', ...(this.tdoc.duration ? ['endAt'] : [])]);
|
||||||
|
}
|
||||||
|
|
||||||
@param('tid', Types.ObjectId, true)
|
@param('tid', Types.ObjectId, true)
|
||||||
async after(domainId: string, tid: ObjectId) {
|
async after(domainId: string, tid: ObjectId) {
|
||||||
if (!tid || this.tdoc.rule === 'homework') return;
|
if (!tid || this.tdoc.rule === 'homework') return;
|
||||||
@@ -129,37 +134,19 @@ export class ContestDetailBaseHandler extends Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ContestDetailHandler extends Handler {
|
export class ContestDetailHandler extends ContestDetailBaseHandler {
|
||||||
tdoc?: Tdoc;
|
|
||||||
tsdoc?: any;
|
|
||||||
|
|
||||||
@param('tid', Types.ObjectId)
|
@param('tid', Types.ObjectId)
|
||||||
async prepare(domainId: string, tid: ObjectId) {
|
async prepare(domainId: string, tid: ObjectId) {
|
||||||
[this.tdoc, this.tsdoc] = await Promise.all([
|
|
||||||
contest.get(domainId, tid),
|
|
||||||
contest.getStatus(domainId, tid, this.user._id),
|
|
||||||
]);
|
|
||||||
if (contest.RULES[this.tdoc.rule].hidden) throw new ContestNotFoundError(domainId, tid);
|
if (contest.RULES[this.tdoc.rule].hidden) throw new ContestNotFoundError(domainId, tid);
|
||||||
if (this.tdoc.assign?.length && !this.user.own(this.tdoc) && !this.user.hasPerm(PERM.PERM_VIEW_HIDDEN_CONTEST)) {
|
|
||||||
const groups = await user.listGroup(domainId, this.user._id);
|
|
||||||
if (!Set.intersection(this.tdoc.assign, groups.map((i) => i.name)).size) {
|
|
||||||
throw new NotAssignedError('contest', tid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.tdoc.duration && this.tsdoc?.startAt) {
|
|
||||||
this.tsdoc.endAt = moment(this.tsdoc.startAt).add(this.tdoc.duration, 'hours').toDate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@param('tid', Types.ObjectId)
|
@param('tid', Types.ObjectId)
|
||||||
async get(domainId: string, tid: ObjectId) {
|
async get(domainId: string, tid: ObjectId) {
|
||||||
this.response.template = 'contest_detail.html';
|
this.response.template = 'contest_detail.html';
|
||||||
const udict = await user.getList(domainId, [this.tdoc.owner]);
|
const udict = await user.getList(domainId, [this.tdoc.owner]);
|
||||||
const fields = ['attend', 'startAt'];
|
|
||||||
if (this.tdoc.duration) fields.push('endAt');
|
|
||||||
this.response.body = {
|
this.response.body = {
|
||||||
tdoc: this.tdoc,
|
tdoc: this.tdoc,
|
||||||
tsdoc: pick(this.tsdoc, fields),
|
tsdoc: this.tsdocAsPublic(),
|
||||||
udict,
|
udict,
|
||||||
files: sortFiles(this.tdoc.files || []),
|
files: sortFiles(this.tdoc.files || []),
|
||||||
urlForFile: (filename: string) => this.url('contest_file_download', { tid, filename }),
|
urlForFile: (filename: string) => this.url('contest_file_download', { tid, filename }),
|
||||||
@@ -168,36 +155,6 @@ export class ContestDetailHandler extends Handler {
|
|||||||
this.response.body.tdoc.content = this.response.body.tdoc.content
|
this.response.body.tdoc.content = this.response.body.tdoc.content
|
||||||
.replace(/\(file:\/\//g, `(./${this.tdoc.docId}/file/`)
|
.replace(/\(file:\/\//g, `(./${this.tdoc.docId}/file/`)
|
||||||
.replace(/="file:\/\//g, `="./${this.tdoc.docId}/file/`);
|
.replace(/="file:\/\//g, `="./${this.tdoc.docId}/file/`);
|
||||||
const pdoc = 'pdoc' in this ? (this as any).pdoc : {};
|
|
||||||
this.response.body.overrideNav = [
|
|
||||||
{
|
|
||||||
name: 'contest_main',
|
|
||||||
args: {},
|
|
||||||
displayName: 'Back to contest list',
|
|
||||||
checker: () => true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'contest_detail',
|
|
||||||
displayName: this.tdoc.title,
|
|
||||||
args: { tid, prefix: 'contest_detail' },
|
|
||||||
checker: () => true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'contest_problemlist',
|
|
||||||
args: { tid },
|
|
||||||
checker: () => true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'contest_scoreboard',
|
|
||||||
args: { tid, prefix: 'contest_scoreboard' },
|
|
||||||
checker: () => contest.canShowScoreboard.call(this, this.tdoc, true),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: `${String.fromCharCode(65 + this.tdoc.pids.indexOf(pdoc.docId))}. ${pdoc.title}`,
|
|
||||||
args: { query: { tid }, pid: pdoc.docId, prefix: 'contest_detail_problem' },
|
|
||||||
checker: () => 'pdoc' in this,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@param('tid', Types.ObjectId)
|
@param('tid', Types.ObjectId)
|
||||||
@@ -231,7 +188,7 @@ export class ContestProblemListHandler extends ContestDetailBaseHandler {
|
|||||||
await contest.setStatus(domainId, tid, this.user._id, { startAt: new Date() });
|
await contest.setStatus(domainId, tid, this.user._id, { startAt: new Date() });
|
||||||
this.tsdoc.startAt = new Date();
|
this.tsdoc.startAt = new Date();
|
||||||
}
|
}
|
||||||
this.response.body.tsdoc = pick(this.tsdoc, ['attend', 'startAt', ...(this.tdoc.duration ? ['endAt'] : [])]);
|
this.response.body.tsdoc = this.tsdocAsPublic();
|
||||||
this.response.body.psdict = this.tsdoc.detail || {};
|
this.response.body.psdict = this.tsdoc.detail || {};
|
||||||
const psdocs: any[] = Object.values(this.response.body.psdict);
|
const psdocs: any[] = Object.values(this.response.body.psdict);
|
||||||
const canViewRecord = contest.canShowSelfRecord.call(this, this.tdoc);
|
const canViewRecord = contest.canShowSelfRecord.call(this, this.tdoc);
|
||||||
@@ -300,9 +257,8 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler {
|
|||||||
const page_name = this.tdoc.rule === 'homework'
|
const page_name = this.tdoc.rule === 'homework'
|
||||||
? 'homework_scoreboard'
|
? 'homework_scoreboard'
|
||||||
: 'contest_scoreboard';
|
: 'contest_scoreboard';
|
||||||
const tsdoc = pick(this.tsdoc, ['attend', 'startAt', ...(this.tdoc.duration ? ['endAt'] : [])]);
|
|
||||||
this.response.body = {
|
this.response.body = {
|
||||||
tdoc: this.tdoc, tsdoc, rows, udict, pdict, page_name, groups,
|
tdoc: this.tdoc, tsdoc: this.tsdocAsPublic(), rows, udict, pdict, page_name, groups,
|
||||||
};
|
};
|
||||||
this.response.pjax = 'partials/scoreboard.html';
|
this.response.pjax = 'partials/scoreboard.html';
|
||||||
this.response.template = 'contest_scoreboard.html';
|
this.response.template = 'contest_scoreboard.html';
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import { PenaltyRules, Tdoc } from '../interface';
|
|||||||
import { PERM } from '../model/builtin';
|
import { PERM } from '../model/builtin';
|
||||||
import * as contest from '../model/contest';
|
import * as contest from '../model/contest';
|
||||||
import * as discussion from '../model/discussion';
|
import * as discussion from '../model/discussion';
|
||||||
import * as oplog from '../model/oplog';
|
|
||||||
import problem from '../model/problem';
|
import problem from '../model/problem';
|
||||||
import record from '../model/record';
|
import record from '../model/record';
|
||||||
import storage from '../model/storage';
|
import storage from '../model/storage';
|
||||||
@@ -20,7 +19,7 @@ import user from '../model/user';
|
|||||||
import {
|
import {
|
||||||
Handler, param, post, Types,
|
Handler, param, post, Types,
|
||||||
} from '../service/server';
|
} from '../service/server';
|
||||||
import { ContestCodeHandler, ContestScoreboardHandler } from './contest';
|
import { ContestCodeHandler, ContestFileDownloadHandler, ContestScoreboardHandler } from './contest';
|
||||||
|
|
||||||
const validatePenaltyRules = (input: string) => yaml.load(input);
|
const validatePenaltyRules = (input: string) => yaml.load(input);
|
||||||
const convertPenaltyRules = validatePenaltyRules;
|
const convertPenaltyRules = validatePenaltyRules;
|
||||||
@@ -301,24 +300,6 @@ export class HomeworkFilesHandler extends Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HomeworkFileDownloadHandler extends Handler {
|
|
||||||
@param('tid', Types.ObjectId)
|
|
||||||
@param('filename', Types.Filename)
|
|
||||||
@param('noDisposition', Types.Boolean)
|
|
||||||
async get(domainId: string, tid: ObjectId, filename: string, noDisposition = false) {
|
|
||||||
this.response.addHeader('Cache-Control', 'public');
|
|
||||||
const target = `contest/${domainId}/${tid}/${filename}`;
|
|
||||||
const file = await storage.getMeta(target);
|
|
||||||
await oplog.log(this, 'download.file.contest', {
|
|
||||||
target,
|
|
||||||
size: file?.size || 0,
|
|
||||||
});
|
|
||||||
this.response.redirect = await storage.signDownloadLink(
|
|
||||||
target, noDisposition ? undefined : filename, false, 'user',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function apply(ctx) {
|
export async function apply(ctx) {
|
||||||
ctx.Route('homework_main', '/homework', HomeworkMainHandler, PERM.PERM_VIEW_HOMEWORK);
|
ctx.Route('homework_main', '/homework', HomeworkMainHandler, PERM.PERM_VIEW_HOMEWORK);
|
||||||
ctx.Route('homework_create', '/homework/create', HomeworkEditHandler);
|
ctx.Route('homework_create', '/homework/create', HomeworkEditHandler);
|
||||||
@@ -331,5 +312,5 @@ export async function apply(ctx) {
|
|||||||
ctx.Route('homework_code', '/homework/:tid/code', ContestCodeHandler, PERM.PERM_VIEW_HOMEWORK);
|
ctx.Route('homework_code', '/homework/:tid/code', ContestCodeHandler, PERM.PERM_VIEW_HOMEWORK);
|
||||||
ctx.Route('homework_edit', '/homework/:tid/edit', HomeworkEditHandler);
|
ctx.Route('homework_edit', '/homework/:tid/edit', HomeworkEditHandler);
|
||||||
ctx.Route('homework_files', '/homework/:tid/file', HomeworkFilesHandler, PERM.PERM_VIEW_HOMEWORK);
|
ctx.Route('homework_files', '/homework/:tid/file', HomeworkFilesHandler, PERM.PERM_VIEW_HOMEWORK);
|
||||||
ctx.Route('homework_file_download', '/homework/:tid/file/:filename', HomeworkFileDownloadHandler, PERM.PERM_VIEW_HOMEWORK);
|
ctx.Route('homework_file_download', '/homework/:tid/file/:filename', ContestFileDownloadHandler, PERM.PERM_VIEW_HOMEWORK);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user