diff --git a/web/app/controllers/super_manage.php b/web/app/controllers/super_manage.php index 844e868..a73f751 100644 --- a/web/app/controllers/super_manage.php +++ b/web/app/controllers/super_manage.php @@ -38,6 +38,10 @@ $tabs_info = [ 'name' => '图床管理', 'url' => "/super_manage/image_hosting", ], + 'meta' => [ + 'name' => 'OJ 基础设置', + 'url' => "/super_manage/meta", + ], ]; if (!isset($tabs_info[$cur_tab])) { @@ -1068,6 +1072,41 @@ if ($cur_tab == 'index') { ]); }; $change_user_image_total_size_limit_form->runAtServer(); +} elseif ($cur_tab == 'meta') { + $submission_frequency = UOJContext::getMeta('submission_frequency'); + $submission_frequency_form = new UOJForm('submission_frequency'); + $submission_frequency_form->addSelect('submission_frequency_interval', [ + 'label' => '时间间隔', + 'options' => [ + 'PT1S' => '1 秒', + 'PT10S' => '10 秒', + 'PT1M' => '1 分钟', + 'PT10M' => '10 分钟', + 'PT30M' => '30 分钟', + 'PT1H' => '1 小时', + ], + 'default_value' => $submission_frequency['interval'], + ]); + $submission_frequency_form->addInput('submission_frequency_limit', [ + 'label' => '最大提交次数', + 'help' => '在时间间隔内最多允许提交的次数。', + 'default_value' => $submission_frequency['limit'], + 'validator_php' => function ($x, &$vdata) { + if (!validateUInt($x)) { + return '不合法'; + } + $vdata['limit'] = (int)$x; + return ''; + }, + ]); + $submission_frequency_form->handle = function (&$vdata) { + UOJContext::setMeta('submission_frequency', [ + 'interval' => UOJRequest::post('submission_frequency_interval'), + 'limit' => $vdata['limit'], + ]); + }; + $submission_frequency_form->succ_href = UOJContext::requestPath() . '#submission-frequency'; + $submission_frequency_form->runAtServer(); } ?> @@ -1463,21 +1502,6 @@ if ($cur_tab == 'index') { - -
@@ -1660,9 +1684,48 @@ EOD; printHTML() ?>
+ +
+
+ +
+
+
+
+
+
+ printHTML() ?> +
+
+ 此处可以设置用户的提交频次限制。请注意,过于严格的限制会导致用户无法正常提交题目。默认限制为 1 秒内最多提交 1 次。 +
+
+
+
+
+
+ + diff --git a/web/app/libs/uoj-security-lib.php b/web/app/libs/uoj-security-lib.php index 3398271..1ecaf0f 100644 --- a/web/app/libs/uoj-security-lib.php +++ b/web/app/libs/uoj-security-lib.php @@ -36,8 +36,10 @@ function crsf_defend() { } function submission_frequency_check() { + $submission_frequency = UOJContext::getMeta('submission_frequency'); + $recent = clone UOJTime::$time_now; - $recent->sub(new DateInterval("PT1S")); + $recent->sub(new DateInterval($submission_frequency['interval'])); $num = DB::selectCount([ "select count(*) from submissions", "where", [ @@ -45,54 +47,10 @@ function submission_frequency_check() { ["submit_time", ">=", $recent->format('Y-m-d H:i:s')] ] ]); - if ($num >= 1) { + + if ($num >= max(1, $submission_frequency['limit'])) { return false; } - // use the implementation below if OJ is under attack - /* - // 1 - $recent = clone UOJTime::$time_now; - $recent->sub(new DateInterval("PT3S")); - $num = DB::selectCount([ - "select count(*) from submissions", - "where", [ - "submitter" => Auth::id(), - ["submit_time", ">=", $recent->format('Y-m-d H:i:s')] - ] - ]); - if ($num >= 1) { - return false; - } - - // 2 - $recent = clone UOJTime::$time_now; - $recent->sub(new DateInterval("PT1M")); - $num = DB::selectCount([ - "select count(*) from submissions", - "where", [ - "submitter" => Auth::id(), - ["submit_time", ">=", $recent->format('Y-m-d H:i:s')] - ] - ]); - if ($num >= 6) { - return false; - } - - // 3 - $recent = clone UOJTime::$time_now; - $recent->sub(new DateInterval("PT30M")); - $num = DB::selectCount([ - "select count(*) from submissions", - "where", [ - "submitter" => Auth::id(), - ["submit_time", ">=", $recent->format('Y-m-d H:i:s')] - ] - ]); - if ($num >= 30) { - return false; - } - */ - return true; } diff --git a/web/app/models/UOJContext.php b/web/app/models/UOJContext.php index 69fb082..a428d34 100644 --- a/web/app/models/UOJContext.php +++ b/web/app/models/UOJContext.php @@ -36,6 +36,10 @@ class UOJContext { 'upload_image' => true, ], ], + 'submission_frequency' => [ + 'interval' => 'PT1S', + 'limit' => 1, + ], ]; public static $data = [ @@ -156,6 +160,7 @@ class UOJContext { "select value from meta", "where", ['name' => $name] ]); + if ($value === null) { return self::$meta_default[$name]; } else { @@ -165,6 +170,7 @@ class UOJContext { public static function setMeta($name, $value) { $value = json_encode($value); + return DB::update([ "insert into meta", DB::bracketed_fields(['name', 'value', 'updated_at']), "values", DB::tuple([$name, $value, DB::now()]),