From 8b0ad78b1a8c850efb7b75e8d97b16ee79fc6358 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 3 Aug 2015 16:52:31 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=90=8D=E6=98=AF=E5=90=A6=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=9A=84=20api=20=E6=8E=A5=E5=8F=A3=E5=92=8C=E7=9B=B8=E5=BA=94?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- account/serializers.py | 5 +++++ account/tests.py | 19 +++++++++++++++++++ account/views.py | 22 ++++++++++++++++++++-- oj/urls.py | 3 ++- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/account/serializers.py b/account/serializers.py index ffa6b3b..659641d 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -5,3 +5,8 @@ from rest_framework import serializers class UserLoginSerializer(serializers.Serializer): username = serializers.CharField(max_length=30) password = serializers.CharField(max_length=30) + + +class UsernameCheckSerializer(serializers.Serializer): + username = serializers.CharField(max_length=30) + diff --git a/account/tests.py b/account/tests.py index 12d087a..d087e8f 100644 --- a/account/tests.py +++ b/account/tests.py @@ -36,3 +36,22 @@ class UserLoginAPITest(APITestCase): data = {"username": "test", "password": "test"} response = self.client.post(self.url, data=data) self.assertEqual(response.data, {"code": 0, "data": u"登录成功"}) + + +class UsernameCheckTest(APITestCase): + def setUp(self): + self.client = APIClient() + self.url = reverse("username_check_api") + User.objects.create(username="testtest") + + def test_invalid_data(self): + response = self.client.post(self.url, data={"username111": "testtest"}) + self.assertEqual(response.data["code"], 1) + + def test_username_exists(self): + response = self.client.post(self.url, data={"username": "testtest"}) + self.assertEqual(response.data, {"code": 0, "data": True}) + + def test_username_does_not_exist(self): + response = self.client.post(self.url, data={"username": "testtest123"}) + self.assertEqual(response.data, {"code": 0, "data": False}) diff --git a/account/views.py b/account/views.py index 8c97320..8a90367 100644 --- a/account/views.py +++ b/account/views.py @@ -6,7 +6,7 @@ from rest_framework.views import APIView from utils.shortcuts import serializer_invalid_response, error_response, success_response from .models import User -from .serializers import UserLoginSerializer +from .serializers import UserLoginSerializer, UsernameCheckSerializer class UserLoginAPIView(APIView): @@ -43,4 +43,22 @@ class UserChangePasswordView(APIView): pass def post(self, request): - pass \ No newline at end of file + pass + + +class UsernameCheckAPIView(APIView): + def post(self, request): + """ + 检测用户名是否存在,存在返回True,不存在返回False + --- + request_serializer: UsernameCheckSerializer + """ + serializer = UsernameCheckSerializer(data=request.DATA) + if serializer.is_valid(): + try: + User.objects.get(username=serializer.data["username"]) + return success_response(True) + except User.DoesNotExist: + return success_response(False) + else: + return serializer_invalid_response(serializer) \ No newline at end of file diff --git a/oj/urls.py b/oj/urls.py index 260a42a..5075e09 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -3,7 +3,7 @@ from django.conf.urls import include, url from django.contrib import admin from django.views.generic import TemplateView -from account.views import UserLoginAPIView +from account.views import UserLoginAPIView, UsernameCheckAPIView urlpatterns = [ url("^$", TemplateView.as_view(template_name="oj/index.html"), name="index_page"), @@ -12,6 +12,7 @@ urlpatterns = [ url(r'^login/$', TemplateView.as_view(template_name="oj/account/login.html"), name="user_login_page"), url(r'^api/login/$', UserLoginAPIView.as_view(), name="login_api"), url(r'^api/login/$', UserLoginAPIView.as_view(), name="user_login_api"), + url(r'^api/username_check/$', UsernameCheckAPIView.as_view(), name="username_check_api"), url(r'^problem/(?P\d+)/$', "problem.views.problem_page", name="problem_page"), url(r'^admin/contest/$', TemplateView.as_view(template_name="admin/contest/add_contest.html"), name="add_contest_page"), From b3d5519987b19b8f156a2897c231cfcbe5560c67 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Mon, 3 Aug 2015 17:14:44 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E5=88=A0=E9=99=A4=20urls=20=E9=87=8C?= =?UTF-8?q?=E9=9D=A2=E5=A4=9A=E4=BD=99=E7=9A=84=20login=20url[CI=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oj/urls.py | 1 - 1 file changed, 1 deletion(-) diff --git a/oj/urls.py b/oj/urls.py index 5075e09..04ae75f 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -10,7 +10,6 @@ urlpatterns = [ url(r'^docs/', include('rest_framework_swagger.urls')), url(r'^admin/$', TemplateView.as_view(template_name="admin/index.html"), name="admin_index_page"), url(r'^login/$', TemplateView.as_view(template_name="oj/account/login.html"), name="user_login_page"), - url(r'^api/login/$', UserLoginAPIView.as_view(), name="login_api"), url(r'^api/login/$', UserLoginAPIView.as_view(), name="user_login_api"), url(r'^api/username_check/$', UsernameCheckAPIView.as_view(), name="username_check_api"), url(r'^problem/(?P\d+)/$', "problem.views.problem_page", name="problem_page"), From 2a2ef36d14a43cfe78f628166c2aea630720b514 Mon Sep 17 00:00:00 2001 From: hohoTT <609029365@qq.com> Date: Mon, 3 Aug 2015 18:45:26 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E4=BB=A3=E7=A0=81=E5=92=8CAPI=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- account/serializers.py | 6 ++++++ account/tests.py | 23 +++++++++++++++++++++++ account/views.py | 26 ++++++++++++++++++++------ oj/urls.py | 3 ++- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/account/serializers.py b/account/serializers.py index 659641d..af229fb 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -10,3 +10,9 @@ class UserLoginSerializer(serializers.Serializer): class UsernameCheckSerializer(serializers.Serializer): username = serializers.CharField(max_length=30) + +class UserRegisterSerializer(serializers.Serializer): + username = serializers.CharField(max_length=30) + real_name = serializers.CharField(max_length=30) + password = serializers.CharField(max_length=30, min_length=6) + diff --git a/account/tests.py b/account/tests.py index d087e8f..8a3ef0c 100644 --- a/account/tests.py +++ b/account/tests.py @@ -55,3 +55,26 @@ class UsernameCheckTest(APITestCase): def test_username_does_not_exist(self): response = self.client.post(self.url, data={"username": "testtest123"}) self.assertEqual(response.data, {"code": 0, "data": False}) + + +class UserRegisterAPITest(APITestCase): + def setUp(self): + self.client = APIClient() + self.url = reverse("user_register_api") + + def test_invalid_data(self): + data = {"username": "test", "real_name": "TT"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 1) + + def test_short_password(self): + data = {"username": "test", "real_name": "TT", "password": "qq"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 1) + + def test_same_username(self): + User.objects.create(username="aa", real_name="ww") + data = {"username": "aa", "real_name": "ww", "password": "zzzzzzz"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data, {"code": 1, "data": u"用户名已存在"}) + diff --git a/account/views.py b/account/views.py index 8a90367..35eace5 100644 --- a/account/views.py +++ b/account/views.py @@ -6,7 +6,7 @@ from rest_framework.views import APIView from utils.shortcuts import serializer_invalid_response, error_response, success_response from .models import User -from .serializers import UserLoginSerializer, UsernameCheckSerializer +from .serializers import UserLoginSerializer, UsernameCheckSerializer, UserRegisterSerializer class UserLoginAPIView(APIView): @@ -30,12 +30,26 @@ class UserLoginAPIView(APIView): return serializer_invalid_response(serializer) -class UserRegisterView(APIView): - def get(self, request): - pass - +class UserRegisterAPIView(APIView): def post(self, request): - pass + """ + 用户注册json api接口 + --- + request_serializer: UserRegisterSerializer + """ + serializer = UserRegisterSerializer(data=request.DATA) + if serializer.is_valid(): + data = serializer.data + try: + User.objects.get(username=data["username"]) + return error_response(u"用户名已存在") + except User.DoesNotExist: + user = User.objects.create(username=data["username"], real_name=data["real_name"]) + user.set_password(data["password"]) + user.save() + return success_response(u"注册成功!") + else: + return serializer_invalid_response(serializer) class UserChangePasswordView(APIView): diff --git a/oj/urls.py b/oj/urls.py index 04ae75f..33d9284 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -3,7 +3,7 @@ from django.conf.urls import include, url from django.contrib import admin from django.views.generic import TemplateView -from account.views import UserLoginAPIView, UsernameCheckAPIView +from account.views import UserLoginAPIView, UsernameCheckAPIView, UserRegisterAPIView urlpatterns = [ url("^$", TemplateView.as_view(template_name="oj/index.html"), name="index_page"), @@ -11,6 +11,7 @@ urlpatterns = [ url(r'^admin/$', TemplateView.as_view(template_name="admin/index.html"), name="admin_index_page"), url(r'^login/$', TemplateView.as_view(template_name="oj/account/login.html"), name="user_login_page"), url(r'^api/login/$', UserLoginAPIView.as_view(), name="user_login_api"), + url(r'^api/register/$', UserRegisterAPIView.as_view(), name="user_register_api"), url(r'^api/username_check/$', UsernameCheckAPIView.as_view(), name="username_check_api"), url(r'^problem/(?P\d+)/$', "problem.views.problem_page", name="problem_page"), From b7280719ac9b093273f23525a47b335ff0b4160b Mon Sep 17 00:00:00 2001 From: hohoTT <609029365@qq.com> Date: Mon, 3 Aug 2015 19:54:55 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=AF=86=E7=A0=81=E5=92=8C=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E7=9A=84API=E6=B5=8B=E8=AF=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- account/serializers.py | 6 ++++++ account/tests.py | 21 +++++++++++++++++++++ account/views.py | 26 ++++++++++++++++++++------ oj/urls.py | 3 ++- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/account/serializers.py b/account/serializers.py index af229fb..41634b7 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -16,3 +16,9 @@ class UserRegisterSerializer(serializers.Serializer): real_name = serializers.CharField(max_length=30) password = serializers.CharField(max_length=30, min_length=6) + +class UserChangePasswordSerializer(serializers.Serializer): + username = serializers.CharField(max_length=30) + old_password = serializers.CharField(max_length=30, min_length=6) + new_password = serializers.CharField(max_length=30, min_length=6) + diff --git a/account/tests.py b/account/tests.py index 8a3ef0c..90e5d12 100644 --- a/account/tests.py +++ b/account/tests.py @@ -78,3 +78,24 @@ class UserRegisterAPITest(APITestCase): response = self.client.post(self.url, data=data) self.assertEqual(response.data, {"code": 1, "data": u"用户名已存在"}) + +class UserChangePasswordAPITest(APITestCase): + def setUp(self): + self.client = APIClient() + self.url = reverse("user_change_password_api") + User.objects.create(username="test", password="aaabbb") + + def test_error_old_password(self): + data = {"username": "test", "old_password": "aaaccc", "new_password": "aaaddd"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data, {"code": 1, "data": u"密码不正确,请重新修改!"}) + + def test_invalid_data_format(self): + data = {"username": "test", "old_password": "aaa", "new_password": "aaaddd"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 1) + + def test_username_does_not_exist(self): + data = {"username": "test1", "old_password": "aaabbb", "new_password": "aaaddd"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 1) \ No newline at end of file diff --git a/account/views.py b/account/views.py index 35eace5..dd05874 100644 --- a/account/views.py +++ b/account/views.py @@ -6,7 +6,8 @@ from rest_framework.views import APIView from utils.shortcuts import serializer_invalid_response, error_response, success_response from .models import User -from .serializers import UserLoginSerializer, UsernameCheckSerializer, UserRegisterSerializer +from .serializers import UserLoginSerializer, UsernameCheckSerializer, UserRegisterSerializer, \ + UserChangePasswordSerializer class UserLoginAPIView(APIView): @@ -52,12 +53,25 @@ class UserRegisterAPIView(APIView): return serializer_invalid_response(serializer) -class UserChangePasswordView(APIView): - def get(self, request): - pass - +class UserChangePasswordAPIView(APIView): def post(self, request): - pass + """ + 用户修改密码json api接口 + --- + request_serializer: UserChangePasswordSerializer + """ + serializer = UserChangePasswordSerializer(data=request.DATA) + if serializer.is_valid(): + data = serializer.data + user = auth.authenticate(username=data["username"], password=data["old_password"]) + if user: + user.set_password(data["new_password"]) + user.save() + return success_response(u"用户密码修改成功!") + else: + return error_response(u"密码不正确,请重新修改!") + else: + return serializer_invalid_response(serializer) class UsernameCheckAPIView(APIView): diff --git a/oj/urls.py b/oj/urls.py index 33d9284..fc652b3 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -3,7 +3,7 @@ from django.conf.urls import include, url from django.contrib import admin from django.views.generic import TemplateView -from account.views import UserLoginAPIView, UsernameCheckAPIView, UserRegisterAPIView +from account.views import UserLoginAPIView, UsernameCheckAPIView, UserRegisterAPIView, UserChangePasswordAPIView urlpatterns = [ url("^$", TemplateView.as_view(template_name="oj/index.html"), name="index_page"), @@ -12,6 +12,7 @@ urlpatterns = [ url(r'^login/$', TemplateView.as_view(template_name="oj/account/login.html"), name="user_login_page"), url(r'^api/login/$', UserLoginAPIView.as_view(), name="user_login_api"), url(r'^api/register/$', UserRegisterAPIView.as_view(), name="user_register_api"), + url(r'^api/change_password/$', UserChangePasswordAPIView.as_view(), name="user_change_password_api"), url(r'^api/username_check/$', UsernameCheckAPIView.as_view(), name="username_check_api"), url(r'^problem/(?P\d+)/$', "problem.views.problem_page", name="problem_page"), From c72624e2d5e997e18a741d2207694d5c8757b22f Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Tue, 4 Aug 2015 13:22:37 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20login=5Frequired=20dec?= =?UTF-8?q?orator=20=E5=92=8C=E5=AF=B9=E5=BA=94=E7=9A=84=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- account/decorators.py | 24 +++++++++++++ account/test_urls.py | 12 +++++++ account/tests.py | 79 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 account/decorators.py create mode 100644 account/test_urls.py diff --git a/account/decorators.py b/account/decorators.py new file mode 100644 index 0000000..6b10896 --- /dev/null +++ b/account/decorators.py @@ -0,0 +1,24 @@ +# coding=utf-8 +from django.http import HttpResponse +from django.shortcuts import render + +from utils.shortcuts import error_response +from .models import User + + +def login_required(func): + def check(*args, **kwargs): + # 在class based views 里面,args 有两个元素,一个是self, 第二个才是request, + # 在function based views 里面,args 只有request 一个参数 + request = args[-1] + if request.user.is_authenticated(): + return func(*args, **kwargs) + if request.is_ajax(): + return error_response(u"请先登录") + else: + return render(request, "utils/error.html", {"error": u"请先登录"}) + return check + + +def admin_required(): + pass diff --git a/account/test_urls.py b/account/test_urls.py new file mode 100644 index 0000000..4066721 --- /dev/null +++ b/account/test_urls.py @@ -0,0 +1,12 @@ +# coding=utf-8 +from django.conf.urls import include, url + +from .tests import LoginRequiredCBVTestWithArgs, LoginRequiredCBVTestWithoutArgs + + +urlpatterns = [ + url(r'^test/fbv/1/$', "account.tests.login_required_FBV_test_without_args"), + url(r'^test/fbv/(?P\d+)/$', "account.tests.login_required_FBC_test_with_args"), + url(r'^test/cbv/1/$', LoginRequiredCBVTestWithoutArgs.as_view()), + url(r'^test/cbv/(?P\d+)/$', LoginRequiredCBVTestWithArgs.as_view()), +] diff --git a/account/tests.py b/account/tests.py index 90e5d12..83226b7 100644 --- a/account/tests.py +++ b/account/tests.py @@ -1,10 +1,16 @@ # coding=utf-8 +import json + from django.core.urlresolvers import reverse from django.test import TestCase, Client +from django.http import HttpResponse from rest_framework.test import APITestCase, APIClient +from rest_framework.views import APIView +from rest_framework.response import Response from .models import User +from .decorators import login_required class UserLoginTest(TestCase): @@ -98,4 +104,75 @@ class UserChangePasswordAPITest(APITestCase): def test_username_does_not_exist(self): data = {"username": "test1", "old_password": "aaabbb", "new_password": "aaaddd"} response = self.client.post(self.url, data=data) - self.assertEqual(response.data["code"], 1) \ No newline at end of file + self.assertEqual(response.data["code"], 1) + + +@login_required +def login_required_FBV_test_without_args(request): + return HttpResponse("function based view test1") + + +@login_required +def login_required_FBC_test_with_args(request, problem_id): + return HttpResponse(problem_id) + + +class LoginRequiredCBVTestWithoutArgs(APIView): + @login_required + def get(self, request): + return HttpResponse("class based view login required test1") + +class LoginRequiredCBVTestWithArgs(APIView): + @login_required + def get(self, request, problem_id): + return HttpResponse(problem_id) + + +class LoginRequiredDecoratorTest(TestCase): + urls = 'account.test_urls' + + def setUp(self): + self.client = Client() + user = User.objects.create(username="test") + user.set_password("test") + user.save() + + def test_fbv_without_args(self): + # 没登陆 + response = self.client.get("/test/fbv/1/") + self.assertTemplateUsed(response, "utils/error.html") + + # 登陆后 + self.client.login(username="test", password="test") + response = self.client.get("/test/fbv/1/") + self.assertEqual(response.content, "function based view test1") + + def test_fbv_with_args(self): + # 没登陆 + response = self.client.get("/test/fbv/1024/") + self.assertTemplateUsed(response, "utils/error.html") + + # 登陆后 + self.client.login(username="test", password="test") + response = self.client.get("/test/fbv/1024/") + self.assertEqual(response.content, "1024") + + def test_cbv_without_args(self): + # 没登陆 + response = self.client.get("/test/cbv/1/") + self.assertTemplateUsed(response, "utils/error.html") + + # 登陆后 + self.client.login(username="test", password="test") + response = self.client.get("/test/cbv/1/") + self.assertEqual(response.content, "class based view login required test1") + + def test_cbv_with_args(self): + # 没登陆 + response = self.client.get("/test/cbv/1024/", HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertEqual(json.loads(response.content), {"code": 1, "data": u"请先登录"}) + + # 登陆后 + self.client.login(username="test", password="test") + response = self.client.get("/test/cbv/1024/") + self.assertEqual(response.content, "1024")