diff --git a/account/serializers.py b/account/serializers.py index 112d59db..68eca7c9 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -1,6 +1,8 @@ +from django import forms + from utils.api import DateTimeTZField, serializers -from .models import AdminType, ProblemPermission, User +from .models import AdminType, ProblemPermission, User, UserProfile class UserLoginSerializer(serializers.Serializer): @@ -32,6 +34,18 @@ class UserSerializer(serializers.ModelSerializer): "create_time", "last_login", "two_factor_auth", "open_api", "is_disabled"] +class UserProfileSerializer(serializers.ModelSerializer): + + class Meta: + model = UserProfile + + +class UserInfoSerializer(serializers.ModelSerializer): + + class Meta: + model = UserProfile + + class EditUserSerializer(serializers.Serializer): id = serializers.IntegerField() username = serializers.CharField(max_length=30) @@ -46,6 +60,16 @@ class EditUserSerializer(serializers.Serializer): is_disabled = serializers.BooleanField() +class EditUserProfileSerializer(serializers.Serializer): + avatar = serializers.CharField(max_length=100, allow_null=True, required=False) + blog = serializers.URLField(allow_null=True, required=False) + mood = serializers.CharField(max_length=200, allow_null=True, required=False) + phone_number = serializers.CharField(max_length=15, allow_null=True, required=False, ) + school = serializers.CharField(max_length=200, allow_null=True, required=False) + major = serializers.CharField(max_length=200, allow_null=True, required=False) + student_id = serializers.CharField(max_length=15, allow_null=True, required=False) + + class ApplyResetPasswordSerializer(serializers.Serializer): email = serializers.EmailField() captcha = serializers.CharField(max_length=4, min_length=4) @@ -64,3 +88,7 @@ class SSOSerializer(serializers.Serializer): class TwoFactorAuthCodeSerializer(serializers.Serializer): code = serializers.IntegerField() + + +class AvatarUploadForm(forms.Form): + file = forms.FileField() diff --git a/account/urls/oj.py b/account/urls/oj.py index fa47e33d..36b28ce5 100644 --- a/account/urls/oj.py +++ b/account/urls/oj.py @@ -8,5 +8,6 @@ urlpatterns = [ url(r"^register/?$", UserRegisterAPI.as_view(), name="user_register_api"), url(r"^change_password/?$", UserChangePasswordAPI.as_view(), name="user_change_password_api"), url(r"^apply_reset_password/?$", ApplyResetPasswordAPI.as_view(), name="apply_reset_password_api"), - url(r"^reset_password/?$", ResetPasswordAPI.as_view(), name="apply_reset_password_api") + url(r"^reset_password/?$", ResetPasswordAPI.as_view(), name="apply_reset_password_api"), + url(r"^captcha/?$", "utils.captcha.views.show_captcha", name="show_captcha"), ] diff --git a/account/urls/user.py b/account/urls/user.py index 1676ddce..1c3ad368 100644 --- a/account/urls/user.py +++ b/account/urls/user.py @@ -4,7 +4,7 @@ from ..views.user import (SSOAPI, AvatarUploadAPI, TwoFactorAuthAPI, UserInfoAPI, UserProfileAPI) urlpatterns = [ - url(r"^user/?$", UserInfoAPI.as_view(), name="user_info_api"), + url(r"^user/(?P\w+)/?$", UserInfoAPI.as_view(), name="user_info_api"), url(r"^profile/?$", UserProfileAPI.as_view(), name="user_profile_api"), url(r"^avatar/upload/?$", AvatarUploadAPI.as_view(), name="avatar_upload_api"), url(r"^sso/?$", SSOAPI.as_view(), name="sso_api"), diff --git a/account/views/oj.py b/account/views/oj.py index 7db3bbb1..39219eee 100644 --- a/account/views/oj.py +++ b/account/views/oj.py @@ -60,8 +60,8 @@ class UserRegisterAPI(APIView): """ data = request.data captcha = Captcha(request) - if not captcha.check(data["captcha"]): - return self.error("Invalid captcha") + # if not captcha.check(data["captcha"]): + # return self.error("Invalid captcha") try: User.objects.get(username=data["username"]) return self.error("Username already exists") diff --git a/account/views/user.py b/account/views/user.py index 19eb893d..727bd780 100644 --- a/account/views/user.py +++ b/account/views/user.py @@ -4,25 +4,37 @@ from io import StringIO import qrcode from django.conf import settings from django.http import HttpResponse +from django.views.decorators.csrf import ensure_csrf_cookie +from django.utils.decorators import method_decorator from otpauth import OtpAuth from conf.models import WebsiteConfig -from utils.api import APIView, validate_serializer +from utils.api import APIView, validate_serializer, CSRFExemptAPIView from utils.shortcuts import rand_str from ..decorators import login_required -from ..models import User +from ..models import User, UserProfile from ..serializers import (EditUserSerializer, SSOSerializer, - TwoFactorAuthCodeSerializer, UserSerializer) + TwoFactorAuthCodeSerializer, UserSerializer, + UserProfileSerializer, UserInfoSerializer, + EditUserProfileSerializer, AvatarUploadForm) class UserInfoAPI(APIView): - @login_required - def get(self, request): + # @login_required + @method_decorator(ensure_csrf_cookie) + def get(self, request, **kwargs): """ Return user info api """ - return self.success(UserSerializer(request.user).data) + try: + user = User.objects.get(username=kwargs["username"]) + except User.DoesNotExist: + return self.error("User does not exist") + profile = UserProfile.objects.get(user=user) + dit = UserProfileSerializer(profile).data + dit['user'] = UserSerializer(user).data + return self.success(dit) class UserProfileAPI(APIView): @@ -31,14 +43,22 @@ class UserProfileAPI(APIView): """ Return user info api """ - return self.success(UserSerializer(request.user).data) + try: + user = User.objects.get(id=request.user.id) + except User.DoesNotExist: + return self.error("User does not exist") + profile = UserProfile.objects.get(user=user) + dit = UserProfileSerializer(profile).data + dit['user'] = UserSerializer(user).data + return self.success(dit) - @validate_serializer(EditUserSerializer) + @validate_serializer(EditUserProfileSerializer) @login_required def put(self, request): data = request.data user_profile = request.user.userprofile - if data["avatar"]: + print(data) + if data.get("avatar"): user_profile.avatar = data["avatar"] else: user_profile.mood = data["mood"] @@ -52,21 +72,25 @@ class UserProfileAPI(APIView): return self.success("Succeeded") -class AvatarUploadAPI(APIView): - def post(self, request): - if "file" not in request.FILES: - return self.error("Upload failed") +class AvatarUploadAPI(CSRFExemptAPIView): + request_parsers = () - f = request.FILES["file"] - if f.size > 1024 * 1024: + def post(self, request): + form = AvatarUploadForm(request.POST, request.FILES) + if form.is_valid(): + avatar = form.cleaned_data["file"] + else: + return self.error("Upload failed") + if avatar.size > 1024 * 1024: return self.error("Picture too large") - if os.path.splitext(f.name)[-1].lower() not in [".gif", ".jpg", ".jpeg", ".bmp", ".png"]: + if os.path.splitext(avatar.name)[-1].lower() not in [".gif", ".jpg", ".jpeg", ".bmp", ".png"]: return self.error("Unsupported file format") - name = "avatar_" + rand_str(5) + os.path.splitext(f.name)[-1] + name = "avatar_" + rand_str(5) + os.path.splitext(avatar.name)[-1] with open(os.path.join(settings.IMAGE_UPLOAD_DIR, name), "wb") as img: - for chunk in request.FILES["file"]: + for chunk in avatar: img.write(chunk) + print(os.path.join(settings.IMAGE_UPLOAD_DIR, name)) return self.success({"path": "/static/upload/" + name})