better types & use attend instead of enroll

This commit is contained in:
undefined committed 2020-09-07 12:43:09 +08:00
1 parent e7428c8f79
commit 3dd4c1c994
17 files changed
+141 -82

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.13.4", "version": "2.13.5",
"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",
+1 -1
View File
@@ -159,7 +159,7 @@ class HomeSecurityHandler extends Handler {
if (udoc) throw new UserAlreadyExistError(email); if (udoc) throw new UserAlreadyExistError(email);
const [code] = await token.add( const [code] = await token.add(
token.TYPE_CHANGEMAIL, token.TYPE_CHANGEMAIL,
await system.get('changemail_token_expire_seconds'), await system.get('changemail_token_expire_seconds') as number,
{ uid: this.user._id, email }, { uid: this.user._id, email },
); );
const m = await this.renderHTML('user_changemail_mail.html', { const m = await this.renderHTML('user_changemail_mail.html', {
+3 -14
View File
@@ -13,10 +13,10 @@ import {
} from '../service/server'; } from '../service/server';
import { Tdoc } from '../interface'; import { Tdoc } from '../interface';
async function _parseDagJson(domainId, dag) { async function _parseDagJson(domainId: string, _dag: string): Promise<Tdoc['dag']> {
const parsed = []; const parsed = [];
try { try {
dag = JSON.parse(dag); const dag = JSON.parse(_dag);
assert(dag instanceof Array, 'dag must be an array'); assert(dag instanceof Array, 'dag must be an array');
const ids = new Set(dag.map((s) => s._id)); const ids = new Set(dag.map((s) => s._id));
assert(dag.length === ids.size, '_id must be unique'); assert(dag.length === ids.size, '_id must be unique');
@@ -177,16 +177,6 @@ class TrainingCreateHandler extends Handler {
const pids = training.getPids(dag); const pids = training.getPids(dag);
assert(pids.length, new ValidationError('dag')); assert(pids.length, new ValidationError('dag'));
const pdocs = await problem.getMulti(domainId, { docId: { $in: pids } }).sort('_id', 1).toArray(); const pdocs = await problem.getMulti(domainId, { docId: { $in: pids } }).sort('_id', 1).toArray();
const existPids = pdocs.map((pdoc) => pdoc.docId);
const existPnames = pdocs.map((pdoc) => pdoc.pid);
if (pids.length !== existPids.length) {
for (const pid of pids) {
assert(
existPids.includes(pid) || existPnames.includes(pid),
new ProblemNotFoundError(pid),
);
}
}
for (const pdoc of pdocs) { for (const pdoc of pdocs) {
if (pdoc.hidden) this.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN); if (pdoc.hidden) this.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN);
} }
@@ -242,11 +232,10 @@ class TrainingEditHandler extends Handler {
], ],
}).sort('_id', 1).toArray(); }).sort('_id', 1).toArray();
const existPids = pdocs.map((pdoc) => pdoc.docId); const existPids = pdocs.map((pdoc) => pdoc.docId);
const existPnames = pdocs.map((pdoc) => pdoc.pid);
if (pids.length !== existPids.length) { if (pids.length !== existPids.length) {
for (const pid in pids) { for (const pid in pids) {
assert( assert(
existPids.includes(pid) || existPnames.includes(pid), existPids.includes(parseInt(pid, 10)),
new ProblemNotFoundError(pid), new ProblemNotFoundError(pid),
); );
} }
+2 -2
View File
@@ -62,7 +62,7 @@ class UserRegisterHandler extends Handler {
this.limitRate('send_mail', 3600, 30); this.limitRate('send_mail', 3600, 30);
const t = await token.add( const t = await token.add(
token.TYPE_REGISTRATION, token.TYPE_REGISTRATION,
await system.get('registration_token_expire_seconds'), await system.get('registration_token_expire_seconds') as number,
{ mail }, { mail },
); );
if (await system.get('smtp.user')) { if (await system.get('smtp.user')) {
@@ -118,7 +118,7 @@ class UserLostPassHandler extends Handler {
if (!udoc) throw new UserNotFoundError(mail); if (!udoc) throw new UserNotFoundError(mail);
const [tid] = await token.add( const [tid] = await token.add(
token.TYPE_LOSTPASS, token.TYPE_LOSTPASS,
await system.get('lostpass_token_expire_seconds'), await system.get('lostpass_token_expire_seconds') as number,
{ uid: udoc._id }, { uid: udoc._id },
); );
const m = await this.renderHTML('user_lostpass_mail', { url: `lostpass/${tid}`, uname: udoc.uname }); const m = await this.renderHTML('user_lostpass_mail', { url: `lostpass/${tid}`, uname: udoc.uname });
+35 -1
View File
@@ -3,6 +3,15 @@ import { ObjectID, GridFSBucket } from 'mongodb';
import fs from 'fs'; import fs from 'fs';
import { Dictionary, NumericDictionary } from 'lodash'; import { Dictionary, NumericDictionary } from 'lodash';
export type NumberKeys<O> = {
[K in keyof O]: number extends O[K] ? K : never
}[keyof O]
export interface System {
_id: string,
value: string | number,
}
export interface Setting { export interface Setting {
family: string, family: string,
key: string, key: string,
@@ -175,7 +184,7 @@ export interface PretestConfig {
} }
export interface ContestInfo { export interface ContestInfo {
type: number, type: 30 | 60,
tid: ObjectID, tid: ObjectID,
} }
@@ -293,6 +302,8 @@ export interface Ddoc {
ip: string, ip: string,
pin: boolean, pin: boolean,
highlight: boolean, highlight: boolean,
updateAt: Date,
nReply: number,
} }
// Discussion reply // Discussion reply
@@ -379,6 +390,29 @@ export interface JudgeResultBody {
export type PathComponent = [string, string, Dictionary<any>?, boolean?]; export type PathComponent = [string, string, Dictionary<any>?, boolean?];
export interface Collections {
'blacklist': Bdoc,
'contest': Tdoc,
'domain': DomainDoc,
'domain.user': any,
'record': Rdoc,
'document': any,
'problem': Pdoc,
'user': Udoc,
'check': any,
'message': Mdoc,
'token': TokenDoc,
'file': Ufdoc,
'status': any,
'oauth': any,
'system': System,
'task': any,
'opcount': any,
'fs.chunks': any,
'fs.files': any,
'document.status': any,
}
export interface Model { export interface Model {
blacklist: typeof import('./model/blacklist'), blacklist: typeof import('./model/blacklist'),
builtin: typeof import('./model/builtin'), builtin: typeof import('./model/builtin'),
+1 -1
View File
@@ -12,7 +12,7 @@ export async function sendMail(to: string, subject: string, text: string, html:
system.get('smtp.user'), system.get('smtp.user'),
system.get('smtp.pass'), system.get('smtp.pass'),
system.get('smtp.from'), system.get('smtp.from'),
]); ]) as unknown as [string, number, boolean, string, string, string];
const transporter = nodemailer.createTransport({ const transporter = nodemailer.createTransport({
host, port, secure, auth: { user, pass }, host, port, secure, auth: { user, pass },
}); });
+16 -12
View File
@@ -1,4 +1,4 @@
import { ObjectID } from 'mongodb'; import { ObjectID, FilterQuery } from 'mongodb';
import * as user from './user'; import * as user from './user';
import * as problem from './problem'; import * as problem from './problem';
import * as document from './document'; import * as document from './document';
@@ -13,6 +13,8 @@ import {
import * as misc from '../lib/misc'; import * as misc from '../lib/misc';
import ranked from '../lib/rank'; import ranked from '../lib/rank';
type Type = 30 | 60;
const acm: ContestRule = { const acm: ContestRule = {
TEXT: 'ACM/ICPC', TEXT: 'ACM/ICPC',
check: () => { }, check: () => { },
@@ -356,7 +358,7 @@ function _getStatusJournal(tsdoc) {
export function add( export function add(
domainId: string, title: string, content: string, owner: number, domainId: string, title: string, content: string, owner: number,
rule: string, beginAt = new Date(), endAt = new Date(), pids = [], rule: string, beginAt = new Date(), endAt = new Date(), pids = [],
rated = false, data = {}, type = document.TYPE_CONTEST, rated = false, data: Partial<Tdoc> = {}, type: Type = document.TYPE_CONTEST,
) { ) {
if (!this.RULES[rule]) throw new ValidationError('rule'); if (!this.RULES[rule]) throw new ValidationError('rule');
if (beginAt >= endAt) throw new ValidationError('beginAt', 'endAt'); if (beginAt >= endAt) throw new ValidationError('beginAt', 'endAt');
@@ -371,7 +373,7 @@ export function add(
export async function edit( export async function edit(
domainId: string, tid: ObjectID, domainId: string, tid: ObjectID,
$set: any, type = document.TYPE_CONTEST, $set: any, type: Type = document.TYPE_CONTEST,
) { ) {
if ($set.rule) { if ($set.rule) {
if (!this.RULES[$set.rule]) throw new ValidationError('rule'); if (!this.RULES[$set.rule]) throw new ValidationError('rule');
@@ -383,7 +385,7 @@ export async function edit(
} }
export async function get( export async function get(
domainId: string, tid: ObjectID, type = document.TYPE_CONTEST, domainId: string, tid: ObjectID, type: Type | -1 = document.TYPE_CONTEST,
) { ) {
let tdoc: Tdoc; let tdoc: Tdoc;
if (type === -1) { if (type === -1) {
@@ -396,7 +398,7 @@ export async function get(
export async function updateStatus( export async function updateStatus(
domainId: string, tid: ObjectID, uid: number, rid: ObjectID, pid: number, domainId: string, tid: ObjectID, uid: number, rid: ObjectID, pid: number,
accept = false, score = 0, type = document.TYPE_CONTEST, accept = false, score = 0, type: 30 | 60 = document.TYPE_CONTEST,
) { ) {
const tdoc = await get(domainId, tid, type); const tdoc = await get(domainId, tid, type);
const tsdoc = await document.revPushStatus(domainId, type, tid, uid, 'journal', { const tsdoc = await document.revPushStatus(domainId, type, tid, uid, 'journal', {
@@ -427,7 +429,7 @@ export async function getListStatus(
export async function attend( export async function attend(
domainId: string, tid: ObjectID, uid: number, domainId: string, tid: ObjectID, uid: number,
type = document.TYPE_CONTEST, type: Type = document.TYPE_CONTEST,
) { ) {
try { try {
await document.cappedIncStatus(domainId, type, tid, uid, 'attend', 1, 0, 1); await document.cappedIncStatus(domainId, type, tid, uid, 'attend', 1, 0, 1);
@@ -491,7 +493,7 @@ export const ContestHandlerMixin = (c) => class extends c {
async getScoreboard( async getScoreboard(
domainId: string, tid: ObjectID, domainId: string, tid: ObjectID,
isExport = false, docType = document.TYPE_CONTEST, isExport = false, docType: 30 | 60 = document.TYPE_CONTEST,
): Promise<[Tdoc, ScoreboardNode[][], Udict]> { ): Promise<[Tdoc, ScoreboardNode[][], Udict]> {
const tdoc = await get(domainId, tid, docType); const tdoc = await get(domainId, tid, docType);
if (!this.canShowScoreboard(tdoc)) throw new ContestScoreboardHiddenError(tid); if (!this.canShowScoreboard(tdoc)) throw new ContestScoreboardHiddenError(tid);
@@ -522,16 +524,18 @@ export function setStatus(domainId: string, tid: ObjectID, uid: number, $set: an
return document.setStatus(domainId, document.TYPE_CONTEST, tid, uid, $set); return document.setStatus(domainId, document.TYPE_CONTEST, tid, uid, $set);
} }
export function count(domainId: string, query: any, type = document.TYPE_CONTEST) { export function count(domainId: string, query: any, type: Type = document.TYPE_CONTEST) {
return document.count(domainId, type, query); return document.count(domainId, type, query);
} }
export function getMulti(domainId: string, query = {}, type = document.TYPE_CONTEST) { export function getMulti<K extends Type & keyof document.DocumentType>(
return document.getMulti(domainId, type, query); domainId: string, query: FilterQuery<document.DocumentType[K]> = {}, type?: K,
) {
return document.getMulti(domainId, type || document.TYPE_CONTEST, query);
} }
export async function getAndListStatus( export async function getAndListStatus(
domainId: string, tid: ObjectID, docType = document.TYPE_CONTEST, domainId: string, tid: ObjectID, docType: Type | -1 = document.TYPE_CONTEST,
): Promise<[Tdoc, any[]]> { ): Promise<[Tdoc, any[]]> {
// TODO(iceboy): projection, pagination. // TODO(iceboy): projection, pagination.
const tdoc = await get(domainId, tid, docType); const tdoc = await get(domainId, tid, docType);
@@ -540,7 +544,7 @@ export async function getAndListStatus(
return [tdoc, tsdocs]; return [tdoc, tsdocs];
} }
export async function recalcStatus(domainId: string, tid: ObjectID, type = document.TYPE_CONTEST) { export async function recalcStatus(domainId: string, tid: ObjectID, type: Type = document.TYPE_CONTEST) {
const [tdoc, tsdocs] = await Promise.all([ const [tdoc, tsdocs] = await Promise.all([
document.get(domainId, type, tid), document.get(domainId, type, tid),
document.getMultiStatus(domainId, type, { docId: tid }).toArray(), document.getMultiStatus(domainId, type, { docId: tid }).toArray(),
+57 -27
View File
@@ -1,7 +1,10 @@
import assert from 'assert'; import assert from 'assert';
import { ObjectID } from 'mongodb'; import { ObjectID, Cursor, FilterQuery } from 'mongodb';
import * as db from '../service/db'; import * as db from '../service/db';
import * as bus from '../service/bus'; import * as bus from '../service/bus';
import {
Pdoc, Ddoc, Ufdoc, Drdoc, Tdoc, TrainingDoc, NumberKeys,
} from '../interface';
type DocID = ObjectID | string | number; type DocID = ObjectID | string | number;
@@ -19,15 +22,28 @@ export const TYPE_TRAINING = 40;
export const TYPE_FILE = 50; export const TYPE_FILE = 50;
export const TYPE_HOMEWORK = 60; export const TYPE_HOMEWORK = 60;
export async function add<T extends DocID>( export interface DocumentType {
[TYPE_PROBLEM]: Pdoc,
[TYPE_PROBLEM_SOLUTION]: any,
[TYPE_PROBLEM_LIST]: any,
[TYPE_DISCUSSION_NODE]: any,
[TYPE_DISCUSSION]: Ddoc,
[TYPE_DISCUSSION_REPLY]: Drdoc,
[TYPE_CONTEST]: Tdoc,
[TYPE_TRAINING]: TrainingDoc,
[TYPE_FILE]: Ufdoc,
[TYPE_HOMEWORK]: Tdoc,
}
export async function add<T extends DocID, K extends keyof DocumentType>(
domainId: string, content: string, owner: number, domainId: string, content: string, owner: number,
docType: number, docId: T, docType: K, docId: DocumentType[K]['docId'],
parentType?: number | null, parentId?: DocID, parentType?: number | null, parentId?: DocID,
args?: any, args?: any,
): Promise<T> ): Promise<T>
export async function add( export async function add<K extends keyof DocumentType>(
domainId: string, content: string, owner: number, domainId: string, content: string, owner: number,
docType: number, docId: null, docType: K, docId: null,
parentType?: number, parentId?: DocID, parentType?: number, parentId?: DocID,
args?: any, args?: any,
): Promise<ObjectID> ): Promise<ObjectID>
@@ -57,11 +73,13 @@ export async function add(
return docId || res.insertedId; return docId || res.insertedId;
} }
export function get(domainId: string, docType: number, docId: DocID) { export function get<K extends keyof DocumentType>(domainId: string, docType: K, docId: DocumentType[K]['docId']) {
return coll.findOne({ domainId, docType, docId }); return coll.findOne({ domainId, docType, docId });
} }
export async function set(domainId: string, docType: number, docId: DocID, $set: any) { export async function set<K extends keyof DocumentType>(
domainId: string, docType: K, docId: DocumentType[K]['docId'], $set: Partial<DocumentType[K]>,
): Promise<DocumentType[K]> {
await bus.parallel('document/set', domainId, docType, docId, $set); await bus.parallel('document/set', domainId, docType, docId, $set);
const res = await coll.findOneAndUpdate( const res = await coll.findOneAndUpdate(
{ domainId, docType, docId }, { domainId, docType, docId },
@@ -71,28 +89,36 @@ export async function set(domainId: string, docType: number, docId: DocID, $set:
return res.value; return res.value;
} }
export function deleteOne(domainId: string, docType: number, docId: DocID) { export function deleteOne<K extends keyof DocumentType>(
domainId: string, docType: K, docId: DocumentType[K]['docId'],
) {
return Promise.all([ return Promise.all([
collStatus.deleteMany({ domainId, docType, docId }), collStatus.deleteMany({ domainId, docType, docId }),
coll.deleteOne({ domainId, docType, docId }), coll.deleteOne({ domainId, docType, docId }),
]); ]);
} }
export function deleteMulti(domainId: string, docType: number, args: any = {}) { export function deleteMulti<K extends keyof DocumentType>(
return coll.deleteMany({ ...args, domainId, docType }); domainId: string, docType: K, query?: FilterQuery<DocumentType[K]>,
) {
return coll.deleteMany({ ...query, domainId, docType });
} }
export function deleteMultiStatus(domainId: string, docType: number, args: any = {}) { export function deleteMultiStatus<K extends keyof DocumentType>(
return collStatus.deleteMany({ ...args, domainId, docType }); domainId: string, docType: K, query?: FilterQuery<DocumentType[K]>,
) {
return collStatus.deleteMany({ ...query, domainId, docType });
} }
export function getMulti(domainId: string, docType: number, args: any = {}) { export function getMulti<K extends keyof DocumentType>(
return coll.find({ ...args, docType, domainId }); domainId: string, docType: K, query?: FilterQuery<DocumentType[K]>,
): Cursor<DocumentType[K]> {
return coll.find({ ...query, docType, domainId });
} }
export async function inc( export async function inc<K extends keyof DocumentType>(
domainId: string, docType: number, docId: DocID, domainId: string, docType: K, docId: DocumentType[K]['docId'],
key: string, value: number, key: NumberKeys<DocumentType[K]>, value: number,
) { ) {
const res = await coll.findOneAndUpdate( const res = await coll.findOneAndUpdate(
{ domainId, docType, docId }, { domainId, docType, docId },
@@ -102,9 +128,11 @@ export async function inc(
return res.value; return res.value;
} }
export async function incAndSet( type Q = NumberKeys<DocumentType[10]>
domainId: string, docType: number, docId: DocID,
key: string, value: number, args: any, export async function incAndSet<K extends keyof DocumentType>(
domainId: string, docType: K, docId: DocumentType[K]['docId'],
key: NumberKeys<DocumentType[K]>, value: number, args: Partial<DocumentType[K]>,
) { ) {
const res = await coll.findOneAndUpdate( const res = await coll.findOneAndUpdate(
{ domainId, docType, docId }, { domainId, docType, docId },
@@ -114,13 +142,15 @@ export async function incAndSet(
return res.value; return res.value;
} }
export function count(domainId: string, docType: number, query: any) { export function count<K extends keyof DocumentType>(
domainId: string, docType: K, query?: FilterQuery<DocumentType[K]>,
) {
return coll.find({ ...query, docType, domainId }).count(); return coll.find({ ...query, docType, domainId }).count();
} }
export async function push( export async function push<K extends keyof DocumentType, T extends keyof DocumentType[K]>(
domainId: string, docType: number, docId: DocID, domainId: string, docType: K, docId: DocumentType[K]['docId'],
key: string, content: string, owner: number, args: any = {}, key: keyof DocumentType[K], content: string, owner: number, args: DocumentType[K][T][0] = {},
) { ) {
const _id = new ObjectID(); const _id = new ObjectID();
const doc = await coll.findOneAndUpdate( const doc = await coll.findOneAndUpdate(
@@ -137,10 +167,10 @@ export async function push(
return [doc.value, _id]; return [doc.value, _id];
} }
export async function pull( export async function pull<K extends keyof DocumentType>(
domainId: string, docType: number, docId: DocID, domainId: string, docType: K, docId: DocumentType[K]['docId'],
setKey: string, contents: string[], setKey: string, contents: string[],
) { ): Promise<DocumentType[K]> {
const res = await coll.findOneAndUpdate( const res = await coll.findOneAndUpdate(
{ domainId, docType, docId }, { domainId, docType, docId },
{ $pull: { [setKey]: { $in: contents } } }, { $pull: { [setKey]: { $in: contents } } },
+1 -2
View File
@@ -1,10 +1,9 @@
import { Dictionary } from 'lodash'; import { Dictionary } from 'lodash';
import { Collection } from 'mongodb';
import { BUILTIN_ROLES, PRIV } from './builtin'; import { BUILTIN_ROLES, PRIV } from './builtin';
import { DomainDoc } from '../interface'; import { DomainDoc } from '../interface';
import * as db from '../service/db'; import * as db from '../service/db';
const coll: Collection<DomainDoc> = db.collection('domain'); const coll = db.collection('domain');
const collUser = db.collection('domain.user'); const collUser = db.collection('domain.user');
export const JOIN_METHOD_NONE = 0; export const JOIN_METHOD_NONE = 0;
+3 -3
View File
@@ -6,7 +6,7 @@ import * as file from './file';
import * as document from './document'; import * as document from './document';
import * as domain from './domain'; import * as domain from './domain';
import { import {
Pdoc, Pdict, ProblemDataSource, ProblemStatusDoc, Pdoc, Pdict, ProblemDataSource, ProblemStatusDoc, NumberKeys,
} from '../interface'; } from '../interface';
import { ProblemNotFoundError } from '../error'; import { ProblemNotFoundError } from '../error';
import * as testdataConfig from '../lib/testdataConfig'; import * as testdataConfig from '../lib/testdataConfig';
@@ -63,7 +63,7 @@ export async function get(
if (typeof pid !== 'number') { if (typeof pid !== 'number') {
if (Number.isSafeInteger(parseInt(pid, 10))) pid = parseInt(pid, 10); if (Number.isSafeInteger(parseInt(pid, 10))) pid = parseInt(pid, 10);
} }
const pdoc = Number.isInteger(pid) const pdoc = typeof pid === 'number'
? await document.get(domainId, document.TYPE_PROBLEM, pid) ? await document.get(domainId, document.TYPE_PROBLEM, pid)
: (await document.getMulti(domainId, document.TYPE_PROBLEM, { pid }).toArray())[0]; : (await document.getMulti(domainId, document.TYPE_PROBLEM, { pid }).toArray())[0];
if (!pdoc) return null; if (!pdoc) return null;
@@ -85,7 +85,7 @@ export function edit(domainId: string, _id: number, $set: Partial<Pdoc>): Promis
return document.set(domainId, document.TYPE_PROBLEM, _id, $set); return document.set(domainId, document.TYPE_PROBLEM, _id, $set);
} }
export function inc(domainId: string, _id: number, field: string, n: number): Promise<Pdoc> { export function inc(domainId: string, _id: number, field: NumberKeys<Pdoc>, n: number): Promise<Pdoc> {
return document.inc(domainId, document.TYPE_PROBLEM, _id, field, n); return document.inc(domainId, document.TYPE_PROBLEM, _id, field, n);
} }
+5 -3
View File
@@ -2,11 +2,11 @@ import Lru from 'lru-cache';
import * as db from '../service/db'; import * as db from '../service/db';
const coll = db.collection('system'); const coll = db.collection('system');
const cache = new Lru({ const cache = new Lru<string, string | number>({
maxAge: 5000, maxAge: 5000,
}); });
export async function get(_id: string) { export async function get(_id: string): Promise<string | number> {
const res = cache.get(_id); const res = cache.get(_id);
if (res !== undefined) return res; if (res !== undefined) return res;
const doc = await coll.findOne({ _id }); const doc = await coll.findOne({ _id });
@@ -51,11 +51,13 @@ export async function set(_id: string, value: any) {
export async function inc(_id: string) { export async function inc(_id: string) {
const res = await coll.findOneAndUpdate( const res = await coll.findOneAndUpdate(
{ _id }, { _id },
// FIXME NumberKeys<>
// @ts-ignore
{ $inc: { value: 1 } }, { $inc: { value: 1 } },
{ upsert: true, returnOriginal: false }, { upsert: true, returnOriginal: false },
); );
cache.set(_id, res.value.value); cache.set(_id, res.value.value);
return res.value.value; return res.value.value as number;
} }
global.Hydro.model.system = { global.Hydro.model.system = {
+2 -2
View File
@@ -27,7 +27,7 @@ export async function enroll(domainId: string, tid: ObjectID, uid: number) {
} catch (e) { } catch (e) {
throw new TrainingAlreadyEnrollError(tid, uid); throw new TrainingAlreadyEnrollError(tid, uid);
} }
return await document.inc(domainId, document.TYPE_TRAINING, tid, 'enroll', 1); return await document.inc(domainId, document.TYPE_TRAINING, tid, 'attend', 1);
} }
export function setStatus(domainId: string, tid: ObjectID, uid: number, $set: any) { export function setStatus(domainId: string, tid: ObjectID, uid: number, $set: any) {
@@ -42,7 +42,7 @@ export function add(
dag, dag,
title, title,
description, description,
enroll: 0, attend: 0,
}); });
} }
+1 -1
View File
@@ -128,7 +128,7 @@ async function runInDomain(domainId: string, isSub: boolean, report: Function) {
for (const dudoc of dudocs) { for (const dudoc of dudocs) {
deltaudict[dudoc.uid] = dudoc.rpdelta || 0; deltaudict[dudoc.uid] = dudoc.rpdelta || 0;
} }
const contests = await contest.getMulti(domainId, { rated: true }, -1).sort('endAt', -1).toArray(); const contests = await contest.getMulti(domainId, { rated: true }).sort('endAt', -1).toArray();
await report({ message: `Found ${contests.length} contests in ${domainId}` }); await report({ message: `Found ${contests.length} contests in ${domainId}` });
for (const i in contests) { for (const i in contests) {
const tdoc = contests[i]; const tdoc = contests[i];
+3 -2
View File
@@ -1,6 +1,7 @@
import mongodb from 'mongodb'; import mongodb, { Collection } from 'mongodb';
import * as bus from './bus'; import * as bus from './bus';
import options from '../options'; import options from '../options';
import { Collections } from '../interface';
const opts = options(); const opts = options();
@@ -25,7 +26,7 @@ mongodb.MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopolog
}); });
}); });
export function collection(c: string) { export function collection<K extends keyof Collections>(c: K): Collection<Collections[K]> {
if (opts.prefix) return db.collection(`${opts.prefix}.${c}`); if (opts.prefix) return db.collection(`${opts.prefix}.${c}`);
return db.collection(c); return db.collection(c);
} }
+5 -5
View File
@@ -203,7 +203,7 @@ export function requireCsrfToken(target: any, funcName: string, obj: any) {
} }
export async function prepare() { export async function prepare() {
app.keys = await system.get('session.keys'); app.keys = await system.get('session.keys') as unknown as string[];
if (argv.public) { if (argv.public) {
app.use(cache(argv.public, { app.use(cache(argv.public, {
maxAge: 0, maxAge: 0,
@@ -402,7 +402,7 @@ export class Handler {
} }
async init({ domainId }) { async init({ domainId }) {
const xff = await system.get('server.xff'); const xff = await system.get('server.xff') as string;
if (xff) this.request.ip = this.request.headers[xff.toLowerCase()]; 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),
@@ -498,8 +498,8 @@ export class Handler {
async saveCookie() { async saveCookie() {
const expireSeconds = this.session.save const expireSeconds = this.session.save
? await system.get('session.expire_seconds') ? await system.get('session.expire_seconds') as number
: await system.get('session.unsaved_expire_seconds'); : await system.get('session.unsaved_expire_seconds') as number;
if (this.session._id) { if (this.session._id) {
await token.update( await token.update(
this.session._id, this.session._id,
@@ -525,7 +525,7 @@ export class Handler {
); );
} }
const cookie: SetOption = { const cookie: SetOption = {
secure: await system.get('session.secure'), secure: !!await system.get('session.secure'),
httpOnly: false, httpOnly: false,
}; };
if (this.session.save) { if (this.session.save) {
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@hydrooj/migrate-vijos", "name": "@hydrooj/migrate-vijos",
"version": "1.3.7", "version": "1.3.8",
"main": "package.json", "main": "package.json",
"repository": "git@github.com:hydro-dev/Hydro.git", "repository": "git@github.com:hydro-dev/Hydro.git",
"author": "undefined <masnn0@outlook.com>", "author": "undefined <masnn0@outlook.com>",
@@ -14,7 +14,7 @@
"@types/mongodb": "^3.5.27" "@types/mongodb": "^3.5.27"
}, },
"peerDependencies": { "peerDependencies": {
"hydrooj": "^2.13.0" "hydrooj": "^2.13.5"
}, },
"dependencies": { "dependencies": {
"js-yaml": "^3.14.0", "js-yaml": "^3.14.0",
+3 -3
View File
@@ -1,6 +1,6 @@
/* eslint-disable no-await-in-loop */ /* eslint-disable no-await-in-loop */
import { import {
Rdoc, TestCase, Mdoc, Drrdoc, Rdoc, TestCase, Mdoc, Drrdoc, TrainingNode,
} from 'hydrooj'; } from 'hydrooj';
import fs from 'fs'; import fs from 'fs';
import os from 'os'; import os from 'os';
@@ -126,12 +126,12 @@ const tasks = {
}, },
attend: 'attend', attend: 'attend',
desc: 'description', desc: 'description',
enroll: 'enroll', enroll: 'attend',
rated: 'rated', rated: 'rated',
dag: { dag: {
field: 'dag', field: 'dag',
processer: (dag) => { processer: (dag) => {
const r = []; const r: TrainingNode[] = [];
for (const t of dag) { for (const t of dag) {
r.push({ r.push({
_id: t._id, _id: t._id,