用户名不区分大小写;

修复更新problem时的一些问题
This commit is contained in:
zema1 2017-11-02 15:29:08 +08:00
parent b86ebf0ed7
commit 70f52b6f27
5 changed files with 103 additions and 78 deletions

View File

@ -20,7 +20,7 @@ class UserManager(models.Manager):
use_in_migrations = True use_in_migrations = True
def get_by_natural_key(self, username): def get_by_natural_key(self, username):
return self.get(**{self.model.USERNAME_FIELD: username}) return self.get(**{f"{self.model.USERNAME_FIELD}__iexact": username})
class User(AbstractBaseUser): class User(AbstractBaseUser):

View File

@ -198,7 +198,7 @@ class UsernameOrEmailCheck(APIView):
if data.get("username"): if data.get("username"):
result["username"] = User.objects.filter(username=data["username"]).exists() result["username"] = User.objects.filter(username=data["username"]).exists()
if data.get("email"): if data.get("email"):
result["email"] = User.objects.filter(email=data["email"]).exists() result["email"] = User.objects.filter(email=data["email"].lower()).exists()
return self.success(result) return self.success(result)
@ -218,9 +218,9 @@ class UserRegisterAPI(APIView):
return self.error("Invalid captcha") return self.error("Invalid captcha")
if User.objects.filter(username=data["username"]).exists(): if User.objects.filter(username=data["username"]).exists():
return self.error("Username already exists") return self.error("Username already exists")
data["email"] = data["email"].lower()
if User.objects.filter(email=data["email"]).exists(): if User.objects.filter(email=data["email"]).exists():
return self.error("Email already exists") return self.error("Email already exists")
user = User.objects.create(username=data["username"], email=data["email"]) user = User.objects.create(username=data["username"], email=data["email"])
user.set_password(data["password"]) user.set_password(data["password"])
user.save() user.save()
@ -240,6 +240,7 @@ class UserChangeEmailAPI(APIView):
return self.error("tfa_required") return self.error("tfa_required")
if not OtpAuth(user.tfa_token).valid_totp(data["tfa_code"]): if not OtpAuth(user.tfa_token).valid_totp(data["tfa_code"]):
return self.error("Invalid two factor verification code") return self.error("Invalid two factor verification code")
data["new_email"] = data["new_email"].lower()
if User.objects.filter(email=data["new_email"]).exists(): if User.objects.filter(email=data["new_email"]).exists():
return self.error("The email is owned by other account") return self.error("The email is owned by other account")
user.email = data["new_email"] user.email = data["new_email"]
@ -280,7 +281,7 @@ class ApplyResetPasswordAPI(APIView):
if not captcha.check(data["captcha"]): if not captcha.check(data["captcha"]):
return self.error("Invalid captcha") return self.error("Invalid captcha")
try: try:
user = User.objects.get(email=data["email"]) user = User.objects.get(email__iexact=data["email"])
except User.DoesNotExist: except User.DoesNotExist:
return self.error("User does not exist") return self.error("User does not exist")
if user.reset_password_token_expire_time and 0 < int( if user.reset_password_token_expire_time and 0 < int(

View File

@ -118,7 +118,9 @@ LOGGING = {
'disable_existing_loggers': False, 'disable_existing_loggers': False,
'formatters': { 'formatters': {
'standard': { 'standard': {
'format': '%(asctime)s [%(threadName)s:%(thread)d] [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] [%(levelname)s]- %(message)s'} 'format': '%(asctime)s [%(threadName)s:%(thread)d] [%(name)s:%(lineno)d] [%(module)s:%(funcName)s] [%(levelname)s]- %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S'
}
}, },
'handlers': { 'handlers': {
'django_error': { 'django_error': {
@ -145,11 +147,6 @@ LOGGING = {
'level': 'WARNING', 'level': 'WARNING',
'propagate': True, 'propagate': True,
}, },
'django.server': {
'handlers': ['django_error', 'console'],
'level': 'ERROR',
'propagate': True,
},
'django.db.backends': { 'django.db.backends': {
'handlers': ['django_error', 'console'], 'handlers': ['django_error', 'console'],
'level': 'WARNING', 'level': 'WARNING',

View File

@ -39,7 +39,7 @@ class CreateOrEditProblemSerializer(serializers.Serializer):
input_description = serializers.CharField() input_description = serializers.CharField()
output_description = serializers.CharField() output_description = serializers.CharField()
samples = serializers.ListField(child=CreateSampleSerializer(), allow_empty=False) samples = serializers.ListField(child=CreateSampleSerializer(), allow_empty=False)
test_case_id = serializers.CharField(min_length=32, max_length=32) test_case_id = serializers.CharField(max_length=32)
test_case_score = serializers.ListField(child=CreateTestCaseScoreSerializer(), allow_empty=False) test_case_score = serializers.ListField(child=CreateTestCaseScoreSerializer(), allow_empty=False)
time_limit = serializers.IntegerField(min_value=1, max_value=1000 * 60) time_limit = serializers.IntegerField(min_value=1, max_value=1000 * 60)
memory_limit = serializers.IntegerField(min_value=1, max_value=1024) memory_limit = serializers.IntegerField(min_value=1, max_value=1024)
@ -68,6 +68,11 @@ class CreateContestProblemSerializer(CreateOrEditProblemSerializer):
contest_id = serializers.IntegerField() contest_id = serializers.IntegerField()
class EditContestProblemSerializer(CreateOrEditProblemSerializer):
id = serializers.IntegerField()
contest_id = serializers.IntegerField()
class TagSerializer(serializers.ModelSerializer): class TagSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = ProblemTag model = ProblemTag

View File

@ -12,7 +12,7 @@ from utils.shortcuts import rand_str
from ..models import Problem, ProblemRuleType, ProblemTag from ..models import Problem, ProblemRuleType, ProblemTag
from ..serializers import (CreateContestProblemSerializer, ContestProblemAdminSerializer, from ..serializers import (CreateContestProblemSerializer, ContestProblemAdminSerializer,
CreateProblemSerializer, EditProblemSerializer, CreateProblemSerializer, EditProblemSerializer, EditContestProblemSerializer,
ProblemAdminSerializer, TestCaseUploadForm) ProblemAdminSerializer, TestCaseUploadForm)
@ -109,26 +109,14 @@ class TestCaseUploadAPI(CSRFExemptAPIView):
return self.success({"id": test_case_id, "info": ret, "hint": hint, "spj": spj}) return self.success({"id": test_case_id, "info": ret, "hint": hint, "spj": spj})
class ProblemAPI(APIView): class ProblemBase(APIView):
@validate_serializer(CreateProblemSerializer) def common_checks(self, request):
@problem_permission_required
def post(self, request):
data = request.data data = request.data
_id = data["_id"]
if _id:
try:
Problem.objects.get(_id=_id)
return self.error("Display ID already exists")
except Problem.DoesNotExist:
pass
else:
data["_id"] = rand_str(8)
if data["spj"]: if data["spj"]:
if not data["spj_language"] or not data["spj_code"]: if not data["spj_language"] or not data["spj_code"]:
return self.error("Invalid spj") return "Invalid spj"
data["spj_version"] = hashlib.md5((data["spj_language"] + ":" + data["spj_code"]).encode("utf-8")).hexdigest() data["spj_version"] = hashlib.md5(
(data["spj_language"] + ":" + data["spj_code"]).encode("utf-8")).hexdigest()
else: else:
data["spj_language"] = None data["spj_language"] = None
data["spj_code"] = None data["spj_code"] = None
@ -136,21 +124,33 @@ class ProblemAPI(APIView):
total_score = 0 total_score = 0
for item in data["test_case_score"]: for item in data["test_case_score"]:
if item["score"] <= 0: if item["score"] <= 0:
return self.error("Invalid score") return "Invalid score"
else: else:
total_score += item["score"] total_score += item["score"]
data["total_score"] = total_score data["total_score"] = total_score
# todo check filename and score info
data["created_by"] = request.user data["created_by"] = request.user
tags = data.pop("tags")
data["languages"] = list(data["languages"]) data["languages"] = list(data["languages"])
problem = Problem.objects.create(**data)
class ProblemAPI(ProblemBase):
@validate_serializer(CreateProblemSerializer)
@problem_permission_required
def post(self, request):
data = request.data
_id = data["_id"]
if not _id: if not _id:
problem._id = str(problem.id) return self.error("Display ID is required")
problem.save() if Problem.objects.filter(_id=_id, contest_id__isnull=True).exists():
return self.error("Display ID already exists")
error_info = self.common_checks(request)
if error_info:
return self.error(error_info)
# todo check filename and score info
tags = data.pop("tags")
problem = Problem.objects.create(**data)
for item in tags: for item in tags:
try: try:
@ -196,31 +196,14 @@ class ProblemAPI(APIView):
return self.error("Problem does not exist") return self.error("Problem does not exist")
_id = data["_id"] _id = data["_id"]
if _id: if not _id:
try: return self.error("Display ID is required")
Problem.objects.exclude(id=problem_id).get(_id=_id) if Problem.objects.exclude(id=problem_id).filter(_id=_id, contest_id__isnull=True).exists():
return self.error("Display ID already exists") return self.error("Display ID already exists")
except Problem.DoesNotExist:
pass
else:
data["_id"] = str(problem_id)
if data["spj"]: error_info = self.common_checks(request)
if not data["spj_language"] or not data["spj_code"]: if error_info:
return self.error("Invalid spj") return self.error(error_info)
data["spj_version"] = hashlib.md5((data["spj_language"] + ":" + data["spj_code"]).encode("utf-8")).hexdigest()
else:
data["spj_language"] = None
data["spj_code"] = None
if data["rule_type"] == ProblemRuleType.OI:
total_score = 0
for item in data["test_case_score"]:
if item["score"] <= 0:
return self.error("Invalid score")
else:
total_score += item["score"]
data["total_score"] = total_score
# todo check filename and score info # todo check filename and score info
tags = data.pop("tags") tags = data.pop("tags")
data["languages"] = list(data["languages"]) data["languages"] = list(data["languages"])
@ -240,11 +223,11 @@ class ProblemAPI(APIView):
return self.success() return self.success()
class ContestProblemAPI(APIView): class ContestProblemAPI(ProblemBase):
@validate_serializer(CreateContestProblemSerializer) @validate_serializer(CreateContestProblemSerializer)
@problem_permission_required
def post(self, request): def post(self, request):
data = request.data data = request.data
try: try:
contest = Contest.objects.get(id=data.pop("contest_id")) contest = Contest.objects.get(id=data.pop("contest_id"))
if request.user.is_admin() and contest.created_by != request.user: if request.user.is_admin() and contest.created_by != request.user:
@ -257,30 +240,18 @@ class ContestProblemAPI(APIView):
_id = data["_id"] _id = data["_id"]
if not _id: if not _id:
return self.error("Display id is required for contest problem") return self.error("Display ID is required")
if Problem.objects.filter(_id=_id, contest=contest).exists(): if Problem.objects.filter(_id=_id, contest=contest).exists():
return self.error("Duplicate Display id") return self.error("Duplicate Display id")
if data["spj"]: error_info = self.common_checks(request)
if not data["spj_language"] or not data["spj_code"]: if error_info:
return self.error("Invalid spj") return self.error(error_info)
data["spj_version"] = hashlib.md5((data["spj_language"] + ":" + data["spj_code"]).encode("utf-8")).hexdigest()
else:
data["spj_language"] = None
data["spj_code"] = None
if data["rule_type"] == ProblemRuleType.OI:
for item in data["test_case_score"]:
if item["score"] <= 0:
return self.error("Invalid score")
# todo check filename and score info # todo check filename and score info
data["created_by"] = request.user
data["contest"] = contest data["contest"] = contest
tags = data.pop("tags") tags = data.pop("tags")
data["languages"] = list(data["languages"])
problem = Problem.objects.create(**data) problem = Problem.objects.create(**data)
for item in tags: for item in tags:
@ -291,6 +262,7 @@ class ContestProblemAPI(APIView):
problem.tags.add(tag) problem.tags.add(tag)
return self.success(ContestProblemAdminSerializer(problem).data) return self.success(ContestProblemAdminSerializer(problem).data)
@problem_permission_required
def get(self, request): def get(self, request):
problem_id = request.GET.get("id") problem_id = request.GET.get("id")
contest_id = request.GET.get("contest_id") contest_id = request.GET.get("contest_id")
@ -314,3 +286,53 @@ class ContestProblemAPI(APIView):
if keyword: if keyword:
problems = problems.filter(title__contains=keyword) problems = problems.filter(title__contains=keyword)
return self.success(self.paginate_data(request, problems, ContestProblemAdminSerializer)) return self.success(self.paginate_data(request, problems, ContestProblemAdminSerializer))
@validate_serializer(EditContestProblemSerializer)
@problem_permission_required
def put(self, request):
data = request.data
try:
contest = Contest.objects.get(id=data.pop("contest_id"))
if request.user.is_admin() and contest.created_by != request.user:
return self.error("Contest does not exist")
except Contest.DoesNotExist:
return self.error("Contest does not exist")
if data["rule_type"] != contest.rule_type:
return self.error("Invalid rule type")
problem_id = data.pop("id")
user = request.user
try:
problem = Problem.objects.get(id=problem_id, contest=contest)
if not user.can_mgmt_all_problem() and problem.created_by != user:
return self.error("Problem does not exist")
except Problem.DoesNotExist:
return self.error("Problem does not exist")
_id = data["_id"]
if not _id:
return self.error("Display ID is required")
if Problem.objects.exclude(id=problem_id).filter(_id=_id, contest=contest).exists():
return self.error("Display ID already exists")
error_info = self.common_checks(request)
if error_info:
return self.error(error_info)
# todo check filename and score info
tags = data.pop("tags")
data["languages"] = list(data["languages"])
for k, v in data.items():
setattr(problem, k, v)
problem.save()
problem.tags.remove(*problem.tags.all())
for tag in tags:
try:
tag = ProblemTag.objects.get(name=tag)
except ProblemTag.DoesNotExist:
tag = ProblemTag.objects.create(name=tag)
problem.tags.add(tag)
return self.success()