diff --git a/account/views.py b/account/views.py index 09c1e6a7..53076757 100644 --- a/account/views.py +++ b/account/views.py @@ -1,4 +1,5 @@ # coding=utf-8 +import codecs from django import http from django.contrib import auth from django.shortcuts import render @@ -9,6 +10,9 @@ from rest_framework.views import APIView from rest_framework.response import Response from utils.shortcuts import serializer_invalid_response, error_response, success_response, paginate, rand_str from utils.captcha import Captcha +from mail.tasks import send_email + +from envelopes import Envelope from .decorators import login_required from .models import User @@ -32,15 +36,27 @@ class UserLoginAPIView(APIView): user = auth.authenticate(username=data["username"], password=data["password"]) # 用户名或密码错误的话 返回None if user: - if user.admin_type > 0: + # 管理员必须使用验证码 多次错误的使用验证码 + if user.admin_type > 0 or user.login_failed_counter: if "captcha" not in data: return error_response(u"请填写验证码!") captcha = Captcha(request) if not captcha.check(data["captcha"]): return error_response(u"验证码错误") auth.login(request, user) + # 登陆成功,计数器减去1 + if user.login_failed_counter > 0: + user.login_failed_counter -= 1 + user.save() return success_response(u"登录成功") else: + # 登陆失败,计数器加3 + try: + user = User.objects.get(username=data["username"]) + user.login_failed_counter += 3 + user.save() + except User.DoesNotExist: + pass return error_response(u"用户名或密码错误") else: return serializer_invalid_response(serializer) @@ -230,13 +246,18 @@ class AccountSecurityAPIView(APIView): user = User.objects.get(username=username) except User.DoesNotExist: return success_response({"applied_captcha": True}) - if user.admin_type > 0: + if user.admin_type > 0 or user.login_failed_counter > 0: return success_response({"applied_captcha": True}) return success_response({"applied_captcha": False}) class ApplyResetPasswordAPIView(APIView): def post(self, request): + """ + 提交请求重置密码 + --- + request_serializer: ApplyResetPasswordSerializer + """ serializer = ApplyResetPasswordSerializer(data=request.data) if serializer.is_valid(): data = serializer.data @@ -249,9 +270,11 @@ class ApplyResetPasswordAPIView(APIView): return error_response(u"用户不存在") user.reset_password_token = rand_str() user.save() - # todo - email_template = open(settings.TEMPLATES[0]["DIRS"][0] + "utils/reset_password_email.html", "r").read() - email_template.replace("{{ username }}", user.username).replace("{{ link }}", "/reset_password/?token=" + user.reset_password_token) + email_template = codecs.open(settings.TEMPLATES[0]["DIRS"][0] + "utils/reset_password_email.html", "r", "utf-8").read() + + email_template = email_template.replace("{{ username }}", user.username).replace("{{ link }}", request.scheme + "://" + request.META['HTTP_HOST'] + "/reset_password/?token=" + user.reset_password_token) + + send_email(user.email, user.username, u"qduoj 密码找回邮件", email_template) return success_response(u"邮件发生成功") else: return serializer_invalid_response(serializer) diff --git a/mail/tasks.py b/mail/tasks.py index 9bad5790..c3145481 100644 --- a/mail/tasks.py +++ b/mail/tasks.py @@ -1 +1,14 @@ # coding=utf-8 + + +def send_email(*args, **kwargs): + pass + + +''' +envelope = Envelope(from_addr=("noreply@qduoj.com", u"qduoj 密码找回邮件", email_template), + to_addr=(user.email, user.username), + subject=u"qduoj 密码找回邮件", + html_body=email_template) +envelope.send("smtp.mxhichina.com", login="noreply@qduoj.com", password="092122302Zarpe2015", tls=False) +''' \ No newline at end of file diff --git a/oj/settings.py b/oj/settings.py index 8231216c..849885ce 100644 --- a/oj/settings.py +++ b/oj/settings.py @@ -51,6 +51,7 @@ INSTALLED_APPS = ( 'mq', 'contest', 'contest_submission', + 'mail', 'django_extensions', 'rest_framework', diff --git a/oj/urls.py b/oj/urls.py index d1b84d5b..94935e12 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -1,10 +1,12 @@ # coding=utf-8 +from django.conf import settings from django.conf.urls import include, url from django.views.generic import TemplateView from account.views import (UserLoginAPIView, UsernameCheckAPIView, UserRegisterAPIView, UserChangePasswordAPIView, EmailCheckAPIView, - UserAdminAPIView, UserInfoAPIView, AccountSecurityAPIView) + UserAdminAPIView, UserInfoAPIView, AccountSecurityAPIView, + ApplyResetPasswordAPIView) from announcement.views import AnnouncementAdminAPIView @@ -28,7 +30,7 @@ from contest_submission.views import contest_problem_my_submissions_list_page urlpatterns = [ url("^$", "account.views.index_page", name="index_page"), - url(r'^docs/', include('rest_framework_swagger.urls')), + url(r'^admin/$', TemplateView.as_view(template_name="admin/admin.html"), name="admin_spa_page"), url(r'^admin/contest/$', TemplateView.as_view(template_name="admin/contest/add_contest.html"), name="add_contest_page"), @@ -120,4 +122,15 @@ urlpatterns = [ url(r'^api/contest/time/$', ContestTimeAPIView.as_view(), name="contest_time_api_view"), url(r'^api/admin/rejudge/$', SubmissionRejudgeAdminAPIView.as_view(), name="submission_rejudge_api"), + + url(r'^user/(?P\w+)/$', "account.views.user_index_page"), + + url(r'^api/reset_password/$', ApplyResetPasswordAPIView.as_view(), name="apply_reset_password_api"), + + url(r'^account/settings/$', TemplateView.as_view(template_name="oj/account/settings.html"), name="account_setting_page"), + url(r'^account/settings/avatar/$', TemplateView.as_view(template_name="oj/account/avatar.html"), name="avatar_settings_page"), ] + + +if settings.DEBUG: + urlpatterns.append(url(r'^docs/', include('rest_framework_swagger.urls'))) \ No newline at end of file