bump ver,system.get更换为同步操作

This commit is contained in:
undefined committed 2020-09-26 18:39:15 +08:00
1 parent 99b7d33157
commit 03d199fe9d
19 files changed
+96 -107

No files matched your search

+8 -8
View File
@@ -19,26 +19,26 @@
"devDependencies": { "devDependencies": {
"@shelf/jest-mongodb": "^1.2.3", "@shelf/jest-mongodb": "^1.2.3",
"@types/cross-spawn": "^6.0.2", "@types/cross-spawn": "^6.0.2",
"@types/jest": "^26.0.13", "@types/jest": "^26.0.14",
"@types/node": "^14.6.4", "@types/node": "^14.11.2",
"@types/semver": "^7.3.3", "@types/semver": "^7.3.4",
"@typescript-eslint/eslint-plugin": "^3.9.1", "@typescript-eslint/eslint-plugin": "^3.9.1",
"@typescript-eslint/parser": "^3.9.1", "@typescript-eslint/parser": "^3.9.1",
"cross-spawn": "^7.0.3", "cross-spawn": "^7.0.3",
"eslint": "^7.8.1", "eslint": "^7.9.0",
"eslint-config-airbnb-base": "^14.2.0", "eslint-config-airbnb-base": "^14.2.0",
"eslint-import-resolver-typescript": "^2.3.0", "eslint-import-resolver-typescript": "^2.3.0",
"eslint-plugin-import": "^2.22.0", "eslint-plugin-import": "^2.22.0",
"globby": "^11.0.1", "globby": "^11.0.1",
"jest": "^26.4.2", "jest": "^26.4.2",
"latest-version": "^5.1.0", "latest-version": "^5.1.0",
"ora": "^5.0.0", "ora": "^5.1.0",
"semver": "^7.3.2", "semver": "^7.3.2",
"ts-jest": "^26.3.0", "ts-jest": "^26.4.0",
"typescript": "^4.0.2" "typescript": "^4.0.3"
}, },
"dependencies": { "dependencies": {
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"yargs": "^15.4.1" "yargs": "^16.0.3"
} }
} }
+2 -2
View File
@@ -7,14 +7,14 @@
"linux" "linux"
], ],
"dependencies": { "dependencies": {
"axios": "^0.19.0", "axios": "^0.20.0",
"bson": "^4.1.0", "bson": "^4.1.0",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"js-yaml": "^3.14.0", "js-yaml": "^3.14.0",
"lodash": "^4.17.20", "lodash": "^4.17.20",
"p-queue": "^6.6.1", "p-queue": "^6.6.1",
"shell-quote": "^1.7.2", "shell-quote": "^1.7.2",
"systeminformation": "^4.27.3" "systeminformation": "^4.27.5"
}, },
"peerDependencies": { "peerDependencies": {
"hydrooj": "^2.13.3" "hydrooj": "^2.13.3"
+1
View File
@@ -12,3 +12,4 @@ message.markAsRead
存储系统抽象化 存储系统抽象化
extend problem settings extend problem settings
+oplog +oplog
将系统设置存于本地而非数据库
+6 -6
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.13.17", "version": "2.13.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",
@@ -24,15 +24,15 @@
"lodash": "^4.17.20", "lodash": "^4.17.20",
"lru-cache": "^6.0.0", "lru-cache": "^6.0.0",
"moment-timezone": "^0.5.31", "moment-timezone": "^0.5.31",
"mongodb": "^3.6.1", "mongodb": "^3.6.2",
"nodemailer": "^6.4.10", "nodemailer": "^6.4.10",
"ps-list": "^7.2.0", "ps-list": "^7.2.0",
"serialize-javascript": "^4.0.0", "serialize-javascript": "^5.0.1",
"sockjs": "^0.3.20", "sockjs": "^0.3.20",
"superagent": "^6.1.0", "superagent": "^6.1.0",
"supports-color": "^7.2.0", "supports-color": "^7.2.0",
"systeminformation": "^4.27.3", "systeminformation": "^4.27.5",
"yargs": "^15.4.1" "yargs": "^16.0.3"
}, },
"devDependencies": { "devDependencies": {
"@types/adm-zip": "^0.4.33", "@types/adm-zip": "^0.4.33",
@@ -49,7 +49,7 @@
"@types/sockjs": "^0.3.32", "@types/sockjs": "^0.3.32",
"@types/superagent": "^4.1.8", "@types/superagent": "^4.1.8",
"@types/supports-color": "^5.3.0", "@types/supports-color": "^5.3.0",
"@types/yargs": "^15.0.5" "@types/yargs": "^15.0.7"
}, },
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
+2 -2
View File
@@ -34,11 +34,11 @@ const checks: Dictionary<CheckItem> = {
} }
}, },
async checkMail(ctx, log, warn) { async checkMail(ctx, log, warn) {
const from = await system.get('smtp.from'); const from = system.get('smtp.from');
if (!from) warn('SMTP account was not provided, email verification disabled.'); if (!from) warn('SMTP account was not provided, email verification disabled.');
}, },
async checkIpHeader(ctx, log, warn) { async checkIpHeader(ctx, log, warn) {
const header = await system.get('server.xff'); const header = system.get('server.xff');
if (header && !ctx.request.ip) warn('IP header seems incorrect.\nCheck dashboard>settings>server.'); if (header && !ctx.request.ip) warn('IP header seems incorrect.\nCheck dashboard>settings>server.');
}, },
}; };
+4 -1
View File
@@ -49,7 +49,10 @@ export async function load(call: Entry) {
fs.removeSync(lockfile); fs.removeSync(lockfile);
}); });
await new Promise((resolve) => { await new Promise((resolve) => {
bus.once('database/connect', resolve); bus.once('database/connect', () => {
bus.once('database/config', resolve);
require('../model/system');
});
require('../service/db'); require('../service/db');
}); });
require('../service/monitor'); require('../service/monitor');
+4 -1
View File
@@ -20,7 +20,10 @@ export async function load() {
uistatic(pending, fail), uistatic(pending, fail),
]); ]);
await new Promise((resolve) => { await new Promise((resolve) => {
bus.once('database/connect', resolve); bus.once('database/connect', () => {
bus.once('database/config', resolve);
require('../model/system');
});
require('../service/db'); require('../service/db');
}); });
for (const i of builtinLib) require(`../lib/${i}`); for (const i of builtinLib) require(`../lib/${i}`);
+1 -1
View File
@@ -201,7 +201,7 @@ class DomainJoinApplicationsHandler extends ManageHandler {
if (!this.response.body.joinSettings) { if (!this.response.body.joinSettings) {
delete this.response.body.expirations[domain.JOIN_EXPIRATION_KEEP_CURRENT]; delete this.response.body.expirations[domain.JOIN_EXPIRATION_KEEP_CURRENT];
} }
this.response.body.url_prefix = await system.get('server.url'); this.response.body.url_prefix = system.get('server.url');
this.response.body.path = [ this.response.body.path = [
['Hydro', 'homepage'], ['Hydro', 'homepage'],
['domain', null], ['domain', null],
+2 -2
View File
@@ -159,13 +159,13 @@ 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'), system.get('changemail_token_expire_seconds'),
{ 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', {
path: `home/changeMail/${code}`, path: `home/changeMail/${code}`,
uname: this.user.uname, uname: this.user.uname,
url_prefix: await system.get('server.url'), url_prefix: system.get('server.url'),
}); });
await mail.sendMail(email, 'Change Email', 'user_changemail_mail', m); await mail.sendMail(email, 'Change Email', 'user_changemail_mail', m);
this.response.template = 'user_changemail_mail_sent.html'; this.response.template = 'user_changemail_mail_sent.html';
+2 -2
View File
@@ -78,7 +78,7 @@ class SystemDashboardHandler extends SystemHandler {
} }
async postRestart() { async postRestart() {
const count = await system.get('server.worker'); const count = system.get('server.worker');
process.send({ event: 'restart', count }); process.send({ event: 'restart', count });
this.back(); this.back();
} }
@@ -141,7 +141,7 @@ class SystemSettingHandler extends SystemHandler {
for (const s of this.response.body.settings) { for (const s of this.response.body.settings) {
// FIXME no-await-in-loop // FIXME no-await-in-loop
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
this.response.body.current[s.key] = await system.get(s.key); this.response.body.current[s.key] = system.get(s.key);
} }
} }
+1 -1
View File
@@ -26,7 +26,7 @@ class FileDownloadHandler extends Handler {
class FileUploadHandler extends Handler { class FileUploadHandler extends Handler {
async getQuota() { async getQuota() {
let quota = await system.get('user.quota'); let quota = system.get('user.quota');
if (this.user.hasPriv(PRIV.PRIV_UNLIMITED_QUOTA)) { if (this.user.hasPriv(PRIV.PRIV_UNLIMITED_QUOTA)) {
quota = 2 ** 63 - 1; quota = 2 ** 63 - 1;
} }
+6 -6
View File
@@ -62,13 +62,13 @@ 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('session.unsaved_expire_seconds'), system.get('session.unsaved_expire_seconds'),
{ mail }, { mail },
); );
if (await system.get('smtp.user')) { if (system.get('smtp.user')) {
const m = await this.renderHTML('user_register_mail.html', { const m = await this.renderHTML('user_register_mail.html', {
path: `register/${t[0]}`, path: `register/${t[0]}`,
url_prefix: await system.get('server.url'), url_prefix: system.get('server.url'),
}); });
await sendMail(mail, 'Sign Up', 'user_register_mail', m); await sendMail(mail, 'Sign Up', 'user_register_mail', m);
this.response.template = 'user_register_mail_sent.html'; this.response.template = 'user_register_mail_sent.html';
@@ -107,18 +107,18 @@ class UserRegisterWithCodeHandler extends Handler {
class UserLostPassHandler extends Handler { class UserLostPassHandler extends Handler {
async get() { async get() {
if (!await system.get('smtp.user')) throw new SystemError('Cannot send mail'); if (!system.get('smtp.user')) throw new SystemError('Cannot send mail');
this.response.template = 'user_lostpass.html'; this.response.template = 'user_lostpass.html';
} }
@param('mail', Types.String, isEmail) @param('mail', Types.String, isEmail)
async post(domainId: string, mail: string) { async post(domainId: string, mail: string) {
if (!await system.get('smtp.user')) throw new SystemError('Cannot send mail'); if (!system.get('smtp.user')) throw new SystemError('Cannot send mail');
const udoc = await user.getByEmail('system', mail); const udoc = await user.getByEmail('system', mail);
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('session.unsaved_expire_seconds'), system.get('session.unsaved_expire_seconds'),
{ 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 });
+1
View File
@@ -18,6 +18,7 @@ export interface SystemKeys {
'smtp.port': number, 'smtp.port': number,
'smtp.secure': boolean, 'smtp.secure': boolean,
'user': number, 'user': number,
'server.name': string,
'server.url': string, 'server.url': string,
'server.xff': string, 'server.xff': string,
'server.worker': number, 'server.worker': number,
+25 -46
View File
@@ -1,72 +1,45 @@
import Lru from 'lru-cache';
import { NumberKeys } from '../typeutils'; import { NumberKeys } from '../typeutils';
import { SystemKeys } from '../interface'; import { SystemKeys } from '../interface';
import * as db from '../service/db'; import * as db from '../service/db';
import * as bus from '../service/bus';
const coll = db.collection('system'); const coll = db.collection('system');
const cache: Record<string, any> = {};
const cache = new Lru<string, any>({ export function get<K extends keyof SystemKeys>(key: K): SystemKeys[K] {
maxAge: 5000, return cache[key];
});
export async function get<K extends keyof SystemKeys>(_id: K): Promise<SystemKeys[K]> {
const res = cache.get(_id);
if (res !== undefined) return res;
const doc = await coll.findOne({ _id });
if (doc) {
cache.set(_id, doc.value);
return doc.value;
}
return null;
} }
export async function getMany< export function getMany<
A extends keyof SystemKeys, B extends keyof SystemKeys, A extends keyof SystemKeys, B extends keyof SystemKeys,
>(keys: [A, B]): Promise<[SystemKeys[A], SystemKeys[B]]> >(keys: [A, B]): [SystemKeys[A], SystemKeys[B]]
export async function getMany< export function getMany<
A extends keyof SystemKeys, B extends keyof SystemKeys, C extends keyof SystemKeys, A extends keyof SystemKeys, B extends keyof SystemKeys, C extends keyof SystemKeys,
>(keys: [A, B, C]): Promise<[SystemKeys[A], SystemKeys[B], SystemKeys[C]]> >(keys: [A, B, C]): [SystemKeys[A], SystemKeys[B], SystemKeys[C]]
export async function getMany< export function getMany<
A extends keyof SystemKeys, B extends keyof SystemKeys, C extends keyof SystemKeys, A extends keyof SystemKeys, B extends keyof SystemKeys, C extends keyof SystemKeys,
D extends keyof SystemKeys, D extends keyof SystemKeys,
>(keys: [A, B, C, D]): Promise<[SystemKeys[A], SystemKeys[B], SystemKeys[C], SystemKeys[D]]> >(keys: [A, B, C, D]): [SystemKeys[A], SystemKeys[B], SystemKeys[C], SystemKeys[D]]
export async function getMany< export function getMany<
A extends keyof SystemKeys, B extends keyof SystemKeys, C extends keyof SystemKeys, A extends keyof SystemKeys, B extends keyof SystemKeys, C extends keyof SystemKeys,
D extends keyof SystemKeys, E extends keyof SystemKeys, D extends keyof SystemKeys, E extends keyof SystemKeys,
>(keys: [A, B, C, D, E]): Promise<[SystemKeys[A], SystemKeys[B], SystemKeys[C], SystemKeys[D], SystemKeys[E]]> >(keys: [A, B, C, D, E]): [SystemKeys[A], SystemKeys[B], SystemKeys[C], SystemKeys[D], SystemKeys[E]]
export async function getMany< export function getMany<
A extends keyof SystemKeys, B extends keyof SystemKeys, C extends keyof SystemKeys, A extends keyof SystemKeys, B extends keyof SystemKeys, C extends keyof SystemKeys,
D extends keyof SystemKeys, E extends keyof SystemKeys, F extends keyof SystemKeys, D extends keyof SystemKeys, E extends keyof SystemKeys, F extends keyof SystemKeys,
>(keys: [A, B, C, D, E, F]): Promise<[SystemKeys[A], SystemKeys[B], SystemKeys[C], SystemKeys[D], SystemKeys[E], SystemKeys[F]]> >(keys: [A, B, C, D, E, F]): [SystemKeys[A], SystemKeys[B], SystemKeys[C], SystemKeys[D], SystemKeys[E], SystemKeys[F]]
export async function getMany(keys: (keyof SystemKeys)[]): Promise<any[]> export function getMany(keys: (keyof SystemKeys)[]): any[]
export async function getMany(keys: string[]): Promise<any[]> { export function getMany(keys: string[]): any[] {
const r = []; return keys.map((key) => cache[key]);
let success = true;
for (const key of keys) {
const res = cache.get(key);
if (res !== undefined) r.push(res);
else success = false;
}
if (success) return r;
const docs = await coll.find({ _id: { $in: keys } }).toArray();
const dict = {};
const res = [];
for (const doc of docs) {
dict[doc._id] = doc.value;
}
for (const key of keys) {
res.push(dict[key] || null);
}
return res;
} }
export async function set<K extends keyof SystemKeys>(_id: K, value: SystemKeys[K]) { export async function set<K extends keyof SystemKeys>(_id: K, value: SystemKeys[K]) {
cache.set(_id, value);
const res = await coll.findOneAndUpdate( const res = await coll.findOneAndUpdate(
{ _id }, { _id },
{ $set: { value } }, { $set: { value } },
{ upsert: true, returnOriginal: false }, { upsert: true, returnOriginal: false },
); );
cache[_id] = res.value.value;
return res.value.value; return res.value.value;
} }
@@ -78,10 +51,16 @@ export async function inc<K extends NumberKeys<SystemKeys>>(_id: K) {
{ $inc: { value: 1 } }, { $inc: { value: 1 } },
{ upsert: true, returnOriginal: false }, { upsert: true, returnOriginal: false },
); );
cache.set(_id, res.value.value); cache[_id] = res.value.value;
return res.value.value; return res.value.value;
} }
(async () => {
const config = await coll.find({}).toArray();
for (const i of config) cache[i._id] = i.value;
bus.emit('database/config');
})();
global.Hydro.model.system = { global.Hydro.model.system = {
get, get,
getMany, getMany,
+1
View File
@@ -31,6 +31,7 @@ export interface EventMap {
'app/exit': () => VoidReturn 'app/exit': () => VoidReturn
'database/connect': (db: Db) => void 'database/connect': (db: Db) => void
'database/config': () => void
'monitor/update': (type: 'server' | 'judger', $set: any) => VoidReturn 'monitor/update': (type: 'server' | 'judger', $set: any) => VoidReturn
+25 -20
View File
@@ -169,7 +169,7 @@ function _descriptor(v: ParamOption) {
: item.source === 'get' : item.source === 'get'
? this.request.query ? this.request.query
: item.source === 'route' : item.source === 'route'
? this.request.params ? { ...this.request.params, domainId: this.domainId }
: this.request.body; : this.request.body;
const value = src[item.name]; const value = src[item.name];
if (!item.isOptional || value) { if (!item.isOptional || value) {
@@ -263,7 +263,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') as unknown as string[]; app.keys = 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,
@@ -286,6 +286,8 @@ export class Handler {
args: any; args: any;
domainId: string;
ctx: Koa.Context; ctx: Koa.Context;
request: { request: {
@@ -398,7 +400,7 @@ export class Handler {
} }
renderTitle(str: string) { renderTitle(str: string) {
return `${this.translate(str)} - Hydro`; return `${this.translate(str)} - ${system.get('server.name')}`;
} }
checkPerm(...args: bigint[]) { checkPerm(...args: bigint[]) {
@@ -419,9 +421,9 @@ export class Handler {
else args[key] = kwargs[key].toString(); else args[key] = kwargs[key].toString();
} }
try { try {
if (this.args.domainId !== 'system' || args.domainId) { if (this.domainId !== 'system' || args.domainId) {
name += '_with_domainId'; name += '_with_domainId';
args.domainId = args.domainId || this.args.domainId; args.domainId = args.domainId || this.domainId;
} }
const { anchor, query } = args; const { anchor, query } = args;
if (query) res = router.url(name, args, { query }); if (query) res = router.url(name, args, { query });
@@ -464,7 +466,7 @@ export class Handler {
} }
async init({ domainId }) { async init({ domainId }) {
const xff = await system.get('server.xff') as string; const xff = 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),
@@ -560,8 +562,8 @@ export class Handler {
async saveCookie() { async saveCookie() {
const expireSeconds = this.session.save const expireSeconds = this.session.save
? await system.get('session.expire_seconds') as number ? system.get('session.expire_seconds') as number
: await system.get('session.unsaved_expire_seconds') as number; : 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,
@@ -587,7 +589,7 @@ export class Handler {
); );
} }
const cookie: SetOption = { const cookie: SetOption = {
secure: !!await system.get('session.secure'), secure: !!system.get('session.secure'),
httpOnly: false, httpOnly: false,
}; };
if (this.session.save) { if (this.session.save) {
@@ -694,18 +696,20 @@ export class ConnectionHandler {
conn: sockjs.Connection; conn: sockjs.Connection;
request: { request: {
params: any params: any;
headers: any headers: any;
ip: string ip: string;
} }
session: any domainId: string;
args: any session: any;
user: any args: any;
domain: DomainDoc user: User;
domain: DomainDoc;
constructor(conn: sockjs.Connection) { constructor(conn: sockjs.Connection) {
this.conn = conn; this.conn = conn;
@@ -738,7 +742,7 @@ export class ConnectionHandler {
} }
renderTitle(str: string) { renderTitle(str: string) {
return `${this.translate(str)} - Hydro`; return `${this.translate(str)} - ${system.get('server.name')}`;
} }
checkPerm(...args: bigint[]) { checkPerm(...args: bigint[]) {
@@ -832,6 +836,7 @@ export function Connection(
try { try {
const args = { domainId: 'system', ...h.request.params }; const args = { domainId: 'system', ...h.request.params };
h.args = args; h.args = args;
h.domainId = args.domainId;
const cookie = await new Promise((r) => { const cookie = await new Promise((r) => {
conn.once('data', r); conn.once('data', r);
}); });
@@ -860,8 +865,8 @@ export function Connection(
} }
// TODO use postInit? // TODO use postInit?
export async function start() { export function start() {
const port = await system.get('server.port'); const port = system.get('server.port');
if (argv.debug) { if (argv.debug) {
app.use(async (ctx: Context, next: Function) => { app.use(async (ctx: Context, next: Function) => {
const startTime = new Date().getTime(); const startTime = new Date().getTime();
@@ -880,7 +885,7 @@ export async function start() {
}); });
} }
app.use(async (ctx, next) => { app.use(async (ctx, next) => {
const xff = await system.get('server.xff'); const xff = system.get('server.xff');
const ip = xff ? ctx.request.headers[xff] : ctx.request.ip; const ip = xff ? ctx.request.headers[xff] : ctx.request.ip;
try { try {
await opcount.inc('global', ip, 10, 100); await opcount.inc('global', ip, 10, 100);
+3 -7
View File
@@ -17,6 +17,7 @@ describe('Model.Problem', () => {
test('add_get', async () => { test('add_get', async () => {
const pid = await problem.add(DOMAIN_ID, PNAME, TITLE, CONTENT, UID); const pid = await problem.add(DOMAIN_ID, PNAME, TITLE, CONTENT, UID);
expect(pid).toBeTruthy();
let pdoc = await problem.get(DOMAIN_ID, PNAME); let pdoc = await problem.get(DOMAIN_ID, PNAME);
expect(pdoc.domainId).toStrictEqual(DOMAIN_ID); expect(pdoc.domainId).toStrictEqual(DOMAIN_ID);
expect(pdoc.title).toStrictEqual(TITLE); expect(pdoc.title).toStrictEqual(TITLE);
@@ -24,13 +25,8 @@ describe('Model.Problem', () => {
expect(pdoc.owner).toStrictEqual(UID); expect(pdoc.owner).toStrictEqual(UID);
expect(pdoc.docId).toStrictEqual(pid); expect(pdoc.docId).toStrictEqual(pid);
expect(pdoc.pid).toStrictEqual(PNAME); expect(pdoc.pid).toStrictEqual(PNAME);
pdoc = await problem.get(DOMAIN_ID, pid); const pdoc1 = await problem.get(DOMAIN_ID, pid);
expect(pdoc.domainId).toStrictEqual(DOMAIN_ID); expect(pdoc1).toStrictEqual(pdoc);
expect(pdoc.title).toStrictEqual(TITLE);
expect(pdoc.content).toStrictEqual(CONTENT);
expect(pdoc.owner).toStrictEqual(UID);
expect(pdoc.docId).toStrictEqual(pid);
expect(pdoc.pid).toStrictEqual(PNAME);
const pdocs = await problem.getMulti(DOMAIN_ID, {}).toArray(); const pdocs = await problem.getMulti(DOMAIN_ID, {}).toArray();
expect(pdocs.length).toStrictEqual(1); expect(pdocs.length).toStrictEqual(1);
expect(pdocs[0].docId).toStrictEqual(pid); expect(pdocs[0].docId).toStrictEqual(pid);
+1 -1
View File
@@ -12,7 +12,7 @@ declare module 'hydrooj' {
export async function postInit() { export async function postInit() {
const { system, token } = global.Hydro.model; const { system, token } = global.Hydro.model;
const [url, accessToken] = await system.getMany(['login-with-qq.url', 'login-with-qq.token']); const [url, accessToken] = system.getMany(['login-with-qq.url', 'login-with-qq.token']);
if (!url) return; if (!url) return;
const headers: Record<string, string> = {}; const headers: Record<string, string> = {};
if (accessToken) headers.Authorization = `Bearer ${accessToken}`; if (accessToken) headers.Authorization = `Bearer ${accessToken}`;
+1 -1
View File
@@ -18,6 +18,6 @@
}, },
"dependencies": { "dependencies": {
"js-yaml": "^3.14.0", "js-yaml": "^3.14.0",
"mongodb": "^3.6.1" "mongodb": "^3.6.2"
} }
} }