diff --git a/framework/framework/validator.ts b/framework/framework/validator.ts index ef64b2001..036665304 100644 --- a/framework/framework/validator.ts +++ b/framework/framework/validator.ts @@ -111,7 +111,7 @@ export const Types = { Float: [(v) => +v, (v) => Number.isFinite(+v)], ObjectId: [() => { throw new Error('mongodb package not found'); }, () => true], - Boolean: [(v) => !!(v && !['false', 'off'].includes(v)), null, true], + Boolean: [(v) => !!(v && !['false', 'off', 'no', '0'].includes(v)), null, true], Date: [ (v) => { const d = v.split('-'); diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index beca5b820..a88e3252c 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -192,23 +192,35 @@ export class ProblemMainHandler extends Handler { @param('target', Types.String) @param('hidden', Types.Boolean) async postCopy(domainId: string, pids: number[], target: string, hidden?: boolean) { - const t = `,${this.domain.share || ''},`; - if (t !== ',*,' && !t.includes(`,${target},`)) throw new PermissionError(target); - const ddoc = await domain.get(target); + let t = `,${this.domain.share || ''},`; + if (t !== ',*,' && !t.includes(`,${target},`)) throw new ProblemNotAllowCopyError(this.domain._id, target); + let ddoc = await domain.get(target); if (!ddoc) throw new NotFoundError(target); const dudoc = await user.getById(target, this.user._id); if (!dudoc.hasPerm(PERM.PERM_CREATE_PROBLEM)) throw new PermissionError(PERM.PERM_CREATE_PROBLEM); // Check if user can access all those problems - await problem.getList( + const pdict = await problem.getList( domainId, pids, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN) || this.user._id, true, ['docId'], true, ); const ids = []; for (const pid of pids) { + let pdoc = pdict[pid]; + if (pdoc.reference) { + // eslint-disable-next-line no-await-in-loop + [pdoc, ddoc] = await Promise.all([ + problem.get(pdoc.reference.domainId, pdoc.reference.pid), + domain.get(pdoc.reference.domainId), + ]); + if (!pdoc) throw new ProblemNotFoundError(pdoc.reference.domainId, pdoc.reference.pid); + t = `,${ddoc.share || ''},`; + if (t !== ',*,' && !t.includes(`,${target},`)) throw new ProblemNotAllowCopyError(ddoc._id, target); + } // eslint-disable-next-line no-await-in-loop - ids.push(await problem.copy(domainId, pid, target, undefined, hidden)); + ids.push(await problem.copy(pdoc.domainId, pdoc.docId, target, undefined, hidden)); } this.response.body = ids; + if (ids.length === 1) this.response.redirect = this.url('problem_detail', { domainId: target, pid: ids[0] }); } @param('pids', Types.NumericArray) @@ -420,28 +432,6 @@ export class ProblemDetailHandler extends ContestDetailBaseHandler { this.back(); } - @param('target', Types.String) - async postCopy({ }, target: string) { - let t = `,${this.domain.share || ''},`; - if (t !== ',*,' && !t.includes(`,${target},`)) throw new ProblemNotAllowCopyError(this.domain._id, target); - let ddoc = await domain.get(target); - if (!ddoc) throw new NotFoundError(target); - const dudoc = await user.getById(target, this.user._id); - let pdoc = this.pdoc; - if (this.pdoc.reference) { - [pdoc, ddoc] = await Promise.all([ - problem.get(this.pdoc.reference.domainId, this.pdoc.reference.pid), - domain.get(this.pdoc.reference.domainId), - ]); - if (!pdoc) throw new ProblemNotFoundError(this.pdoc.reference.domainId, this.pdoc.reference.pid); - t = `,${ddoc.share || ''},`; - if (t !== ',*,' && !t.includes(`,${target},`)) throw new ProblemNotAllowCopyError(ddoc._id, target); - } - if (!dudoc.hasPerm(PERM.PERM_CREATE_PROBLEM)) throw new PermissionError(PERM.PERM_CREATE_PROBLEM); - const docId = await problem.copy(pdoc.domainId, pdoc.docId, target); - this.response.redirect = this.url('problem_detail', { domainId: target, pid: docId }); - } - async postDelete() { if (!this.user.own(this.pdoc, PERM.PERM_EDIT_PROBLEM_SELF)) this.checkPerm(PERM.PERM_EDIT_PROBLEM); const tdocs = await contest.getRelated(this.args.domainId, this.pdoc.docId); diff --git a/packages/hydrooj/src/model/message.ts b/packages/hydrooj/src/model/message.ts index f43a14d53..6fdf332bf 100644 --- a/packages/hydrooj/src/model/message.ts +++ b/packages/hydrooj/src/model/message.ts @@ -31,9 +31,8 @@ class MessageModel { } static async sendInfo(to: number, content: string) { - const _id = new ObjectId(); const mdoc: MessageDoc = { - _id, from: 1, to, content, flag: MessageModel.FLAG_INFO | MessageModel.FLAG_I18N, + from: 1, to, content, flag: MessageModel.FLAG_INFO | MessageModel.FLAG_I18N, }; bus.broadcast('user/message', [to], mdoc); } diff --git a/packages/hydrooj/src/plugin-api.ts b/packages/hydrooj/src/plugin-api.ts index 58cebb39d..e70bbf508 100644 --- a/packages/hydrooj/src/plugin-api.ts +++ b/packages/hydrooj/src/plugin-api.ts @@ -6,7 +6,7 @@ export { default as moment, isMoment } from 'moment-timezone'; export { WebService, Router, HandlerCommon, httpServer, - Query, Mutation, Subscription, Apis, + Query, Mutation, Subscription, Apis, APIS, } from '@hydrooj/framework'; export * from './pipelineUtils'; diff --git a/packages/ui-default/components/dialog/index.tsx b/packages/ui-default/components/dialog/index.tsx index c9761963f..5f2b898e8 100644 --- a/packages/ui-default/components/dialog/index.tsx +++ b/packages/ui-default/components/dialog/index.tsx @@ -1,6 +1,7 @@ /* eslint-disable react-refresh/only-export-components */ import $ from 'jquery'; import React from 'react'; +import ReactDOM from 'react-dom/client'; import { i18n, tpl } from 'vj/utils'; import DomainSelectAutoComplete from '../autocomplete/components/DomainSelectAutoComplete'; import UserSelectAutoComplete from '../autocomplete/components/UserSelectAutoComplete'; @@ -125,6 +126,8 @@ export async function prompt(title: string, fields: Record [name, field.default || ''])) as Record; + console.log(valueCache, defaultValues); + const Component = () => { const [values, setValues] = React.useState(defaultValues); @@ -132,7 +135,7 @@ export async function prompt(title: string, fields: Record + return

{title}

@@ -169,8 +172,12 @@ export async function prompt(title: string, fields: Record)}
; }; + const div = document.createElement('div'); + const root = ReactDOM.createRoot(div); + root.render(); const res = await new Dialog({ - $body: $(tpl(, true)), + $body: $(div), + $action: [buttonCancel, buttonOk].join('\n'), onDispatch(action) { if (action === 'ok') { for (const [name, field] of Object.entries(fields)) { @@ -180,6 +187,7 @@ export async function prompt(title: string, fields: Record