diff --git a/README.md b/README.md new file mode 100644 index 000000000..1851c4ed2 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Hydro + +Hydro是一个高效的信息学在线测评系统。 +特点: 易于部署,轻量,功能强大。 + +## 使用方式 + +使用 `docker-compose`(推荐) + +// TODO(WIP) diff --git a/hydro/error.js b/hydro/error.js index 123743b79..555918163 100644 --- a/hydro/error.js +++ b/hydro/error.js @@ -6,6 +6,14 @@ class UserFacingError extends Error { this.params = []; } } +class SystemError extends Error { + constructor(type) { + super(type); + this.code = 500; + // this.stack = ''; + this.params = []; + } +} class BadRequestError extends UserFacingError { constructor(type) { super(type); @@ -154,7 +162,8 @@ module.exports = { ValidationError, ProblemNotFoundError, TrainingNotFoundError, ContestNotFoundError, RecordNotFoundError, SolutionNotFoundError, AlreadyVotedError, ContestNotAttendedError, ContestNotLiveError, - ContestScoreboardHiddenError, ContestAlreadyAttendedError + ContestScoreboardHiddenError, ContestAlreadyAttendedError, UserFacingError, + SystemError }; /* diff --git a/hydro/install.js b/hydro/install.js index 302360e0e..a80762958 100644 --- a/hydro/install.js +++ b/hydro/install.js @@ -52,7 +52,6 @@ async function run() { await coll_user.createIndex('unameLower', { unique: true }); await coll_user.createIndex('mailLower', { sparse: true }); await coll_role.insertMany(builtin.BUILTIN_ROLES); - await coll_user.insertMany(builtin.BUILTIN_USERS); await coll_blacklist.createIndex('expireAt', { expireAfterSeconds: 0 }); await coll_token.createIndex([{ uid: 1 }, { tokenType: 1 }, { updateAt: -1 }], { sparse: true }); await coll_token.createIndex('expireAt', { expireAfterSeconds: 0 }); diff --git a/hydro/service/server.js b/hydro/service/server.js index 571f09981..7626d2670 100644 --- a/hydro/service/server.js +++ b/hydro/service/server.js @@ -1,6 +1,7 @@ const path = require('path'), { ObjectID } = require('bson'), + { MongoError } = require('mongodb'), Koa = require('koa'), morgan = require('koa-morgan'), Body = require('koa-body'), @@ -14,7 +15,7 @@ const token = require('../model/token'), opcount = require('../model/opcount'), { UserNotFoundError, BlacklistedError, PermissionError, - NotFoundError } = require('../error'); + NotFoundError, UserFacingError } = require('../error'); const options = require('../options'); let http = options.listen.https ? require('https') : require('http'); @@ -60,6 +61,7 @@ class Handler { url_prefix: '/' }; this._handler = {}; + this.session = {}; } renderHTML(name, context) { console.time(name); @@ -130,7 +132,7 @@ class Handler { await this.renderBody(); } catch (error) { if (this.preferJson) this.response.body = { error }; - else await this.render('bsod.html', { error }); + else await this.render(error instanceof UserFacingError ? 'error.html' : 'bsod.html', { error }); } await this.putResponse(); await this.saveCookie(); @@ -186,9 +188,9 @@ class Handler { async onerror(error) { console.error(error.message, error.params); console.error(error.stack); - this.response.template = 'error.html'; + this.response.template = error instanceof UserFacingError ? 'error.html' : 'bsod.html'; this.response.body = { error }; - await this.___cleanup(); + await this.___cleanup().catch(() => { }); } } function Route(route, handler) { diff --git a/templates/layout/html5.html b/templates/layout/html5.html index b1d866da2..f5e0ddb16 100644 --- a/templates/layout/html5.html +++ b/templates/layout/html5.html @@ -22,7 +22,6 @@ -