core: 更新请求频率限制

This commit is contained in:
undefined committed 2021-03-27 17:35:37 +08:00
1 parent 3040f17702
commit b71011b3b9
9 files changed
+17 -14

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.20.41", "version": "2.20.43",
"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",
+2 -2
View File
@@ -311,7 +311,7 @@ class ContestDetailProblemSubmitHandler extends ContestProblemHandler {
@param('lang', Types.String) @param('lang', Types.String)
@param('code', Types.String) @param('code', Types.String)
async post(domainId: string, tid: ObjectID, lang: string, code: string) { async post(domainId: string, tid: ObjectID, lang: string, code: string) {
await this.limitRate('add_record', 60, 100); await this.limitRate('add_record', 60, 10);
const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true, { const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true, {
type: document.TYPE_CONTEST, type: document.TYPE_CONTEST,
tid, tid,
@@ -339,7 +339,7 @@ class ContestCodeHandler extends ContestHandler {
if (!this.user.hasPriv(PRIV.PRIV_READ_RECORD_CODE)) { if (!this.user.hasPriv(PRIV.PRIV_READ_RECORD_CODE)) {
this.checkPerm(PERM.PERM_READ_RECORD_CODE); this.checkPerm(PERM.PERM_READ_RECORD_CODE);
} }
this.limitRate('homework_code', 3600, 60); await this.limitRate('homework_code', 3600, 60);
const [tdoc, tsdocs] = await contest.getAndListStatus(domainId, tid); const [tdoc, tsdocs] = await contest.getAndListStatus(domainId, tid);
const rnames = {}; const rnames = {};
for (const tsdoc of tsdocs) { for (const tsdoc of tsdocs) {
+3 -3
View File
@@ -159,7 +159,7 @@ class DiscussionCreateHandler extends DiscussionHandler {
domainId: string, type: string, _name: string, domainId: string, type: string, _name: string,
title: string, content: string, highlight = false, pin = false, title: string, content: string, highlight = false, pin = false,
) { ) {
this.limitRate('add_discussion', 3600, 30); await this.limitRate('add_discussion', 3600, 60);
let name: ObjectID | string | number; let name: ObjectID | string | number;
if (ObjectID.isValid(_name)) name = new ObjectID(_name); if (ObjectID.isValid(_name)) name = new ObjectID(_name);
else if (isSafeInteger(parseInt(_name, 10))) name = parseInt(_name, 10); else if (isSafeInteger(parseInt(_name, 10))) name = parseInt(_name, 10);
@@ -220,7 +220,7 @@ class DiscussionDetailHandler extends DiscussionHandler {
@param('content', Types.String, isContent) @param('content', Types.String, isContent)
async postReply(domainId: string, did: ObjectID, content: string) { async postReply(domainId: string, did: ObjectID, content: string) {
this.checkPerm(PERM.PERM_REPLY_DISCUSSION); this.checkPerm(PERM.PERM_REPLY_DISCUSSION);
this.limitRate('add_discussion', 3600, 30); await this.limitRate('add_discussion', 3600, 60);
// Notify related users // Notify related users
const replies: Drdoc[] = await discussion.getMultiReply(domainId, did).toArray(); const replies: Drdoc[] = await discussion.getMultiReply(domainId, did).toArray();
const uids = Array.from(new Set(replies.map((drdoc) => drdoc.owner))); const uids = Array.from(new Set(replies.map((drdoc) => drdoc.owner)));
@@ -239,7 +239,7 @@ class DiscussionDetailHandler extends DiscussionHandler {
@param('content', Types.String, isContent) @param('content', Types.String, isContent)
async postTailReply(domainId: string, drid: ObjectID, content: string) { async postTailReply(domainId: string, drid: ObjectID, content: string) {
this.checkPerm(PERM.PERM_REPLY_DISCUSSION); this.checkPerm(PERM.PERM_REPLY_DISCUSSION);
this.limitRate('add_discussion', 3600, 30); await this.limitRate('add_discussion', 3600, 60);
await discussion.addTailReply(domainId, drid, this.user._id, content, this.request.ip); await discussion.addTailReply(domainId, drid, this.user._id, content, this.request.ip);
this.back(); this.back();
} }
+1 -1
View File
@@ -152,7 +152,7 @@ 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, current: string, email: string) { async postChangeMail(domainId: string, current: string, email: string) {
this.limitRate('send_mail', 3600, 30); await this.limitRate('send_mail', 3600, 30);
this.user.checkPassword(current); 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);
+2 -2
View File
@@ -177,7 +177,7 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler {
@param('code', Types.String) @param('code', Types.String)
@param('lang', Types.String) @param('lang', Types.String)
async post(domainId: string, tid: ObjectID, pid: number, code: string, lang: string) { async post(domainId: string, tid: ObjectID, pid: number, code: string, lang: string) {
this.limitRate('add_record', 3600, 100); await this.limitRate('add_record', 60, 5);
const tsdoc = await contest.getStatus(domainId, tid, this.user._id, document.TYPE_HOMEWORK); const tsdoc = await contest.getStatus(domainId, tid, this.user._id, document.TYPE_HOMEWORK);
if (!tsdoc.attend) throw new HomeworkNotAttendedError(tid); if (!tsdoc.attend) throw new HomeworkNotAttendedError(tid);
if (!contest.isOngoing(this.tdoc)) throw new HomeworkNotLiveError(tid); if (!contest.isOngoing(this.tdoc)) throw new HomeworkNotLiveError(tid);
@@ -380,7 +380,7 @@ class HomeworkCodeHandler extends HomeworkHandler {
@param('tid', Types.ObjectID) @param('tid', Types.ObjectID)
async get(domainId: string, tid: ObjectID) { async get(domainId: string, tid: ObjectID) {
this.checkPerm(PERM.PERM_READ_RECORD_CODE); this.checkPerm(PERM.PERM_READ_RECORD_CODE);
this.limitRate('homework_code', 3600, 60); await this.limitRate('homework_code', 3600, 60);
const [tdoc, tsdocs] = await contest.getAndListStatus( const [tdoc, tsdocs] = await contest.getAndListStatus(
domainId, tid, document.TYPE_HOMEWORK, domainId, tid, document.TYPE_HOMEWORK,
); );
+2 -1
View File
@@ -231,6 +231,7 @@ export class ProblemSubmitHandler extends ProblemDetailHandler {
@param('lang', Types.String) @param('lang', Types.String)
@param('code', Types.String) @param('code', Types.String)
async post(domainId: string, lang: string, code: string) { async post(domainId: string, lang: string, code: string) {
await this.limitRate('add_record', 60, 5);
const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true); const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true);
const [rdoc] = await Promise.all([ const [rdoc] = await Promise.all([
record.get(domainId, rid), record.get(domainId, rid),
@@ -248,7 +249,7 @@ export class ProblemPretestHandler extends ProblemDetailHandler {
@param('code', Types.String) @param('code', Types.String)
@param('input', Types.String, true) @param('input', Types.String, true)
async post(domainId: string, lang: string, code: string, input = '') { async post(domainId: string, lang: string, code: string, input = '') {
this.limitRate('add_record', 3600, 100); await this.limitRate('add_record', 60, 5);
const rid = await record.add( const rid = await record.add(
domainId, this.pdoc.docId, this.user._id, domainId, this.pdoc.docId, this.user._id,
lang, code, true, input, lang, code, true, input,
+2 -2
View File
@@ -67,7 +67,7 @@ class UserRegisterHandler extends Handler {
async post(domainId: string, mail: string, phoneNumber: string) { async post(domainId: string, mail: string, phoneNumber: string) {
if (mail) { if (mail) {
if (await user.getByEmail('system', mail)) throw new UserAlreadyExistError(mail); if (await user.getByEmail('system', mail)) throw new UserAlreadyExistError(mail);
this.limitRate('send_mail', 3600, 30); await this.limitRate('send_mail', 3600, 30);
const t = await token.add( const t = await token.add(
token.TYPE_REGISTRATION, token.TYPE_REGISTRATION,
system.get('session.unsaved_expire_seconds'), system.get('session.unsaved_expire_seconds'),
@@ -83,7 +83,7 @@ class UserRegisterHandler extends Handler {
} else this.response.redirect = this.url('user_register_with_code', { code: t[0] }); } else this.response.redirect = this.url('user_register_with_code', { code: t[0] });
} else if (phoneNumber) { } else if (phoneNumber) {
if (!global.Hydro.lib.sendSms) throw new SystemError('Cannot send sms'); if (!global.Hydro.lib.sendSms) throw new SystemError('Cannot send sms');
this.limitRate('send_sms', 60, 3); await this.limitRate('send_sms', 60, 3);
const t = await token.add( const t = await token.add(
token.TYPE_REGISTRATION, token.TYPE_REGISTRATION,
system.get('session.unsaved_expire_seconds'), system.get('session.unsaved_expire_seconds'),
+1
View File
@@ -231,6 +231,7 @@ export const PRIV = {
PRIV_REJUDGE: 1 << 13, PRIV_REJUDGE: 1 << 13,
PRIV_VIEW_USER_SECRET: 1 << 14, PRIV_VIEW_USER_SECRET: 1 << 14,
PRIV_VIEW_JUDGE_STATISTICS: 1 << 15, PRIV_VIEW_JUDGE_STATISTICS: 1 << 15,
PRIV_UNLIMITED_RATE: 1 << 22,
PRIV_ALL: -1, PRIV_ALL: -1,
PRIV_DEFAULT: 0, PRIV_DEFAULT: 0,
+3 -2
View File
@@ -36,7 +36,7 @@ import * as system from '../model/system';
import blacklist from '../model/blacklist'; import blacklist from '../model/blacklist';
import token from '../model/token'; import token from '../model/token';
import * as opcount from '../model/opcount'; import * as opcount from '../model/opcount';
import { PERM } from '../model/builtin'; import { PERM, PRIV } from '../model/builtin';
const logger = new Logger('server'); const logger = new Logger('server');
export const app = new Koa(); export const app = new Koa();
@@ -274,6 +274,7 @@ export class HandlerCommon {
extraTitleContent?: string; extraTitleContent?: string;
async limitRate(op: string, periodSecs: number, maxOperations: number) { async limitRate(op: string, periodSecs: number, maxOperations: number) {
if (this.user && this.user.hasPriv(PRIV.PRIV_UNLIMITED_RATE)) return;
await opcount.inc(op, this.request.ip, periodSecs, maxOperations); await opcount.inc(op, this.request.ip, periodSecs, maxOperations);
} }
@@ -459,7 +460,7 @@ export class Handler extends HandlerCommon {
const [absoluteDomain, inferDomain] = await Promise.all([ const [absoluteDomain, inferDomain] = await Promise.all([
domain.get(domainId), domain.get(domainId),
domain.getByHost(this.request.host), domain.getByHost(this.request.host),
this.limitRate('global', 10, 100), this.limitRate('global', 10, 50),
this.getSession(), this.getSession(),
this.getBdoc(), this.getBdoc(),
]); ]);