mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 08:23:20 +00:00
整理代码
This commit is contained in:
parent
0647312124
commit
3b1f02c356
@ -15,6 +15,7 @@ class UsernameOrEmailCheckSerializer(serializers.Serializer):
|
|||||||
username = serializers.CharField(max_length=30, required=False)
|
username = serializers.CharField(max_length=30, required=False)
|
||||||
email = serializers.EmailField(max_length=30, required=False)
|
email = serializers.EmailField(max_length=30, required=False)
|
||||||
|
|
||||||
|
|
||||||
class UserRegisterSerializer(serializers.Serializer):
|
class UserRegisterSerializer(serializers.Serializer):
|
||||||
username = serializers.CharField(max_length=30)
|
username = serializers.CharField(max_length=30)
|
||||||
password = serializers.CharField(max_length=30, min_length=6)
|
password = serializers.CharField(max_length=30, min_length=6)
|
||||||
@ -46,7 +47,6 @@ class UserProfileSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class UserInfoSerializer(serializers.ModelSerializer):
|
class UserInfoSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserProfile
|
model = UserProfile
|
||||||
|
|
||||||
|
@ -2,7 +2,8 @@ from django.conf.urls import url
|
|||||||
|
|
||||||
from ..views.oj import (ApplyResetPasswordAPI, ResetPasswordAPI,
|
from ..views.oj import (ApplyResetPasswordAPI, ResetPasswordAPI,
|
||||||
UserChangePasswordAPI, UserRegisterAPI,
|
UserChangePasswordAPI, UserRegisterAPI,
|
||||||
UserLoginAPI, UserLogoutAPI, UsernameOrEmailCheck)
|
UserLoginAPI, UserLogoutAPI, UsernameOrEmailCheck,
|
||||||
|
SSOAPI, AvatarUploadAPI, TwoFactorAuthAPI, UserProfileAPI)
|
||||||
|
|
||||||
from utils.captcha.views import CaptchaAPIView
|
from utils.captcha.views import CaptchaAPIView
|
||||||
|
|
||||||
@ -14,5 +15,9 @@ urlpatterns = [
|
|||||||
url(r"^apply_reset_password/?$", ApplyResetPasswordAPI.as_view(), name="apply_reset_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/?$", CaptchaAPIView.as_view(), name="show_captcha"),
|
url(r"^captcha/?$", CaptchaAPIView.as_view(), name="show_captcha"),
|
||||||
url(r"^check_username_or_email", UsernameOrEmailCheck.as_view(), name="check_username_or_email")
|
url(r"^check_username_or_email", UsernameOrEmailCheck.as_view(), name="check_username_or_email"),
|
||||||
|
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"),
|
||||||
|
url(r"^two_factor_auth/?$", TwoFactorAuthAPI.as_view(), name="two_factor_auth_api")
|
||||||
]
|
]
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
from django.conf.urls import url
|
|
||||||
|
|
||||||
from ..views.user import (SSOAPI, AvatarUploadAPI, TwoFactorAuthAPI,
|
|
||||||
UserProfileAPI)
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
# url(r"^username/?$", UserNameAPI.as_view(), name="user_name_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"),
|
|
||||||
url(r"^two_factor_auth/?$", TwoFactorAuthAPI.as_view(), name="two_factor_auth_api")
|
|
||||||
]
|
|
@ -1,13 +1,18 @@
|
|||||||
|
import os
|
||||||
|
import qrcode
|
||||||
|
from io import BytesIO
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from otpauth import OtpAuth
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.core.exceptions import MultipleObjectsReturned
|
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from otpauth import OtpAuth
|
from django.http import HttpResponse
|
||||||
|
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
|
||||||
from conf.models import WebsiteConfig
|
from conf.models import WebsiteConfig
|
||||||
from utils.api import APIView, validate_serializer
|
from utils.api import APIView, validate_serializer, CSRFExemptAPIView
|
||||||
from utils.captcha import Captcha
|
from utils.captcha import Captcha
|
||||||
from utils.shortcuts import rand_str
|
from utils.shortcuts import rand_str
|
||||||
|
|
||||||
@ -17,9 +22,153 @@ from ..serializers import (ApplyResetPasswordSerializer,
|
|||||||
ResetPasswordSerializer,
|
ResetPasswordSerializer,
|
||||||
UserChangePasswordSerializer, UserLoginSerializer,
|
UserChangePasswordSerializer, UserLoginSerializer,
|
||||||
UserRegisterSerializer, UsernameOrEmailCheckSerializer)
|
UserRegisterSerializer, UsernameOrEmailCheckSerializer)
|
||||||
|
from ..serializers import (SSOSerializer, TwoFactorAuthCodeSerializer,
|
||||||
|
UserProfileSerializer,
|
||||||
|
EditUserProfileSerializer, AvatarUploadForm)
|
||||||
from ..tasks import send_email_async
|
from ..tasks import send_email_async
|
||||||
|
|
||||||
|
|
||||||
|
class UserProfileAPI(APIView):
|
||||||
|
"""
|
||||||
|
判断是否登录, 若登录返回用户信息
|
||||||
|
"""
|
||||||
|
@method_decorator(ensure_csrf_cookie)
|
||||||
|
def get(self, request, **kwargs):
|
||||||
|
user = request.user
|
||||||
|
if not user.is_authenticated():
|
||||||
|
return self.success(0)
|
||||||
|
|
||||||
|
username = request.GET.get("username")
|
||||||
|
try:
|
||||||
|
if username:
|
||||||
|
user = User.objects.get(username=username, is_disabled=False)
|
||||||
|
else:
|
||||||
|
user = request.user
|
||||||
|
except User.DoesNotExist:
|
||||||
|
return self.error("User does not exist")
|
||||||
|
profile = UserProfile.objects.get(user=user)
|
||||||
|
return self.success(UserProfileSerializer(profile).data)
|
||||||
|
|
||||||
|
@validate_serializer(EditUserProfileSerializer)
|
||||||
|
@login_required
|
||||||
|
def put(self, request):
|
||||||
|
data = request.data
|
||||||
|
user_profile = request.user.userprofile
|
||||||
|
print(data)
|
||||||
|
if data.get("avatar"):
|
||||||
|
user_profile.avatar = data["avatar"]
|
||||||
|
else:
|
||||||
|
user_profile.mood = data["mood"]
|
||||||
|
user_profile.blog = data["blog"]
|
||||||
|
user_profile.school = data["school"]
|
||||||
|
user_profile.student_id = data["student_id"]
|
||||||
|
user_profile.phone_number = data["phone_number"]
|
||||||
|
user_profile.major = data["major"]
|
||||||
|
# Timezone & language 暂时不加
|
||||||
|
user_profile.save()
|
||||||
|
return self.success("Succeeded")
|
||||||
|
|
||||||
|
|
||||||
|
class AvatarUploadAPI(CSRFExemptAPIView):
|
||||||
|
request_parsers = ()
|
||||||
|
|
||||||
|
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(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(avatar.name)[-1]
|
||||||
|
with open(os.path.join(settings.IMAGE_UPLOAD_DIR, name), "wb") as img:
|
||||||
|
for chunk in avatar:
|
||||||
|
img.write(chunk)
|
||||||
|
print(os.path.join(settings.IMAGE_UPLOAD_DIR, name))
|
||||||
|
return self.success({"path": "/static/upload/" + name})
|
||||||
|
|
||||||
|
|
||||||
|
class SSOAPI(APIView):
|
||||||
|
@login_required
|
||||||
|
def get(self, request):
|
||||||
|
callback = request.GET.get("callback", None)
|
||||||
|
if not callback:
|
||||||
|
return self.error("Parameter Error")
|
||||||
|
token = rand_str()
|
||||||
|
request.user.auth_token = token
|
||||||
|
request.user.save()
|
||||||
|
return self.success({"redirect_url": callback + "?token=" + token,
|
||||||
|
"callback": callback})
|
||||||
|
|
||||||
|
@validate_serializer(SSOSerializer)
|
||||||
|
def post(self, request):
|
||||||
|
data = request.data
|
||||||
|
try:
|
||||||
|
User.objects.get(open_api_appkey=data["appkey"])
|
||||||
|
except User.DoesNotExist:
|
||||||
|
return self.error("Invalid appkey")
|
||||||
|
try:
|
||||||
|
user = User.objects.get(auth_token=data["token"])
|
||||||
|
user.auth_token = None
|
||||||
|
user.save()
|
||||||
|
return self.success({"username": user.username,
|
||||||
|
"id": user.id,
|
||||||
|
"admin_type": user.admin_type,
|
||||||
|
"avatar": user.userprofile.avatar})
|
||||||
|
except User.DoesNotExist:
|
||||||
|
return self.error("User does not exist")
|
||||||
|
|
||||||
|
|
||||||
|
class TwoFactorAuthAPI(APIView):
|
||||||
|
@login_required
|
||||||
|
def get(self, request):
|
||||||
|
"""
|
||||||
|
Get QR code
|
||||||
|
"""
|
||||||
|
user = request.user
|
||||||
|
if user.two_factor_auth:
|
||||||
|
return self.error("Already open 2FA")
|
||||||
|
token = rand_str()
|
||||||
|
user.tfa_token = token
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
config = WebsiteConfig.objects.first()
|
||||||
|
image = qrcode.make(OtpAuth(token).to_uri("totp", config.base_url, config.name))
|
||||||
|
buf = BytesIO()
|
||||||
|
image.save(buf, "gif")
|
||||||
|
|
||||||
|
return HttpResponse(buf.getvalue(), "image/gif")
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@validate_serializer(TwoFactorAuthCodeSerializer)
|
||||||
|
def post(self, request):
|
||||||
|
"""
|
||||||
|
Open 2FA
|
||||||
|
"""
|
||||||
|
code = request.data["code"]
|
||||||
|
user = request.user
|
||||||
|
if OtpAuth(user.tfa_token).valid_totp(code):
|
||||||
|
user.two_factor_auth = True
|
||||||
|
user.save()
|
||||||
|
return self.success("Succeeded")
|
||||||
|
else:
|
||||||
|
return self.error("Invalid captcha")
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@validate_serializer(TwoFactorAuthCodeSerializer)
|
||||||
|
def put(self, request):
|
||||||
|
code = request.data["code"]
|
||||||
|
user = request.user
|
||||||
|
if OtpAuth(user.tfa_token).valid_totp(code):
|
||||||
|
user.two_factor_auth = False
|
||||||
|
user.save()
|
||||||
|
else:
|
||||||
|
return self.error("Invalid captcha")
|
||||||
|
|
||||||
|
|
||||||
class UserLoginAPI(APIView):
|
class UserLoginAPI(APIView):
|
||||||
@validate_serializer(UserLoginSerializer)
|
@validate_serializer(UserLoginSerializer)
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
@ -89,22 +238,15 @@ class UserRegisterAPI(APIView):
|
|||||||
captcha = Captcha(request)
|
captcha = Captcha(request)
|
||||||
if not captcha.validate(data["captcha"]):
|
if not captcha.validate(data["captcha"]):
|
||||||
return self.error("Invalid captcha")
|
return self.error("Invalid captcha")
|
||||||
try:
|
if User.objects.filter(username=data["username"]).exists():
|
||||||
User.objects.get(username=data["username"])
|
|
||||||
return self.error("Username already exists")
|
return self.error("Username already exists")
|
||||||
except User.DoesNotExist:
|
if User.objects.filter(email=data["email"]).exists():
|
||||||
pass
|
|
||||||
try:
|
|
||||||
User.objects.get(email=data["email"])
|
|
||||||
return self.error("Email already exists")
|
return self.error("Email already exists")
|
||||||
# Some old data has duplicate email
|
|
||||||
except MultipleObjectsReturned:
|
|
||||||
return self.error("Email already exists")
|
|
||||||
except User.DoesNotExist:
|
|
||||||
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()
|
||||||
UserProfile.objects.create(user=user)
|
UserProfile.objects.create(user=user, time_zone=settings.USER_DEFAULT_TZ)
|
||||||
return self.success("Succeeded")
|
return self.success("Succeeded")
|
||||||
|
|
||||||
|
|
||||||
@ -117,7 +259,7 @@ class UserChangePasswordAPI(APIView):
|
|||||||
"""
|
"""
|
||||||
data = request.data
|
data = request.data
|
||||||
captcha = Captcha(request)
|
captcha = Captcha(request)
|
||||||
if not captcha.check(data["captcha"]):
|
if not captcha.validate(data["captcha"]):
|
||||||
return self.error("Invalid captcha")
|
return self.error("Invalid captcha")
|
||||||
username = request.user.username
|
username = request.user.username
|
||||||
user = auth.authenticate(username=username, password=data["old_password"])
|
user = auth.authenticate(username=username, password=data["old_password"])
|
||||||
|
@ -1,179 +0,0 @@
|
|||||||
import os
|
|
||||||
from io import BytesIO
|
|
||||||
|
|
||||||
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, CSRFExemptAPIView
|
|
||||||
from utils.shortcuts import rand_str
|
|
||||||
|
|
||||||
from ..decorators import login_required
|
|
||||||
from ..models import User, UserProfile
|
|
||||||
from ..serializers import (SSOSerializer, TwoFactorAuthCodeSerializer,
|
|
||||||
UserProfileSerializer,
|
|
||||||
EditUserProfileSerializer, AvatarUploadForm)
|
|
||||||
|
|
||||||
|
|
||||||
class UserNameAPI(APIView):
|
|
||||||
@method_decorator(ensure_csrf_cookie)
|
|
||||||
def get(self, request):
|
|
||||||
"""
|
|
||||||
Return Username to valid login status
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
user = User.objects.get(id=request.user.id)
|
|
||||||
except User.DoesNotExist:
|
|
||||||
return self.success({
|
|
||||||
"username": "User does not exist",
|
|
||||||
"isLogin": False
|
|
||||||
})
|
|
||||||
return self.success({
|
|
||||||
"username": user.username,
|
|
||||||
"isLogin": True
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
class UserProfileAPI(APIView):
|
|
||||||
"""
|
|
||||||
判断是否登录, 若登录返回用户信息
|
|
||||||
"""
|
|
||||||
@method_decorator(ensure_csrf_cookie)
|
|
||||||
def get(self, request, **kwargs):
|
|
||||||
user = request.user
|
|
||||||
if not user.is_authenticated():
|
|
||||||
return self.success(0)
|
|
||||||
|
|
||||||
username = request.GET.get("username")
|
|
||||||
try:
|
|
||||||
if username:
|
|
||||||
user = User.objects.get(username=username, is_disabled=False)
|
|
||||||
else:
|
|
||||||
user = request.user
|
|
||||||
except User.DoesNotExist:
|
|
||||||
return self.error("User does not exist")
|
|
||||||
profile = UserProfile.objects.get(user=user)
|
|
||||||
return self.success(UserProfileSerializer(profile).data)
|
|
||||||
|
|
||||||
@validate_serializer(EditUserProfileSerializer)
|
|
||||||
@login_required
|
|
||||||
def put(self, request):
|
|
||||||
data = request.data
|
|
||||||
user_profile = request.user.userprofile
|
|
||||||
print(data)
|
|
||||||
if data.get("avatar"):
|
|
||||||
user_profile.avatar = data["avatar"]
|
|
||||||
else:
|
|
||||||
user_profile.mood = data["mood"]
|
|
||||||
user_profile.blog = data["blog"]
|
|
||||||
user_profile.school = data["school"]
|
|
||||||
user_profile.student_id = data["student_id"]
|
|
||||||
user_profile.phone_number = data["phone_number"]
|
|
||||||
user_profile.major = data["major"]
|
|
||||||
# Timezone & language 暂时不加
|
|
||||||
user_profile.save()
|
|
||||||
return self.success("Succeeded")
|
|
||||||
|
|
||||||
|
|
||||||
class AvatarUploadAPI(CSRFExemptAPIView):
|
|
||||||
request_parsers = ()
|
|
||||||
|
|
||||||
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(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(avatar.name)[-1]
|
|
||||||
with open(os.path.join(settings.IMAGE_UPLOAD_DIR, name), "wb") as img:
|
|
||||||
for chunk in avatar:
|
|
||||||
img.write(chunk)
|
|
||||||
print(os.path.join(settings.IMAGE_UPLOAD_DIR, name))
|
|
||||||
return self.success({"path": "/static/upload/" + name})
|
|
||||||
|
|
||||||
|
|
||||||
class SSOAPI(APIView):
|
|
||||||
@login_required
|
|
||||||
def get(self, request):
|
|
||||||
callback = request.GET.get("callback", None)
|
|
||||||
if not callback:
|
|
||||||
return self.error("Parameter Error")
|
|
||||||
token = rand_str()
|
|
||||||
request.user.auth_token = token
|
|
||||||
request.user.save()
|
|
||||||
return self.success({"redirect_url": callback + "?token=" + token,
|
|
||||||
"callback": callback})
|
|
||||||
|
|
||||||
@validate_serializer(SSOSerializer)
|
|
||||||
def post(self, request):
|
|
||||||
data = request.data
|
|
||||||
try:
|
|
||||||
User.objects.get(open_api_appkey=data["appkey"])
|
|
||||||
except User.DoesNotExist:
|
|
||||||
return self.error("Invalid appkey")
|
|
||||||
try:
|
|
||||||
user = User.objects.get(auth_token=data["token"])
|
|
||||||
user.auth_token = None
|
|
||||||
user.save()
|
|
||||||
return self.success({"username": user.username,
|
|
||||||
"id": user.id,
|
|
||||||
"admin_type": user.admin_type,
|
|
||||||
"avatar": user.userprofile.avatar})
|
|
||||||
except User.DoesNotExist:
|
|
||||||
return self.error("User does not exist")
|
|
||||||
|
|
||||||
|
|
||||||
class TwoFactorAuthAPI(APIView):
|
|
||||||
@login_required
|
|
||||||
def get(self, request):
|
|
||||||
"""
|
|
||||||
Get QR code
|
|
||||||
"""
|
|
||||||
user = request.user
|
|
||||||
if user.two_factor_auth:
|
|
||||||
return self.error("Already open 2FA")
|
|
||||||
token = rand_str()
|
|
||||||
user.tfa_token = token
|
|
||||||
user.save()
|
|
||||||
|
|
||||||
config = WebsiteConfig.objects.first()
|
|
||||||
image = qrcode.make(OtpAuth(token).to_uri("totp", config.base_url, config.name))
|
|
||||||
buf = BytesIO()
|
|
||||||
image.save(buf, "gif")
|
|
||||||
|
|
||||||
return HttpResponse(buf.getvalue(), "image/gif")
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@validate_serializer(TwoFactorAuthCodeSerializer)
|
|
||||||
def post(self, request):
|
|
||||||
"""
|
|
||||||
Open 2FA
|
|
||||||
"""
|
|
||||||
code = request.data["code"]
|
|
||||||
user = request.user
|
|
||||||
if OtpAuth(user.tfa_token).valid_totp(code):
|
|
||||||
user.two_factor_auth = True
|
|
||||||
user.save()
|
|
||||||
return self.success("Succeeded")
|
|
||||||
else:
|
|
||||||
return self.error("Invalid captcha")
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
@validate_serializer(TwoFactorAuthCodeSerializer)
|
|
||||||
def put(self, request):
|
|
||||||
code = request.data["code"]
|
|
||||||
user = request.user
|
|
||||||
if OtpAuth(user.tfa_token).valid_totp(code):
|
|
||||||
user.two_factor_auth = False
|
|
||||||
user.save()
|
|
||||||
else:
|
|
||||||
return self.error("Invalid captcha")
|
|
@ -10,29 +10,6 @@ DATABASES = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CACHES = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "django_redis.cache.RedisCache",
|
|
||||||
"LOCATION": "redis://127.0.0.1:6379/1",
|
|
||||||
"OPTIONS": {
|
|
||||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"JudgeQueue": {
|
|
||||||
"BACKEND": "django_redis.cache.RedisCache",
|
|
||||||
"LOCATION": "redis://127.0.0.1:6379/2",
|
|
||||||
"OPTIONS": {
|
|
||||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Throttling": {
|
|
||||||
"BACKEND": "django_redis.cache.RedisCache",
|
|
||||||
"LOCATION": "redis://127.0.0.1:6379/3",
|
|
||||||
"OPTIONS": {
|
|
||||||
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# For celery
|
# For celery
|
||||||
REDIS_QUEUE = {
|
REDIS_QUEUE = {
|
||||||
|
@ -97,6 +97,8 @@ USE_L10N = True
|
|||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
# in user's profile
|
||||||
|
USER_DEFAULT_TZ = 'Asia/Shanghai'
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/1.8/howto/static-files/
|
# https://docs.djangoproject.com/en/1.8/howto/static-files/
|
||||||
|
@ -3,7 +3,6 @@ from django.conf.urls import include, url
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r"^api/", include("account.urls.oj")),
|
url(r"^api/", include("account.urls.oj")),
|
||||||
url(r"^api/admin/", include("account.urls.admin")),
|
url(r"^api/admin/", include("account.urls.admin")),
|
||||||
url(r"^api/account/", include("account.urls.user")),
|
|
||||||
url(r"^api/admin/", include("announcement.urls.admin")),
|
url(r"^api/admin/", include("announcement.urls.admin")),
|
||||||
url(r"^api/", include("conf.urls.oj")),
|
url(r"^api/", include("conf.urls.oj")),
|
||||||
url(r"^api/admin/", include("conf.urls.admin")),
|
url(r"^api/admin/", include("conf.urls.admin")),
|
||||||
|
@ -17,30 +17,30 @@ from math import ceil
|
|||||||
from six import BytesIO
|
from six import BytesIO
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
__version__ = '0.3.3'
|
__version__ = "0.3.3"
|
||||||
current_path = os.path.normpath(os.path.dirname(__file__))
|
current_path = os.path.normpath(os.path.dirname(__file__))
|
||||||
|
|
||||||
class Captcha(object):
|
|
||||||
|
|
||||||
|
class Captcha(object):
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
""" something init
|
""" something init
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.django_request = request
|
self.django_request = request
|
||||||
self.session_key = '_django_captcha_key'
|
self.session_key = "_django_captcha_key"
|
||||||
self.words = ["hello", "word"]
|
self.words = ["hello", "word"]
|
||||||
|
|
||||||
# image size (pix)
|
# image size (pix)
|
||||||
self.img_width = 150
|
self.img_width = 150
|
||||||
self.img_height = 30
|
self.img_height = 30
|
||||||
|
|
||||||
self.type = 'number'
|
self.type = "number"
|
||||||
self.mode = 'number'
|
self.mode = "number"
|
||||||
|
|
||||||
def _get_font_size(self):
|
def _get_font_size(self):
|
||||||
s1 = int(self.img_height * 0.8)
|
s1 = int(self.img_height * 0.8)
|
||||||
s2 = int(self.img_width/len(self.code))
|
s2 = int(self.img_width / len(self.code))
|
||||||
return int(min((s1, s2)) + max((s1, s2))*0.05)
|
return int(min((s1, s2)) + max((s1, s2)) * 0.05)
|
||||||
|
|
||||||
def _get_words(self):
|
def _get_words(self):
|
||||||
""" words list
|
""" words list
|
||||||
@ -51,7 +51,6 @@ class Captcha(object):
|
|||||||
if self.words:
|
if self.words:
|
||||||
return set(self.words)
|
return set(self.words)
|
||||||
|
|
||||||
|
|
||||||
def _set_answer(self, answer):
|
def _set_answer(self, answer):
|
||||||
self.django_request.session[self.session_key] = str(answer)
|
self.django_request.session[self.session_key] = str(answer)
|
||||||
|
|
||||||
@ -86,16 +85,16 @@ class Captcha(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# font color
|
# font color
|
||||||
self.font_color = ['black', 'darkblue', 'darkred']
|
self.font_color = ["black", "darkblue", "darkred"]
|
||||||
|
|
||||||
# background color
|
# background color
|
||||||
self.background = (random.randrange(230, 255), random.randrange(230, 255), random.randrange(230, 255))
|
self.background = (random.randrange(230, 255), random.randrange(230, 255), random.randrange(230, 255))
|
||||||
|
|
||||||
# font path
|
# font path
|
||||||
self.font_path = os.path.join(current_path, 'timesbi.ttf') # or Menlo.ttc
|
self.font_path = os.path.join(current_path, "timesbi.ttf") # or Menlo.ttc
|
||||||
|
|
||||||
self.django_request.session[self.session_key] = ''
|
self.django_request.session[self.session_key] = ""
|
||||||
im = Image.new('RGB', (self.img_width, self.img_height), self.background)
|
im = Image.new("RGB", (self.img_width, self.img_height), self.background)
|
||||||
self.code = self._generate()
|
self.code = self._generate()
|
||||||
|
|
||||||
# set font size automaticly
|
# set font size automaticly
|
||||||
@ -105,20 +104,20 @@ class Captcha(object):
|
|||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
# draw noisy point/line
|
# draw noisy point/line
|
||||||
if self.mode == 'word':
|
if self.mode == "word":
|
||||||
c = int(8/len(self.code)*3) or 3
|
c = int(8 / len(self.code) * 3) or 3
|
||||||
elif self.mode == 'number':
|
elif self.mode == "number":
|
||||||
c = 4
|
c = 4
|
||||||
|
|
||||||
for i in range(random.randrange(c-2, c)):
|
for i in range(random.randrange(c - 2, c)):
|
||||||
line_color = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
|
line_color = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255))
|
||||||
xy = (random.randrange(0, int(self.img_width*0.2)), random.randrange(0, self.img_height),
|
xy = (random.randrange(0, int(self.img_width * 0.2)), random.randrange(0, self.img_height),
|
||||||
random.randrange(int(3*self.img_width/4), self.img_width), random.randrange(0, self.img_height))
|
random.randrange(int(3 * self.img_width / 4), self.img_width), random.randrange(0, self.img_height))
|
||||||
draw.line(xy, fill=line_color, width=int(self.font_size*0.1))
|
draw.line(xy, fill=line_color, width=int(self.font_size * 0.1))
|
||||||
|
|
||||||
# main part
|
# main part
|
||||||
j = int(self.font_size*0.3)
|
j = int(self.font_size * 0.3)
|
||||||
k = int(self.font_size*0.5)
|
k = int(self.font_size * 0.5)
|
||||||
x = random.randrange(j, k)
|
x = random.randrange(j, k)
|
||||||
|
|
||||||
for i in self.code:
|
for i in self.code:
|
||||||
@ -126,21 +125,21 @@ class Captcha(object):
|
|||||||
m = int(len(self.code))
|
m = int(len(self.code))
|
||||||
y = random.randrange(1, 3)
|
y = random.randrange(1, 3)
|
||||||
|
|
||||||
if i in ('+', '=', '?'):
|
if i in ("+", "=", "?"):
|
||||||
# 对计算符号等特殊字符放大处理
|
# 对计算符号等特殊字符放大处理
|
||||||
m = ceil(self.font_size*0.8)
|
m = ceil(self.font_size * 0.8)
|
||||||
else:
|
else:
|
||||||
# 字体大小变化量,字数越少,字体大小变化越多
|
# 字体大小变化量,字数越少,字体大小变化越多
|
||||||
m = random.randrange(0, int(45 / self.font_size) + int(self.font_size/5))
|
m = random.randrange(0, int(45 / self.font_size) + int(self.font_size / 5))
|
||||||
|
|
||||||
self.font = ImageFont.truetype(self.font_path.replace('\\', '/'), self.font_size + int(ceil(m)))
|
self.font = ImageFont.truetype(self.font_path.replace("\\", "/"), self.font_size + int(ceil(m)))
|
||||||
draw.text((x, y), i, font=self.font, fill=random.choice(self.font_color))
|
draw.text((x, y), i, font=self.font, fill=random.choice(self.font_color))
|
||||||
x += self.font_size*0.9
|
x += self.font_size * 0.9
|
||||||
|
|
||||||
del x
|
del x
|
||||||
del draw
|
del draw
|
||||||
with BytesIO() as buf:
|
with BytesIO() as buf:
|
||||||
im.save(buf, 'gif')
|
im.save(buf, "gif")
|
||||||
buf_str = buf.getvalue()
|
buf_str = buf.getvalue()
|
||||||
return buf_str
|
return buf_str
|
||||||
|
|
||||||
@ -152,7 +151,6 @@ class Captcha(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
code = code.strip()
|
code = code.strip()
|
||||||
_code = self.django_request.session.get(self.session_key) or ''
|
_code = self.django_request.session.get(self.session_key) or ""
|
||||||
self.django_request.session[self.session_key] = ''
|
self.django_request.session[self.session_key] = ""
|
||||||
return _code.lower() == str(code).lower()
|
return _code.lower() == str(code).lower()
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class Command(BaseCommand):
|
|||||||
"would you like to reset it's password?\n"
|
"would you like to reset it's password?\n"
|
||||||
"Input yes to confirm: "))
|
"Input yes to confirm: "))
|
||||||
if input() == "yes":
|
if input() == "yes":
|
||||||
# for dev
|
# todo remove this in product env
|
||||||
# rand_password = rand_str(length=6)
|
# rand_password = rand_str(length=6)
|
||||||
rand_password = "rootroot"
|
rand_password = "rootroot"
|
||||||
admin.save()
|
admin.save()
|
||||||
|
Loading…
Reference in New Issue
Block a user