refactor: 移除注册验证码,删掉 pillow

验证码只剩注册一处调用方,一并去掉。

- UserRegisterAPI 的校验、UserRegisterSerializer 的 captcha 字段、
  发图的 captcha 路由
- utils/captcha/ 整个包删除,含 Menlo.ttc 和 timesbi.ttf 两个字体
- utils/shortcuts.py 的 img2base64(),唯一调用方是验证码视图
- 依赖删除 pillow(本地实测 PIL/ 5.9M + pillow.libs/ 14M)

注意:注册接口现在只有 SysOptions.allow_register 一个开关,没有限流,
throttling 目前只用在 SubmissionAPI 上。内网自用可以接受,站点若暴露到
公网需要补 IP 维度限流。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-05 23:48:00 -06:00
parent 12c12b1840
commit fda7515263
11 changed files with 0 additions and 263 deletions

View File

@@ -19,7 +19,6 @@ class UserRegisterSerializer(serializers.Serializer):
username = serializers.CharField(max_length=32)
password = serializers.CharField(min_length=6)
email = serializers.EmailField(max_length=64)
captcha = serializers.CharField()
class UserChangePasswordSerializer(serializers.Serializer):

View File

@@ -1,7 +1,5 @@
from django.urls import path
from utils.captcha.views import CaptchaAPIView
from ..views.oj import (
SSOAPI,
AvatarUploadAPI,
@@ -27,7 +25,6 @@ urlpatterns = [
path("register", UserRegisterAPI.as_view()),
path("change_password", UserChangePasswordAPI.as_view()), # DEPRECATED: 前端未调用
path("change_email", UserChangeEmailAPI.as_view()), # DEPRECATED: 前端未调用
path("captcha", CaptchaAPIView.as_view()),
path("check_username_or_email", UsernameOrEmailCheck.as_view()), # DEPRECATED: 前端未调用
path("profile", UserProfileAPI.as_view(), name="user_profile_api"),
path("profile/fresh_display_id", ProfileProblemDisplayIDRefreshAPI.as_view()),

View File

@@ -14,7 +14,6 @@ from problem.models import Problem
from submission.models import JudgeStatus, Submission
from utils.api import APIView, AsyncAPIView, CSRFExemptAPIView, validate_serializer
from utils.async_helpers import async_cache_get, async_cache_set
from utils.captcha import Captcha
from utils.constants import CacheKey
from utils.shortcuts import datetime2str, rand_str
@@ -159,9 +158,6 @@ class UserRegisterAPI(AsyncAPIView):
data = request.data
data["username"] = data["username"].lower()
data["email"] = data["email"].lower()
captcha = Captcha(request)
if not captcha.check(data["captcha"]):
return self.error("Invalid captcha")
if await User.objects.filter(username=data["username"]).aexists():
return self.error("Username already exists")
if await User.objects.filter(email=data["email"]).aexists():