diff --git a/account/serializers.py b/account/serializers.py index 179d28d..4cda3ae 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -27,6 +27,7 @@ class UserRegisterSerializer(serializers.Serializer): class UserChangePasswordSerializer(serializers.Serializer): old_password = serializers.CharField() new_password = serializers.CharField(max_length=30, min_length=6) + captcha = serializers.CharField(max_length=4, min_length=4) class UserSerializer(serializers.ModelSerializer): diff --git a/account/views.py b/account/views.py index 1da8967..1304ded 100644 --- a/account/views.py +++ b/account/views.py @@ -7,6 +7,7 @@ from django.db.models import Q from rest_framework.views import APIView from utils.shortcuts import serializer_invalid_response, error_response, success_response, paginate +from utils.captcha import Captcha from .decorators import login_required from .models import User @@ -79,6 +80,9 @@ class UserChangePasswordAPIView(APIView): serializer = UserChangePasswordSerializer(data=request.data) if serializer.is_valid(): data = serializer.data + captcha = Captcha(request) + if not captcha.check(data["captcha"]): + return error_response(u"验证码错误") username = request.user.username user = auth.authenticate(username=username, password=data["old_password"]) if user: diff --git a/contest/migrations/0007_contestsubmission_ac_time.py b/contest/migrations/0007_contestsubmission_ac_time.py new file mode 100644 index 0000000..d7bc904 --- /dev/null +++ b/contest/migrations/0007_contestsubmission_ac_time.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('contest', '0006_merge'), + ] + + operations = [ + migrations.AddField( + model_name='contestsubmission', + name='ac_time', + field=models.IntegerField(default=0), + ), + ] diff --git a/contest/models.py b/contest/models.py index cab1cc6..a76913b 100644 --- a/contest/models.py +++ b/contest/models.py @@ -90,6 +90,8 @@ class ContestSubmission(models.Model): total_submission_number = models.IntegerField(default=1) # 这道题是 AC 还是没过 ac = models.BooleanField() + # ac 用时 + ac_time = models.IntegerField(default=0) # 总的时间,用于acm 类型的,也需要保存罚时 total_time = models.IntegerField(default=0) diff --git a/contest/views.py b/contest/views.py index 30e9408..3bb1d8f 100644 --- a/contest/views.py +++ b/contest/views.py @@ -404,8 +404,8 @@ def _cmp(x, y): def contest_rank_page(request, contest_id): contest = Contest.objects.get(id=contest_id) contest_problems = ContestProblem.objects.filter(contest=contest).order_by("sort_index") - result = ContestSubmission.objects.filter(contest=contest).values("user_id").annotate( - total_submit=Sum("total_submission_number")) + result = ContestSubmission.objects.filter(contest=contest).values("user_id").\ + annotate(total_submit=Sum("total_submission_number")) for i in range(0, len(result)): # 这个人所有的提交 submissions = ContestSubmission.objects.filter(user_id=result[i]["user_id"], contest_id=contest_id) diff --git a/mq/scripts/info.py b/mq/scripts/info.py index 119845c..a3e13b9 100644 --- a/mq/scripts/info.py +++ b/mq/scripts/info.py @@ -60,11 +60,12 @@ class MessageQueue(object): # 避免这道题已经 ac 了,但是又重新提交了一遍 if not contest_submission.ac: # 这种情况是这个题目前处于错误状态,就使用已经存储了的罚时加上这道题的实际用时 - logger.debug(contest.start_time) - logger.debug(submission.create_time) - logger.debug((submission.create_time - contest.start_time).total_seconds()) - logger.debug(int((submission.create_time - contest.start_time).total_seconds() / 60)) - contest_submission.total_time += int((submission.create_time - contest.start_time).total_seconds() / 60) + # logger.debug(contest.start_time) + # logger.debug(submission.create_time) + # logger.debug((submission.create_time - contest.start_time).total_seconds()) + # logger.debug(int((submission.create_time - contest.start_time).total_seconds() / 60)) + contest_submission.ac_time = int((submission.create_time - contest.start_time).total_seconds() / 60) + contest_submission.total_time += contest_submission.ac_time # 标记为已经通过 contest_submission.ac = True # contest problem ac 计数器加1 diff --git a/oj/urls.py b/oj/urls.py index a5582d2..8d6e819 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -112,4 +112,5 @@ urlpatterns = [ url(r'^help/$', TemplateView.as_view(template_name="utils/help.html"), name="help_page"), url(r'^api/submission/share/$', SubmissionShareAPIView.as_view(), name="submission_share_api"), + url(r'^captcha/$', "utils.captcha.views.show_captcha", name="show_captcha"), ] diff --git a/static/src/js/app/oj/account/change_password.js b/static/src/js/app/oj/account/change_password.js index 608114f..a66505d 100644 --- a/static/src/js/app/oj/account/change_password.js +++ b/static/src/js/app/oj/account/change_password.js @@ -1,13 +1,22 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, csrfTokenHeader) { + function refresh_captcha(){ + this.src = "/captcha/?" + Math.random(); + $("#captcha")[0].value = ""; + } + $("#captcha-img").click(function(){ + refresh_captcha(); + }); + $('form').validator().on('submit', function (e) { e.preventDefault(); var newPassword = $("#new_password ").val(); var password = $("#password").val(); + var captcha = $("#captcha").val(); $.ajax({ beforeSend: csrfTokenHeader, url: "/api/change_password/", - data: {new_password: newPassword, old_password: password}, + data: {new_password: newPassword, old_password: password, captcha: captcha}, dataType: "json", method: "post", success: function (data) { @@ -15,6 +24,7 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c window.location.href = "/login/"; } else { + refresh_captcha(); bsAlert(data.data); } } diff --git a/template/src/oj/account/change_password.html b/template/src/oj/account/change_password.html index dad9d14..d8099f5 100644 --- a/template/src/oj/account/change_password.html +++ b/template/src/oj/account/change_password.html @@ -17,7 +17,13 @@