remove server.log setting item

This commit is contained in:
undefined committed 2020-07-25 19:23:48 +08:00
1 parent e62e7b49a3
commit ee78271a84
27 files changed
+159 -114

No files matched your search

+20 -17
View File
@@ -1,21 +1,24 @@
/* eslint-disable func-names */
const { isClass } = require('./utils');
import { isClass } from './utils';
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 msg;
let code;
let msg: () => string;
let code: number;
for (const item of info) {
if (typeof item === 'number') {
code = item;
} else if (typeof item === 'string') {
msg = function () { return item; };
} else if (isClass(item)) {
// @ts-ignore
} else if (isHydroError(item)) {
Class = item;
} else if (typeof item === 'function') {
msg = item;
@@ -29,19 +32,19 @@ const Err = (name: string, ...info: Array<IHydroError | Function | string | numb
};
export class HydroError extends Error {
params: any[];
params: any[];
code: number;
code: number;
constructor(...params: any[]) {
super();
this.params = params;
}
constructor(...params: any[]) {
super();
this.params = params;
}
// eslint-disable-next-line class-methods-use-this
msg() {
return 'HydroError';
}
// eslint-disable-next-line class-methods-use-this
msg() {
return 'HydroError';
}
}
export const UserFacingError = Err('UserFacingError', HydroError, 'UserFacingError', 400);
+6 -3
View File
@@ -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);
this.back();
}
@@ -161,7 +163,8 @@ class DomainRoleHandler extends ManageHandler {
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 rdict: any = {};
for (const r of roles) rdict[r._id] = r.perm;
@@ -183,7 +186,7 @@ class DomainRoleHandler extends ManageHandler {
class DomainSearchHandler extends Handler {
@param('q', Types.String)
async get(q: string) {
async get(domainId: string, q: string) {
const ddocs = await domain.getPrefixSearch(q, 20);
for (let i = 0; i < ddocs.length; i++) {
ddocs[i].gravatar = ddocs[i].gravatar ? gravatar(ddocs[i].gravatar) : '/img/team_avatar.png';
+2 -2
View File
@@ -150,9 +150,9 @@ class HomeSecurityHandler extends Handler {
@param('currentPassword', Types.String)
@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.user.checkPassword(currentPassword);
this.user.checkPassword(current);
const udoc = await user.getByEmail(domainId, email);
if (udoc) throw new UserAlreadyExistError(email);
const [code] = await token.add(
-9
View File
@@ -158,13 +158,4 @@ export async function apply() {
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;
+3 -3
View File
@@ -15,8 +15,8 @@ import { sendMail } from '../lib/mail';
import * as misc from '../lib/misc';
import {
UserAlreadyExistError, InvalidTokenError, VerifyPasswordError,
UserNotFoundError, LoginError, SystemError,
BlacklistedError, UserFacingError,
UserNotFoundError, SystemError, BlacklistedError,
UserFacingError,
} from '../error';
class UserLoginHandler extends Handler {
@@ -35,7 +35,7 @@ class UserLoginHandler extends Handler {
@param('rememberme', Types.Boolean, true)
async post(domainId: string, uname: string, password: string, rememberme = false) {
const udoc = await user.getByUname(domainId, uname);
if (!udoc) throw new LoginError(uname);
if (!udoc) throw new UserNotFoundError(uname);
udoc.checkPassword(password);
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
if (udoc.priv === PRIV.PRIV_NONE) throw new BlacklistedError(uname);
+36 -4
View File
@@ -141,7 +141,7 @@ export interface Pdoc {
acMsg?: string,
}
export type Pdict = Dictionary<Pdoc>;
export type Pdict = NumericDictionary<Pdoc>;
export interface TestCase {
time: number,
@@ -245,7 +245,38 @@ export interface Bdoc {
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,
}
@@ -330,6 +361,7 @@ declare global {
gridfs: GridFSBucket,
monitor: typeof import('./service/monitor'),
server: typeof import('./service/server'),
[key: string]: any,
},
lib: {
download: typeof import('./lib/download').default,
@@ -363,9 +395,9 @@ declare global {
},
error: typeof import('./error'),
locales: Dict<Dict<string>>,
postInit: Function[],
postInit: Array<() => Promise<any>>,
},
onDestory: Function[],
onDestory: Array<() => void>,
addons: string[],
}
}
-1
View File
@@ -27,7 +27,6 @@ function decodeJWT(idToken: string) {
}
}
// eslint-disable-next-line import/prefer-default-export
export function decode(idToken: string) {
const decodedJWT = decodeJWT(idToken);
return decodedJWT.payload;
-6
View File
@@ -6,12 +6,6 @@ function wrap(func: Function, type: string) {
func(...args);
if (global.Hydro.model.message) {
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);
} catch (e) {
func(e.message);
-1
View File
@@ -1,7 +1,6 @@
import nodemailer from 'nodemailer';
import { SendMailError } from '../error';
// eslint-disable-next-line import/prefer-default-export
export async function sendMail(to: string, subject: string, text: string, html: string) {
let t: unknown;
try {
+12 -11
View File
@@ -1,19 +1,20 @@
import AnsiUp from 'ansi_up';
import { ObjectID } from 'mongodb';
import md5 from './md5';
const AU = new AnsiUp();
export function ansiToHtml(str) {
export function ansiToHtml(str: string) {
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}`;
}
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.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);
return '<span class="time{0}" data-timestamp="{1}">{2}</span>'.format(
relative ? ' relative' : '',
@@ -22,9 +23,10 @@ export function datetimeSpan(dt, relative = true, format = '%Y-%m-%d %H:%M:%S')
);
}
export function* paginate(page, numPages) {
const radius = 2; let first; let
last;
export function* paginate(page: number, numPages: number) {
const radius = 2;
let first: number;
let last: number;
if (page > 1) {
yield ['first', 1];
yield ['previous', page - 1];
@@ -45,7 +47,7 @@ export function* paginate(page, numPages) {
yield ['last', numPages];
}
export function size(s, base = 1) {
export function size(s: number, base = 1) {
s *= base;
const unit = 1024;
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);
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) {
if (number < 10) return `0${number}`;
return number.toString();
return number < 10 ? `0${number}` : number.toString();
}
export function formatSeconds(_seconds = '0') {
+1 -1
View File
@@ -12,7 +12,7 @@ const Checker = (perm: bigint, priv: number, checker: Function = trueChecker) =>
const Item = (
name: string, args: any, prefix: string,
...permPrivChecker: Array<number | bigint | Function | Array<bigint | string>>
...permPrivChecker: Array<number | bigint | Function>
) => {
let _priv: number;
let _perm: bigint;
+4 -2
View File
@@ -1,6 +1,9 @@
import { Cursor } from 'mongodb';
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');
const [count, pageDocs] = await Promise.all([
cursor.count(),
@@ -11,4 +14,3 @@ async function paginate(cursor: import('mongodb').Cursor, page: number, pageSize
}
global.Hydro.lib.paginate = paginate;
export default paginate;
+11 -8
View File
@@ -1,12 +1,16 @@
class User {
rank: any;
rank: number;
old: any;
old: number;
seed: number;
uid: number;
delta?: number;
new: number;
constructor(rank: number, old: number, uid = 0) {
this.rank = rank;
this.old = old;
@@ -16,7 +20,7 @@ class User {
}
class RatingCalculator {
users: any;
users: User[];
constructor(users) {
this.users = [];
@@ -26,11 +30,11 @@ class RatingCalculator {
}
// 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));
}
getExSeed(rating, ownUser) {
getExSeed(rating: number, ownUser: User) {
const exUser = new User(0.0, rating);
let result = 1;
for (const user of this.users) {
@@ -39,7 +43,7 @@ class RatingCalculator {
return result;
}
calRating(rank, user) {
calRating(rank: number, user: User) {
let left = 1;
let right = 8000;
while (right - left > 1) {
@@ -101,10 +105,9 @@ interface RatingOutputUser {
uid: number,
}
function calculate(users: RatingInputUser[]): RatingOutputUser[] {
export default function calculate(users: RatingInputUser[]): RatingOutputUser[] {
const calculator = new RatingCalculator(users);
return calculator.calculate();
}
global.Hydro.lib.rating = calculate;
export default calculate;
+2 -16
View File
@@ -67,22 +67,8 @@ function _validate(scheme: any, arg: any, base: string): void {
}
}
function descriptor(scheme: any): Function {
return function desc(target: any, name: string, obj: any) {
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 function validate(scheme: any, arg: any) {
return _validate(scheme, arg, '');
}
export const isTitle = (s) => s && s.length < 64;
+11 -1
View File
@@ -4,6 +4,11 @@ import { Bdoc } from '../interface';
const coll = db.collection('blacklist');
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 res = await coll.findOneAndUpdate(
{ _id: ip },
@@ -13,7 +18,12 @@ export async function add(ip: string): Promise<Bdoc> {
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 });
}
+18 -10
View File
@@ -5,6 +5,7 @@ import * as training from './training';
import * as document from './document';
import { PERM } from './builtin';
import { DocumentNotFoundError } from '../error';
import { Ddoc, Drdoc, Drrdoc } from '../interface';
export const typeDisplay = {
[document.TYPE_PROBLEM]: 'problem',
@@ -18,7 +19,7 @@ export function add(
domainId: string, parentType: number, parentId: ObjectID | number | string,
owner: number, title: string, content: string,
ip: string | null = null, highlight: boolean = false,
) {
): Promise<ObjectID> {
return document.add(
domainId, content, owner, document.TYPE_DISCUSSION,
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);
}
export function edit(
domainId: string, did: ObjectID,
title: string, content: string, highlight: boolean,
) {
): Promise<Ddoc | null> {
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(
domainId: string, did: ObjectID, owner: number,
content: string, ip: string,
) {
): Promise<Drdoc> {
const [drdoc] = await Promise.all([
document.add(
domainId, content, owner, document.TYPE_DISCUSSION_REPLY,
@@ -76,11 +77,13 @@ export async function addReply(
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);
}
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 });
}
@@ -100,14 +103,14 @@ export function getMultiReply(domainId: string, did: ObjectID) {
).sort('_id', -1);
}
export function getListReply(domainId: string, did: ObjectID) {
export function getListReply(domainId: string, did: ObjectID): Promise<Drdoc[]> {
return getMultiReply(domainId, did).toArray();
}
export async function addTailReply(
domainId: string, drid: ObjectID,
owner: number, content: string, ip: string,
) {
): Promise<[Drdoc, ObjectID]> {
let drdoc = await document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid);
const sid = new ObjectID();
[drdoc] = await Promise.all([
@@ -117,11 +120,16 @@ export async function addTailReply(
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);
}
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 });
}
+2 -2
View File
@@ -27,7 +27,7 @@ export async function send(
return mdoc;
}
export async function get(_id: ObjectID): Promise<Mdoc> {
export async function get(_id: ObjectID): Promise<Mdoc | null> {
return await coll.findOne({ _id });
}
@@ -41,7 +41,7 @@ export async function getMany(query: any, sort: any, page: number, limit: number
.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(
{ _id: messageId },
{ $bit: { flag: { xor: flag } } },
+6 -4
View File
@@ -77,7 +77,7 @@ export function edit(domainId: string, _id: number, $set: any): Promise<Pdoc> {
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);
}
@@ -85,7 +85,7 @@ export function count(domainId: string, query: any) {
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 pcount = await cursor.count();
if (pcount) {
@@ -100,16 +100,18 @@ export async function getList(
): Promise<Pdict> {
pids = Array.from(new Set(pids));
const r = {};
const l = {};
const q: any = { $or: [{ docId: { $in: pids } }, { pid: { $in: pids } }] };
if (!getHidden) q.hidden = false;
const pdocs = await document.getMulti(domainId, document.TYPE_PROBLEM, q).toArray();
for (const pdoc of pdocs) {
r[pdoc.docId] = pdoc;
r[pdoc.pid] = pdoc;
l[pdoc.pid] = pdoc;
}
// TODO enhance
if (pdocs.length !== pids.length) {
for (const pid of pids) {
if (!r[pid]) {
if (!(r[pid] || l[pid])) {
if (doThrow) {
throw new ProblemNotFoundError(domainId, pid);
} else {
-2
View File
@@ -1,5 +1,3 @@
import _ from 'lodash';
import yaml from 'js-yaml';
import { ObjectID } from 'mongodb';
import { STATUS } from './builtin';
import * as task from './task';
-1
View File
@@ -121,7 +121,6 @@ SystemSetting(
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.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.secure', null, false, 'boolean', 'session.secure'),
Setting('setting_session', 'session.saved_expire_seconds', null, 3600 * 24 * 30, 'number', 'Saved session expire seconds'),
-1
View File
@@ -1,4 +1,3 @@
import { ValidationError } from '../error';
import * as db from '../service/db';
const coll = db.collection('token');
+8 -1
View File
@@ -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(), '.hydro', '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;
}
+1 -1
View File
@@ -15,7 +15,7 @@ type ND = NumericDictionary<number>
function calc(udict: ND, rankedDocs: [number, number][]) {
const users = [];
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);
for (const udoc of rated) {
+10 -1
View File
@@ -13,6 +13,15 @@ export async function update() {
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(
async () => {
const info = await sysinfo.get();
@@ -25,4 +34,4 @@ global.Hydro.postInit.push(
},
);
global.Hydro.service.monitor = { update };
global.Hydro.service.monitor = { update, updateJudger };
+2 -2
View File
@@ -743,8 +743,8 @@ export function Connection(
// TODO use postInit?
export async function start() {
const [disableLog, port] = await system.getMany(['server.log', 'server.port']);
if (!disableLog) {
const port = await system.get('server.port');
if (!argv.debug) {
app.use(morgan(':method :url :status :res[content-length] - :response-time ms', {
skip: (req, res) => res.hasHeader('nolog'),
}));
+3 -3
View File
@@ -1,8 +1,8 @@
import fs from 'fs';
import { serialize } from 'v8';
import cluster from 'cluster';
import path from 'path';
import * as superagent from 'superagent';
import serialize from 'serialize-javascript';
import proxy from 'superagent-proxy';
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_UNITS = { k: 0.1, m: 1, g: 1024 };
export function parseTimeMS(str) {
export function parseTimeMS(str: string) {
const match = TIME_RE.exec(str);
if (!match) throw new Error(`${str} error parsing time`);
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);
if (!match) throw new Error(`${str} error parsing memory`);
return Math.floor(parseFloat(match[1]) * MEMORY_UNITS[match[2]]);
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "hydrooj",
"version": "2.10.7",
"version": "2.10.8",
"main": "dist/loader.js",
"bin": "bin/hydrooj.js",
"repository": "https://github.com/hydro-dev/Hydro.git",