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()]),