mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
remove server.log setting item
This commit is contained in:
1 parent
e62e7b49a3
commit
ee78271a84
27 files changed
+148
-103
No files matched your search
+9
-6
@@ -1,21 +1,24 @@
|
|||||||
/* eslint-disable func-names */
|
/* eslint-disable func-names */
|
||||||
const { isClass } = require('./utils');
|
import { isClass } from './utils';
|
||||||
|
|
||||||
interface IHydroError {
|
interface IHydroError {
|
||||||
new(...args: any[]): HydroError
|
new(...args: any[]): HydroError
|
||||||
}
|
}
|
||||||
|
|
||||||
const Err = (name: string, ...info: Array<IHydroError | Function | string | number>) => {
|
function isHydroError(item: any): item is IHydroError {
|
||||||
|
return isClass(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Err = (name: string, ...info: Array<IHydroError | (() => string) | string | number>) => {
|
||||||
let Class: IHydroError;
|
let Class: IHydroError;
|
||||||
let msg;
|
let msg: () => string;
|
||||||
let code;
|
let code: number;
|
||||||
for (const item of info) {
|
for (const item of info) {
|
||||||
if (typeof item === 'number') {
|
if (typeof item === 'number') {
|
||||||
code = item;
|
code = item;
|
||||||
} else if (typeof item === 'string') {
|
} else if (typeof item === 'string') {
|
||||||
msg = function () { return item; };
|
msg = function () { return item; };
|
||||||
} else if (isClass(item)) {
|
} else if (isHydroError(item)) {
|
||||||
// @ts-ignore
|
|
||||||
Class = item;
|
Class = item;
|
||||||
} else if (typeof item === 'function') {
|
} else if (typeof item === 'function') {
|
||||||
msg = item;
|
msg = item;
|
||||||
|
|||||||
@@ -106,7 +106,9 @@ class DomainUserHandler extends ManageHandler {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async postSetUser({ domainId, uid, role }) {
|
@param('uid', Types.Int)
|
||||||
|
@param('role', Types.String)
|
||||||
|
async postSetUser(domainId: string, uid: number, role: string) {
|
||||||
await domain.setUserRole(domainId, uid, role);
|
await domain.setUserRole(domainId, uid, role);
|
||||||
this.back();
|
this.back();
|
||||||
}
|
}
|
||||||
@@ -161,7 +163,8 @@ class DomainRoleHandler extends ManageHandler {
|
|||||||
this.response.body = { roles, domain: this.domain, path };
|
this.response.body = { roles, domain: this.domain, path };
|
||||||
}
|
}
|
||||||
|
|
||||||
async postAdd({ domainId, role }) {
|
@param('role', Types.String)
|
||||||
|
async postAdd(domainId: string, role: string) {
|
||||||
const roles = await domain.getRoles(this.domain);
|
const roles = await domain.getRoles(this.domain);
|
||||||
const rdict: any = {};
|
const rdict: any = {};
|
||||||
for (const r of roles) rdict[r._id] = r.perm;
|
for (const r of roles) rdict[r._id] = r.perm;
|
||||||
@@ -183,7 +186,7 @@ class DomainRoleHandler extends ManageHandler {
|
|||||||
|
|
||||||
class DomainSearchHandler extends Handler {
|
class DomainSearchHandler extends Handler {
|
||||||
@param('q', Types.String)
|
@param('q', Types.String)
|
||||||
async get(q: string) {
|
async get(domainId: string, q: string) {
|
||||||
const ddocs = await domain.getPrefixSearch(q, 20);
|
const ddocs = await domain.getPrefixSearch(q, 20);
|
||||||
for (let i = 0; i < ddocs.length; i++) {
|
for (let i = 0; i < ddocs.length; i++) {
|
||||||
ddocs[i].gravatar = ddocs[i].gravatar ? gravatar(ddocs[i].gravatar) : '/img/team_avatar.png';
|
ddocs[i].gravatar = ddocs[i].gravatar ? gravatar(ddocs[i].gravatar) : '/img/team_avatar.png';
|
||||||
|
|||||||
@@ -150,9 +150,9 @@ class HomeSecurityHandler extends Handler {
|
|||||||
|
|
||||||
@param('currentPassword', Types.String)
|
@param('currentPassword', Types.String)
|
||||||
@param('mail', Types.String, isEmail)
|
@param('mail', Types.String, isEmail)
|
||||||
async postChangeMail(domainId: string, currentPassword: string, email: string) {
|
async postChangeMail(domainId: string, current: string, email: string) {
|
||||||
this.limitRate('send_mail', 3600, 30);
|
this.limitRate('send_mail', 3600, 30);
|
||||||
this.user.checkPassword(currentPassword);
|
this.user.checkPassword(current);
|
||||||
const udoc = await user.getByEmail(domainId, email);
|
const udoc = await user.getByEmail(domainId, email);
|
||||||
if (udoc) throw new UserAlreadyExistError(email);
|
if (udoc) throw new UserAlreadyExistError(email);
|
||||||
const [code] = await token.add(
|
const [code] = await token.add(
|
||||||
|
|||||||
@@ -158,13 +158,4 @@ export async function apply() {
|
|||||||
Route('ui', '/extra.css', UiSettingsHandler);
|
Route('ui', '/extra.css', UiSettingsHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply.updateStatus = function updateStatus(args) {
|
|
||||||
args.type = 'judger';
|
|
||||||
return coll.updateOne(
|
|
||||||
{ mid: args.mid, type: 'judger' },
|
|
||||||
{ $set: args },
|
|
||||||
{ upsert: true },
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
global.Hydro.handler.misc = apply;
|
global.Hydro.handler.misc = apply;
|
||||||
@@ -15,8 +15,8 @@ import { sendMail } from '../lib/mail';
|
|||||||
import * as misc from '../lib/misc';
|
import * as misc from '../lib/misc';
|
||||||
import {
|
import {
|
||||||
UserAlreadyExistError, InvalidTokenError, VerifyPasswordError,
|
UserAlreadyExistError, InvalidTokenError, VerifyPasswordError,
|
||||||
UserNotFoundError, LoginError, SystemError,
|
UserNotFoundError, SystemError, BlacklistedError,
|
||||||
BlacklistedError, UserFacingError,
|
UserFacingError,
|
||||||
} from '../error';
|
} from '../error';
|
||||||
|
|
||||||
class UserLoginHandler extends Handler {
|
class UserLoginHandler extends Handler {
|
||||||
@@ -35,7 +35,7 @@ class UserLoginHandler extends Handler {
|
|||||||
@param('rememberme', Types.Boolean, true)
|
@param('rememberme', Types.Boolean, true)
|
||||||
async post(domainId: string, uname: string, password: string, rememberme = false) {
|
async post(domainId: string, uname: string, password: string, rememberme = false) {
|
||||||
const udoc = await user.getByUname(domainId, uname);
|
const udoc = await user.getByUname(domainId, uname);
|
||||||
if (!udoc) throw new LoginError(uname);
|
if (!udoc) throw new UserNotFoundError(uname);
|
||||||
udoc.checkPassword(password);
|
udoc.checkPassword(password);
|
||||||
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
|
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
|
||||||
if (udoc.priv === PRIV.PRIV_NONE) throw new BlacklistedError(uname);
|
if (udoc.priv === PRIV.PRIV_NONE) throw new BlacklistedError(uname);
|
||||||
|
|||||||
+36
-4
@@ -141,7 +141,7 @@ export interface Pdoc {
|
|||||||
acMsg?: string,
|
acMsg?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Pdict = Dictionary<Pdoc>;
|
export type Pdict = NumericDictionary<Pdoc>;
|
||||||
|
|
||||||
export interface TestCase {
|
export interface TestCase {
|
||||||
time: number,
|
time: number,
|
||||||
@@ -245,7 +245,38 @@ export interface Bdoc {
|
|||||||
expireAt: Date,
|
expireAt: Date,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ContestStat extends Dictionary<any> {
|
// Discussion
|
||||||
|
export interface Ddoc {
|
||||||
|
_id: ObjectID,
|
||||||
|
docType: number,
|
||||||
|
docId: ObjectID,
|
||||||
|
owner: number,
|
||||||
|
title: string,
|
||||||
|
content: string,
|
||||||
|
ip: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discussion reply
|
||||||
|
export interface Drdoc {
|
||||||
|
_id: ObjectID,
|
||||||
|
docType: number,
|
||||||
|
docId: ObjectID,
|
||||||
|
parentType: number,
|
||||||
|
parentId: ObjectID,
|
||||||
|
owner: number,
|
||||||
|
ip: string,
|
||||||
|
reply: Drrdoc[],
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discussion Tail Reply
|
||||||
|
export interface Drrdoc {
|
||||||
|
_id: ObjectID,
|
||||||
|
owner: number,
|
||||||
|
content: string,
|
||||||
|
ip: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContestStat extends Dictionary<any> {
|
||||||
detail: any,
|
detail: any,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,6 +361,7 @@ declare global {
|
|||||||
gridfs: GridFSBucket,
|
gridfs: GridFSBucket,
|
||||||
monitor: typeof import('./service/monitor'),
|
monitor: typeof import('./service/monitor'),
|
||||||
server: typeof import('./service/server'),
|
server: typeof import('./service/server'),
|
||||||
|
[key: string]: any,
|
||||||
},
|
},
|
||||||
lib: {
|
lib: {
|
||||||
download: typeof import('./lib/download').default,
|
download: typeof import('./lib/download').default,
|
||||||
@@ -363,9 +395,9 @@ declare global {
|
|||||||
},
|
},
|
||||||
error: typeof import('./error'),
|
error: typeof import('./error'),
|
||||||
locales: Dict<Dict<string>>,
|
locales: Dict<Dict<string>>,
|
||||||
postInit: Function[],
|
postInit: Array<() => Promise<any>>,
|
||||||
},
|
},
|
||||||
onDestory: Function[],
|
onDestory: Array<() => void>,
|
||||||
addons: string[],
|
addons: string[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ function decodeJWT(idToken: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export function decode(idToken: string) {
|
export function decode(idToken: string) {
|
||||||
const decodedJWT = decodeJWT(idToken);
|
const decodedJWT = decodeJWT(idToken);
|
||||||
return decodedJWT.payload;
|
return decodedJWT.payload;
|
||||||
|
|||||||
@@ -6,12 +6,6 @@ function wrap(func: Function, type: string) {
|
|||||||
func(...args);
|
func(...args);
|
||||||
if (global.Hydro.model.message) {
|
if (global.Hydro.model.message) {
|
||||||
try {
|
try {
|
||||||
for (let i = 0; i <= args.length; i++) {
|
|
||||||
if (args[i] instanceof Error) {
|
|
||||||
// js-yaml cannot dump [object Error]
|
|
||||||
args[i] = `${args[i].message}\n${args[i].stack}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
global.Hydro.model.message.send(1, 1, serialize({ time, type, args }), 0);
|
global.Hydro.model.message.send(1, 1, serialize({ time, type, args }), 0);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
func(e.message);
|
func(e.message);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import nodemailer from 'nodemailer';
|
import nodemailer from 'nodemailer';
|
||||||
import { SendMailError } from '../error';
|
import { SendMailError } from '../error';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export async function sendMail(to: string, subject: string, text: string, html: string) {
|
export async function sendMail(to: string, subject: string, text: string, html: string) {
|
||||||
let t: unknown;
|
let t: unknown;
|
||||||
try {
|
try {
|
||||||
|
|||||||
+12
-11
@@ -1,19 +1,20 @@
|
|||||||
import AnsiUp from 'ansi_up';
|
import AnsiUp from 'ansi_up';
|
||||||
|
import { ObjectID } from 'mongodb';
|
||||||
import md5 from './md5';
|
import md5 from './md5';
|
||||||
|
|
||||||
const AU = new AnsiUp();
|
const AU = new AnsiUp();
|
||||||
|
|
||||||
export function ansiToHtml(str) {
|
export function ansiToHtml(str: string) {
|
||||||
return AU.ansi_to_html(str);
|
return AU.ansi_to_html(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function gravatar(email, s = 32) {
|
export function gravatar(email: string, s = 32) {
|
||||||
return `//gravatar.loli.net/avatar/${md5((email || '').toString().trim().toLowerCase())}?d=mm&s=${s}`;
|
return `//gravatar.loli.net/avatar/${md5((email || '').toString().trim().toLowerCase())}?d=mm&s=${s}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function datetimeSpan(dt, relative = true, format = '%Y-%m-%d %H:%M:%S') {
|
export function datetimeSpan(dt: Date | ObjectID, relative = true, format = '%Y-%m-%d %H:%M:%S') {
|
||||||
if (!dt) return 'DATETIME_SPAN_ERROR';
|
if (!dt) return 'DATETIME_SPAN_ERROR';
|
||||||
if (dt.generationTime) dt = new Date(dt.generationTime * 1000);
|
if (dt instanceof ObjectID) dt = new Date(dt.generationTime * 1000);
|
||||||
else if (typeof dt === 'number' || typeof dt === 'string') dt = new Date(dt);
|
else if (typeof dt === 'number' || typeof dt === 'string') dt = new Date(dt);
|
||||||
return '<span class="time{0}" data-timestamp="{1}">{2}</span>'.format(
|
return '<span class="time{0}" data-timestamp="{1}">{2}</span>'.format(
|
||||||
relative ? ' relative' : '',
|
relative ? ' relative' : '',
|
||||||
@@ -22,9 +23,10 @@ export function datetimeSpan(dt, relative = true, format = '%Y-%m-%d %H:%M:%S')
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* paginate(page, numPages) {
|
export function* paginate(page: number, numPages: number) {
|
||||||
const radius = 2; let first; let
|
const radius = 2;
|
||||||
last;
|
let first: number;
|
||||||
|
let last: number;
|
||||||
if (page > 1) {
|
if (page > 1) {
|
||||||
yield ['first', 1];
|
yield ['first', 1];
|
||||||
yield ['previous', page - 1];
|
yield ['previous', page - 1];
|
||||||
@@ -45,7 +47,7 @@ export function* paginate(page, numPages) {
|
|||||||
yield ['last', numPages];
|
yield ['last', numPages];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function size(s, base = 1) {
|
export function size(s: number, base = 1) {
|
||||||
s *= base;
|
s *= base;
|
||||||
const unit = 1024;
|
const unit = 1024;
|
||||||
const unitNames = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
const unitNames = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
||||||
@@ -53,12 +55,11 @@ export function size(s, base = 1) {
|
|||||||
if (s < unit) return '{0} {1}'.format(Math.round(s * 10) / 10, unitName);
|
if (s < unit) return '{0} {1}'.format(Math.round(s * 10) / 10, unitName);
|
||||||
s /= unit;
|
s /= unit;
|
||||||
}
|
}
|
||||||
return '{0} {1}'.format(Math.round(s * unit), unitNames[unitNames.length - 1]);
|
return `${Math.round(s * unit)} ${unitNames[unitNames.length - 1]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _digit2(number: number) {
|
function _digit2(number: number) {
|
||||||
if (number < 10) return `0${number}`;
|
return number < 10 ? `0${number}` : number.toString();
|
||||||
return number.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatSeconds(_seconds = '0') {
|
export function formatSeconds(_seconds = '0') {
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ const Checker = (perm: bigint, priv: number, checker: Function = trueChecker) =>
|
|||||||
|
|
||||||
const Item = (
|
const Item = (
|
||||||
name: string, args: any, prefix: string,
|
name: string, args: any, prefix: string,
|
||||||
...permPrivChecker: Array<number | bigint | Function | Array<bigint | string>>
|
...permPrivChecker: Array<number | bigint | Function>
|
||||||
) => {
|
) => {
|
||||||
let _priv: number;
|
let _priv: number;
|
||||||
let _perm: bigint;
|
let _perm: bigint;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import { Cursor } from 'mongodb';
|
||||||
import { ValidationError } from '../error';
|
import { ValidationError } from '../error';
|
||||||
|
|
||||||
async function paginate(cursor: import('mongodb').Cursor, page: number, pageSize: number): Promise<[any[], number, number]> {
|
export default async function paginate(
|
||||||
|
cursor: Cursor, page: number, pageSize: number,
|
||||||
|
): Promise<[any[], number, number]> {
|
||||||
if (page <= 0) throw new ValidationError('page');
|
if (page <= 0) throw new ValidationError('page');
|
||||||
const [count, pageDocs] = await Promise.all([
|
const [count, pageDocs] = await Promise.all([
|
||||||
cursor.count(),
|
cursor.count(),
|
||||||
@@ -11,4 +14,3 @@ async function paginate(cursor: import('mongodb').Cursor, page: number, pageSize
|
|||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.lib.paginate = paginate;
|
global.Hydro.lib.paginate = paginate;
|
||||||
export default paginate;
|
|
||||||
+11
-8
@@ -1,12 +1,16 @@
|
|||||||
class User {
|
class User {
|
||||||
rank: any;
|
rank: number;
|
||||||
|
|
||||||
old: any;
|
old: number;
|
||||||
|
|
||||||
seed: number;
|
seed: number;
|
||||||
|
|
||||||
uid: number;
|
uid: number;
|
||||||
|
|
||||||
|
delta?: number;
|
||||||
|
|
||||||
|
new: number;
|
||||||
|
|
||||||
constructor(rank: number, old: number, uid = 0) {
|
constructor(rank: number, old: number, uid = 0) {
|
||||||
this.rank = rank;
|
this.rank = rank;
|
||||||
this.old = old;
|
this.old = old;
|
||||||
@@ -16,7 +20,7 @@ class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class RatingCalculator {
|
class RatingCalculator {
|
||||||
users: any;
|
users: User[];
|
||||||
|
|
||||||
constructor(users) {
|
constructor(users) {
|
||||||
this.users = [];
|
this.users = [];
|
||||||
@@ -26,11 +30,11 @@ class RatingCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line class-methods-use-this
|
// eslint-disable-next-line class-methods-use-this
|
||||||
calP(a, b) {
|
calP(a: User, b: User) {
|
||||||
return 1 / (1 + 10 ** ((b.old - a.old) / 400));
|
return 1 / (1 + 10 ** ((b.old - a.old) / 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
getExSeed(rating, ownUser) {
|
getExSeed(rating: number, ownUser: User) {
|
||||||
const exUser = new User(0.0, rating);
|
const exUser = new User(0.0, rating);
|
||||||
let result = 1;
|
let result = 1;
|
||||||
for (const user of this.users) {
|
for (const user of this.users) {
|
||||||
@@ -39,7 +43,7 @@ class RatingCalculator {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
calRating(rank, user) {
|
calRating(rank: number, user: User) {
|
||||||
let left = 1;
|
let left = 1;
|
||||||
let right = 8000;
|
let right = 8000;
|
||||||
while (right - left > 1) {
|
while (right - left > 1) {
|
||||||
@@ -101,10 +105,9 @@ interface RatingOutputUser {
|
|||||||
uid: number,
|
uid: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculate(users: RatingInputUser[]): RatingOutputUser[] {
|
export default function calculate(users: RatingInputUser[]): RatingOutputUser[] {
|
||||||
const calculator = new RatingCalculator(users);
|
const calculator = new RatingCalculator(users);
|
||||||
return calculator.calculate();
|
return calculator.calculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.lib.rating = calculate;
|
global.Hydro.lib.rating = calculate;
|
||||||
export default calculate;
|
|
||||||
+2
-16
@@ -67,22 +67,8 @@ function _validate(scheme: any, arg: any, base: string): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function descriptor(scheme: any): Function {
|
export function validate(scheme: any, arg: any) {
|
||||||
return function desc(target: any, name: string, obj: any) {
|
return _validate(scheme, arg, '');
|
||||||
const originalMethod = obj.value;
|
|
||||||
obj.value = function func(...args: any[]) {
|
|
||||||
_validate(scheme, args[0], '');
|
|
||||||
return originalMethod.call(this, ...args);
|
|
||||||
};
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function validate(scheme: any): Function;
|
|
||||||
export function validate(scheme: any, arg: any): void;
|
|
||||||
export function validate(...args: any[]): any {
|
|
||||||
if (args.length === 1) return descriptor(args[0]);
|
|
||||||
return _validate(args[0], args[1], '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isTitle = (s) => s && s.length < 64;
|
export const isTitle = (s) => s && s.length < 64;
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ import { Bdoc } from '../interface';
|
|||||||
const coll = db.collection('blacklist');
|
const coll = db.collection('blacklist');
|
||||||
|
|
||||||
export async function add(ip: string): Promise<Bdoc> {
|
export async function add(ip: string): Promise<Bdoc> {
|
||||||
|
/**
|
||||||
|
* Add a ip into blacklist.
|
||||||
|
* @param {string} ip
|
||||||
|
* @returns {Promise<Bdoc>}
|
||||||
|
*/
|
||||||
const expireAt = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000);
|
const expireAt = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000);
|
||||||
const res = await coll.findOneAndUpdate(
|
const res = await coll.findOneAndUpdate(
|
||||||
{ _id: ip },
|
{ _id: ip },
|
||||||
@@ -13,7 +18,12 @@ export async function add(ip: string): Promise<Bdoc> {
|
|||||||
return res.value;
|
return res.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get(ip: string): Promise<Bdoc> {
|
export function get(ip: string): Promise<Bdoc | null> {
|
||||||
|
/**
|
||||||
|
* Get a ip, return null if not.
|
||||||
|
* @param {string} ip
|
||||||
|
* @returns {Promise<Bdoc>}
|
||||||
|
*/
|
||||||
return coll.findOne({ _id: ip });
|
return coll.findOne({ _id: ip });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-10
@@ -5,6 +5,7 @@ import * as training from './training';
|
|||||||
import * as document from './document';
|
import * as document from './document';
|
||||||
import { PERM } from './builtin';
|
import { PERM } from './builtin';
|
||||||
import { DocumentNotFoundError } from '../error';
|
import { DocumentNotFoundError } from '../error';
|
||||||
|
import { Ddoc, Drdoc, Drrdoc } from '../interface';
|
||||||
|
|
||||||
export const typeDisplay = {
|
export const typeDisplay = {
|
||||||
[document.TYPE_PROBLEM]: 'problem',
|
[document.TYPE_PROBLEM]: 'problem',
|
||||||
@@ -18,7 +19,7 @@ export function add(
|
|||||||
domainId: string, parentType: number, parentId: ObjectID | number | string,
|
domainId: string, parentType: number, parentId: ObjectID | number | string,
|
||||||
owner: number, title: string, content: string,
|
owner: number, title: string, content: string,
|
||||||
ip: string | null = null, highlight: boolean = false,
|
ip: string | null = null, highlight: boolean = false,
|
||||||
) {
|
): Promise<ObjectID> {
|
||||||
return document.add(
|
return document.add(
|
||||||
domainId, content, owner, document.TYPE_DISCUSSION,
|
domainId, content, owner, document.TYPE_DISCUSSION,
|
||||||
null, parentType, parentId,
|
null, parentType, parentId,
|
||||||
@@ -33,14 +34,14 @@ export function add(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get(domainId: string, did: ObjectID) {
|
export function get(domainId: string, did: ObjectID): Promise<Ddoc | null> {
|
||||||
return document.get(domainId, document.TYPE_DISCUSSION, did);
|
return document.get(domainId, document.TYPE_DISCUSSION, did);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function edit(
|
export function edit(
|
||||||
domainId: string, did: ObjectID,
|
domainId: string, did: ObjectID,
|
||||||
title: string, content: string, highlight: boolean,
|
title: string, content: string, highlight: boolean,
|
||||||
) {
|
): Promise<Ddoc | null> {
|
||||||
return document.set(domainId, document.TYPE_DISCUSSION, did, { title, content, highlight });
|
return document.set(domainId, document.TYPE_DISCUSSION, did, { title, content, highlight });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ export function getMulti(domainId: string, query: any = {}) {
|
|||||||
export async function addReply(
|
export async function addReply(
|
||||||
domainId: string, did: ObjectID, owner: number,
|
domainId: string, did: ObjectID, owner: number,
|
||||||
content: string, ip: string,
|
content: string, ip: string,
|
||||||
) {
|
): Promise<Drdoc> {
|
||||||
const [drdoc] = await Promise.all([
|
const [drdoc] = await Promise.all([
|
||||||
document.add(
|
document.add(
|
||||||
domainId, content, owner, document.TYPE_DISCUSSION_REPLY,
|
domainId, content, owner, document.TYPE_DISCUSSION_REPLY,
|
||||||
@@ -76,11 +77,13 @@ export async function addReply(
|
|||||||
return drdoc;
|
return drdoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getReply(domainId: string, drid: ObjectID) {
|
export function getReply(domainId: string, drid: ObjectID): Promise<Drdoc | null> {
|
||||||
return document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid);
|
return document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function editReply(domainId: string, drid: ObjectID, content: string) {
|
export async function editReply(
|
||||||
|
domainId: string, drid: ObjectID, content: string,
|
||||||
|
): Promise<Drdoc | null> {
|
||||||
return document.set(domainId, document.TYPE_DISCUSSION_REPLY, drid, { content });
|
return document.set(domainId, document.TYPE_DISCUSSION_REPLY, drid, { content });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,14 +103,14 @@ export function getMultiReply(domainId: string, did: ObjectID) {
|
|||||||
).sort('_id', -1);
|
).sort('_id', -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getListReply(domainId: string, did: ObjectID) {
|
export function getListReply(domainId: string, did: ObjectID): Promise<Drdoc[]> {
|
||||||
return getMultiReply(domainId, did).toArray();
|
return getMultiReply(domainId, did).toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addTailReply(
|
export async function addTailReply(
|
||||||
domainId: string, drid: ObjectID,
|
domainId: string, drid: ObjectID,
|
||||||
owner: number, content: string, ip: string,
|
owner: number, content: string, ip: string,
|
||||||
) {
|
): Promise<[Drdoc, ObjectID]> {
|
||||||
let drdoc = await document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid);
|
let drdoc = await document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid);
|
||||||
const sid = new ObjectID();
|
const sid = new ObjectID();
|
||||||
[drdoc] = await Promise.all([
|
[drdoc] = await Promise.all([
|
||||||
@@ -117,11 +120,16 @@ export async function addTailReply(
|
|||||||
return [drdoc, sid];
|
return [drdoc, sid];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTailReply(domainId: string, drid: ObjectID, drrid: ObjectID) {
|
export function getTailReply(
|
||||||
|
domainId: string, drid: ObjectID, drrid: ObjectID,
|
||||||
|
): Promise<[Drdoc, Drrdoc] | [null, null]> {
|
||||||
|
// @ts-ignore
|
||||||
return document.getSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid);
|
return document.getSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editTailReply(domainId: string, drid: ObjectID, drrid: ObjectID, content: string) {
|
export function editTailReply(
|
||||||
|
domainId: string, drid: ObjectID, drrid: ObjectID, content: string,
|
||||||
|
): Promise<Drrdoc> {
|
||||||
return document.setSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid, { content });
|
return document.setSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid, { content });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export async function send(
|
|||||||
return mdoc;
|
return mdoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get(_id: ObjectID): Promise<Mdoc> {
|
export async function get(_id: ObjectID): Promise<Mdoc | null> {
|
||||||
return await coll.findOne({ _id });
|
return await coll.findOne({ _id });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ export async function getMany(query: any, sort: any, page: number, limit: number
|
|||||||
.toArray();
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setFlag(messageId: ObjectID, flag: number) {
|
export async function setFlag(messageId: ObjectID, flag: number): Promise<Mdoc | null> {
|
||||||
const result = await coll.findOneAndUpdate(
|
const result = await coll.findOneAndUpdate(
|
||||||
{ _id: messageId },
|
{ _id: messageId },
|
||||||
{ $bit: { flag: { xor: flag } } },
|
{ $bit: { flag: { xor: flag } } },
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export function edit(domainId: string, _id: number, $set: any): Promise<Pdoc> {
|
|||||||
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) {
|
export function inc(domainId: string, _id: number, field: string, n: number): Promise<Pdoc> {
|
||||||
return document.inc(domainId, document.TYPE_PROBLEM, _id, field, n);
|
return document.inc(domainId, document.TYPE_PROBLEM, _id, field, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ export function count(domainId: string, query: any) {
|
|||||||
return document.count(domainId, document.TYPE_PROBLEM, query);
|
return document.count(domainId, document.TYPE_PROBLEM, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function random(domainId: string, query: any) {
|
export async function random(domainId: string, query: any): Promise<string | null> {
|
||||||
const cursor = document.getMulti(domainId, document.TYPE_PROBLEM, query);
|
const cursor = document.getMulti(domainId, document.TYPE_PROBLEM, query);
|
||||||
const pcount = await cursor.count();
|
const pcount = await cursor.count();
|
||||||
if (pcount) {
|
if (pcount) {
|
||||||
@@ -100,16 +100,18 @@ export async function getList(
|
|||||||
): Promise<Pdict> {
|
): Promise<Pdict> {
|
||||||
pids = Array.from(new Set(pids));
|
pids = Array.from(new Set(pids));
|
||||||
const r = {};
|
const r = {};
|
||||||
|
const l = {};
|
||||||
const q: any = { $or: [{ docId: { $in: pids } }, { pid: { $in: pids } }] };
|
const q: any = { $or: [{ docId: { $in: pids } }, { pid: { $in: pids } }] };
|
||||||
if (!getHidden) q.hidden = false;
|
if (!getHidden) q.hidden = false;
|
||||||
const pdocs = await document.getMulti(domainId, document.TYPE_PROBLEM, q).toArray();
|
const pdocs = await document.getMulti(domainId, document.TYPE_PROBLEM, q).toArray();
|
||||||
for (const pdoc of pdocs) {
|
for (const pdoc of pdocs) {
|
||||||
r[pdoc.docId] = pdoc;
|
r[pdoc.docId] = pdoc;
|
||||||
r[pdoc.pid] = pdoc;
|
l[pdoc.pid] = pdoc;
|
||||||
}
|
}
|
||||||
|
// TODO enhance
|
||||||
if (pdocs.length !== pids.length) {
|
if (pdocs.length !== pids.length) {
|
||||||
for (const pid of pids) {
|
for (const pid of pids) {
|
||||||
if (!r[pid]) {
|
if (!(r[pid] || l[pid])) {
|
||||||
if (doThrow) {
|
if (doThrow) {
|
||||||
throw new ProblemNotFoundError(domainId, pid);
|
throw new ProblemNotFoundError(domainId, pid);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import _ from 'lodash';
|
|
||||||
import yaml from 'js-yaml';
|
|
||||||
import { ObjectID } from 'mongodb';
|
import { ObjectID } from 'mongodb';
|
||||||
import { STATUS } from './builtin';
|
import { STATUS } from './builtin';
|
||||||
import * as task from './task';
|
import * as task from './task';
|
||||||
|
|||||||
@@ -121,7 +121,6 @@ SystemSetting(
|
|||||||
Setting('setting_server', 'server.cdn', null, '/', 'text', 'CDN Prefix', 'Ends with /'),
|
Setting('setting_server', 'server.cdn', null, '/', 'text', 'CDN Prefix', 'Ends with /'),
|
||||||
Setting('setting_server', 'server.port', null, 8888, 'number', 'Server Port'),
|
Setting('setting_server', 'server.port', null, 8888, 'number', 'Server Port'),
|
||||||
Setting('setting_server', 'server.xff', null, null, 'text', 'IP Header', 'e.g. x-forwarded-for (lowercase)'),
|
Setting('setting_server', 'server.xff', null, null, 'text', 'IP Header', 'e.g. x-forwarded-for (lowercase)'),
|
||||||
Setting('setting_server', 'server.log', null, false, 'boolean', 'Disable Access Log'),
|
|
||||||
Setting('setting_session', 'session.keys', null, [String.random(32)], 'text', 'session.keys', null, FLAG_DISABLED | FLAG_HIDDEN),
|
Setting('setting_session', 'session.keys', null, [String.random(32)], 'text', 'session.keys', null, FLAG_DISABLED | FLAG_HIDDEN),
|
||||||
Setting('setting_session', 'session.secure', null, false, 'boolean', 'session.secure'),
|
Setting('setting_session', 'session.secure', null, false, 'boolean', 'session.secure'),
|
||||||
Setting('setting_session', 'session.saved_expire_seconds', null, 3600 * 24 * 30, 'number', 'Saved session expire seconds'),
|
Setting('setting_session', 'session.saved_expire_seconds', null, 3600 * 24 * 30, 'number', 'Saved session expire seconds'),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { ValidationError } from '../error';
|
|
||||||
import * as db from '../service/db';
|
import * as db from '../service/db';
|
||||||
|
|
||||||
const coll = db.collection('token');
|
const coll = db.collection('token');
|
||||||
|
|||||||
+8
-1
@@ -8,5 +8,12 @@ export default function load() {
|
|||||||
if (!fs.existsSync(f)) f = path.resolve(os.homedir(), '.config', 'hydro', 'config.json');
|
if (!fs.existsSync(f)) f = path.resolve(os.homedir(), '.config', 'hydro', 'config.json');
|
||||||
if (!fs.existsSync(f)) f = path.resolve(os.homedir(), '.hydro', 'config.json');
|
if (!fs.existsSync(f)) f = path.resolve(os.homedir(), '.hydro', 'config.json');
|
||||||
if (!fs.existsSync(f)) f = path.resolve('/config/config.json');
|
if (!fs.existsSync(f)) f = path.resolve('/config/config.json');
|
||||||
return JSON.parse(fs.readFileSync(f).toString());
|
let result: any = {};
|
||||||
|
try {
|
||||||
|
result = JSON.parse(fs.readFileSync(f).toString());
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Cannot read config file', e);
|
||||||
|
result = {};
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ type ND = NumericDictionary<number>
|
|||||||
function calc(udict: ND, rankedDocs: [number, number][]) {
|
function calc(udict: ND, rankedDocs: [number, number][]) {
|
||||||
const users = [];
|
const users = [];
|
||||||
for (const [rank, uid] of rankedDocs) {
|
for (const [rank, uid] of rankedDocs) {
|
||||||
users.push({ uid, rank, old: users[uid] || 1500 });
|
users.push({ uid, rank, old: udict[uid] || 1500 });
|
||||||
}
|
}
|
||||||
const rated = rating(users);
|
const rated = rating(users);
|
||||||
for (const udoc of rated) {
|
for (const udoc of rated) {
|
||||||
|
|||||||
@@ -13,6 +13,15 @@ export async function update() {
|
|||||||
global.Hydro.stat.reqCount = 0;
|
global.Hydro.stat.reqCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function updateJudger(args) {
|
||||||
|
args.type = 'judger';
|
||||||
|
return coll.updateOne(
|
||||||
|
{ mid: args.mid, type: 'judger' },
|
||||||
|
{ $set: args },
|
||||||
|
{ upsert: true },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
global.Hydro.postInit.push(
|
global.Hydro.postInit.push(
|
||||||
async () => {
|
async () => {
|
||||||
const info = await sysinfo.get();
|
const info = await sysinfo.get();
|
||||||
@@ -25,4 +34,4 @@ global.Hydro.postInit.push(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
global.Hydro.service.monitor = { update };
|
global.Hydro.service.monitor = { update, updateJudger };
|
||||||
@@ -743,8 +743,8 @@ export function Connection(
|
|||||||
|
|
||||||
// TODO use postInit?
|
// TODO use postInit?
|
||||||
export async function start() {
|
export async function start() {
|
||||||
const [disableLog, port] = await system.getMany(['server.log', 'server.port']);
|
const port = await system.get('server.port');
|
||||||
if (!disableLog) {
|
if (!argv.debug) {
|
||||||
app.use(morgan(':method :url :status :res[content-length] - :response-time ms', {
|
app.use(morgan(':method :url :status :res[content-length] - :response-time ms', {
|
||||||
skip: (req, res) => res.hasHeader('nolog'),
|
skip: (req, res) => res.hasHeader('nolog'),
|
||||||
}));
|
}));
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { serialize } from 'v8';
|
|
||||||
import cluster from 'cluster';
|
import cluster from 'cluster';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as superagent from 'superagent';
|
import * as superagent from 'superagent';
|
||||||
|
import serialize from 'serialize-javascript';
|
||||||
import proxy from 'superagent-proxy';
|
import proxy from 'superagent-proxy';
|
||||||
import Lru from 'lru-cache';
|
import Lru from 'lru-cache';
|
||||||
|
|
||||||
@@ -147,13 +147,13 @@ const TIME_UNITS = { '': 1000, m: 1, u: 0.001 };
|
|||||||
const MEMORY_RE = /^([0-9]+(?:\.[0-9]*)?)([kmg])b?$/i;
|
const MEMORY_RE = /^([0-9]+(?:\.[0-9]*)?)([kmg])b?$/i;
|
||||||
const MEMORY_UNITS = { k: 0.1, m: 1, g: 1024 };
|
const MEMORY_UNITS = { k: 0.1, m: 1, g: 1024 };
|
||||||
|
|
||||||
export function parseTimeMS(str) {
|
export function parseTimeMS(str: string) {
|
||||||
const match = TIME_RE.exec(str);
|
const match = TIME_RE.exec(str);
|
||||||
if (!match) throw new Error(`${str} error parsing time`);
|
if (!match) throw new Error(`${str} error parsing time`);
|
||||||
return Math.floor(parseFloat(match[1]) * TIME_UNITS[match[2]]);
|
return Math.floor(parseFloat(match[1]) * TIME_UNITS[match[2]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseMemoryMB(str) {
|
export function parseMemoryMB(str: string) {
|
||||||
const match = MEMORY_RE.exec(str);
|
const match = MEMORY_RE.exec(str);
|
||||||
if (!match) throw new Error(`${str} error parsing memory`);
|
if (!match) throw new Error(`${str} error parsing memory`);
|
||||||
return Math.floor(parseFloat(match[1]) * MEMORY_UNITS[match[2]]);
|
return Math.floor(parseFloat(match[1]) * MEMORY_UNITS[match[2]]);
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.10.7",
|
"version": "2.10.8",
|
||||||
"main": "dist/loader.js",
|
"main": "dist/loader.js",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"repository": "https://github.com/hydro-dev/Hydro.git",
|
"repository": "https://github.com/hydro-dev/Hydro.git",
|
||||||
|
|||||||
Reference in new issue
Block a user