Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(asgi): replace async to sync #24

Merged
merged 1 commit into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cruft.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"template": "https://github.com/OVINC-CN/DevTemplateDjango.git",
"commit": "1e0028fba6cb111a2ef69038ca07ac74fc95a219",
"commit": "c57436b9cfec6091334edb5b2115ea498911d51c",
"checkout": "main",
"context": {
"cookiecutter": {
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ pre-commit:
scripts/pre-commit.sh

lint: pre-commit pylint

messages:
scripts/messages.sh
32 changes: 11 additions & 21 deletions apps/account/serializers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import re

from adrf.serializers import ModelSerializer, Serializer
from django.contrib.auth import get_user_model
from django.utils.translation import gettext, gettext_lazy
from ovinc_client.core.async_tools import SyncRunner
from ovinc_client.tcaptcha.exceptions import TCaptchaInvalid
from ovinc_client.tcaptcha.utils import TCaptchaVerify
from rest_framework import serializers
Expand All @@ -21,7 +19,7 @@
USER_MODEL: User = get_user_model()


class UserInfoSerializer(ModelSerializer):
class UserInfoSerializer(serializers.ModelSerializer):
"""
User Info
"""
Expand All @@ -31,7 +29,7 @@ class Meta:
fields = ["username", "nick_name", "last_login", "user_type"]


class SignInSerializer(Serializer):
class SignInSerializer(serializers.Serializer):
"""
Sign in
"""
Expand All @@ -44,14 +42,12 @@ class SignInSerializer(Serializer):

def validate(self, attrs: dict) -> dict:
data = super().validate(attrs)
if not SyncRunner().run(
TCaptchaVerify(user_ip=self.context.get("user_ip", ""), **data.get("tcaptcha", {})).verify()
):
if not TCaptchaVerify(user_ip=self.context.get("user_ip", ""), **data.get("tcaptcha", {})).verify():
raise TCaptchaInvalid()
return data


class UserRegistrySerializer(ModelSerializer):
class UserRegistrySerializer(serializers.ModelSerializer):
"""
User Registry
"""
Expand Down Expand Up @@ -84,9 +80,7 @@ class Meta:

def validate(self, attrs: dict) -> dict:
data = super().validate(attrs)
if not SyncRunner().run(
TCaptchaVerify(user_ip=self.context.get("user_ip", ""), **data.get("tcaptcha", {})).verify()
):
if not TCaptchaVerify(user_ip=self.context.get("user_ip", ""), **data.get("tcaptcha", {})).verify():
raise TCaptchaInvalid()
if not USER_MODEL.check_phone_verify_code(
area=data["phone_area"], phone_number=data["phone_number"], code=data["phone_verify"]
Expand All @@ -108,15 +102,15 @@ def validate_phone_number(self, phone_number: str) -> str:
return phone_number


class VerifyCodeRequestSerializer(Serializer):
class VerifyCodeRequestSerializer(serializers.Serializer):
"""
Verify Code
"""

code = serializers.CharField(label=gettext_lazy("Code"))


class WeChatLoginReqSerializer(Serializer):
class WeChatLoginReqSerializer(serializers.Serializer):
"""
WeChat Login
"""
Expand All @@ -126,7 +120,7 @@ class WeChatLoginReqSerializer(Serializer):
is_oauth = serializers.BooleanField(label=gettext_lazy("Is OAuth"), default=False)


class ResetPasswordRequestSerializer(Serializer):
class ResetPasswordRequestSerializer(serializers.Serializer):
"""
Reset Password
"""
Expand All @@ -144,9 +138,7 @@ class ResetPasswordRequestSerializer(Serializer):

def validate(self, attrs: dict) -> dict:
data = super().validate(attrs)
if not SyncRunner().run(
TCaptchaVerify(user_ip=self.context.get("user_ip", ""), **data.get("tcaptcha", {})).verify()
):
if not TCaptchaVerify(user_ip=self.context.get("user_ip", ""), **data.get("tcaptcha", {})).verify():
raise TCaptchaInvalid()
if not USER_MODEL.check_phone_verify_code(
area=data["phone_area"], phone_number=data["phone_number"], code=data["phone_verify"]
Expand All @@ -155,7 +147,7 @@ def validate(self, attrs: dict) -> dict:
return data


class SendVerifyCodeRequestSerializer(Serializer):
class SendVerifyCodeRequestSerializer(serializers.Serializer):
"""
Verify Code
"""
Expand All @@ -166,8 +158,6 @@ class SendVerifyCodeRequestSerializer(Serializer):

def validate(self, attrs: dict) -> dict:
data = super().validate(attrs)
if not SyncRunner().run(
TCaptchaVerify(user_ip=self.context.get("user_ip", ""), **data.get("tcaptcha", {})).verify()
):
if not TCaptchaVerify(user_ip=self.context.get("user_ip", ""), **data.get("tcaptcha", {})).verify():
raise TCaptchaInvalid()
return data
71 changes: 35 additions & 36 deletions apps/account/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from json import JSONDecodeError

import httpx
from channels.db import database_sync_to_async
from django.conf import settings
from django.contrib import auth
from django.contrib.auth import get_user_model
Expand Down Expand Up @@ -53,13 +52,13 @@ class UserInfoViewSet(MainViewSet):
queryset = USER_MODEL.get_queryset()
serializer_class = UserInfoSerializer

async def list(self, request, *args, **kwargs):
def list(self, request, *args, **kwargs):
"""
Get User Info
"""

serializer = self.serializer_class(instance=request.user)
return Response(await serializer.adata)
return Response(serializer.data)


class UserSignViewSet(MainViewSet):
Expand All @@ -70,7 +69,7 @@ class UserSignViewSet(MainViewSet):
queryset = USER_MODEL.get_queryset()

@action(methods=["POST"], detail=False, authentication_classes=[SessionAuthenticate])
async def sign_in(self, request, *args, **kwargs):
def sign_in(self, request, *args, **kwargs):
"""
Sign in
"""
Expand All @@ -81,16 +80,16 @@ async def sign_in(self, request, *args, **kwargs):
request_data = request_serializer.validated_data

# login
user: User = await database_sync_to_async(auth.authenticate)(request, **request_data)
user: User = auth.authenticate(request, **request_data)
if not user:
raise WrongSignInParam()

# bind wechat
if request_data.get("wechat_code"):
await self.update_user_by_wechat(user, request_data["wechat_code"])
self.update_user_by_wechat(user, request_data["wechat_code"])

# auth session
await database_sync_to_async(auth.login)(request, user)
auth.login(request, user)

# oauth
if request_data["is_oauth"]:
Expand All @@ -99,27 +98,27 @@ async def sign_in(self, request, *args, **kwargs):
return Response()

@action(methods=["GET"], detail=False)
async def sign_out(self, request, *args, **kwargs):
def sign_out(self, request, *args, **kwargs):
"""
Sign out
"""

await database_sync_to_async(auth.logout)(request)
auth.logout(request)
return Response()

@action(methods=["POST"], detail=False, authentication_classes=[SessionAuthenticate])
async def sign_up(self, request, *args, **kwargs):
def sign_up(self, request, *args, **kwargs):
"""
sign up
"""

# validate request
request_serializer = UserRegistrySerializer(data=request.data, context={"user_ip": get_ip(request)})
await database_sync_to_async(request_serializer.is_valid)(raise_exception=True)
request_serializer.is_valid(raise_exception=True)
request_data = request_serializer.validated_data

# save
user = await database_sync_to_async(USER_MODEL.objects.create_user)(
user = USER_MODEL.objects.create_user(
last_login=datetime.datetime.now(),
username=request_data["username"],
password=request_data["password"],
Expand All @@ -129,10 +128,10 @@ async def sign_up(self, request, *args, **kwargs):

# bind wechat
if request_data.get("wechat_code"):
await self.update_user_by_wechat(user, request_data["wechat_code"])
self.update_user_by_wechat(user, request_data["wechat_code"])

# login session
await database_sync_to_async(auth.login)(request, user)
auth.login(request, user)

# oauth
if request_data["is_oauth"]:
Expand All @@ -147,7 +146,7 @@ async def sign_up(self, request, *args, **kwargs):
authentication_classes=[SessionAuthenticate],
throttle_classes=[SMSRateThrottle, IPRateThrottle],
)
async def phone_verify_code(self, request, *args, **kwargs):
def phone_verify_code(self, request, *args, **kwargs):
"""
send verify code
"""
Expand All @@ -164,15 +163,15 @@ async def phone_verify_code(self, request, *args, **kwargs):
return Response()

@action(methods=["GET"], detail=False)
async def oauth_code(self, request, *args, **kwargs):
def oauth_code(self, request, *args, **kwargs):
"""
oauth code
"""

return Response({"code": request.user.generate_oauth_code()})

@action(methods=["POST"], detail=False, authentication_classes=[ApplicationAuthenticate])
async def verify_code(self, request, *args, **kwargs):
def verify_code(self, request, *args, **kwargs):
"""
verify oauth code
"""
Expand All @@ -183,13 +182,13 @@ async def verify_code(self, request, *args, **kwargs):
request_data = request_serializer.validated_data

# load user
is_success, user = await database_sync_to_async(USER_MODEL.check_oauth_code)(request_data["code"])
is_success, user = USER_MODEL.check_oauth_code(request_data["code"])
if is_success:
return Response(await UserInfoSerializer(instance=user).adata)
return Response(UserInfoSerializer(instance=user).data)
raise WrongToken()

@action(methods=["GET"], detail=False, authentication_classes=[SessionAuthenticate])
async def wechat_config(self, request, *args, **kwargs):
def wechat_config(self, request, *args, **kwargs):
"""
WeChat Config
"""
Expand All @@ -209,7 +208,7 @@ async def wechat_config(self, request, *args, **kwargs):

# pylint: disable=R0914
@action(methods=["POST"], detail=False, authentication_classes=[SessionAuthenticate])
async def wechat_login(self, request, *args, **kwargs):
def wechat_login(self, request, *args, **kwargs):
"""
WeChat Login
"""
Expand Down Expand Up @@ -241,15 +240,15 @@ async def wechat_login(self, request, *args, **kwargs):
f"&code={request_data['code']}"
f"&grant_type={WeChatAuthType.CODE}"
)
client = httpx.AsyncClient()
client = httpx.Client()
try:
resp = await client.get(url)
resp = client.get(url)
access_info = resp.json()
except Exception as err:
logger.exception("[CallWeChatAPIFailed] %s %s", url, err)
raise WeChatLoginFailed() from err
finally:
await client.aclose()
client.close()

if "openid" not in access_info:
logger.error("[WeChatLoginFailed] %s", access_info)
Expand All @@ -259,31 +258,31 @@ async def wechat_login(self, request, *args, **kwargs):
url = (
f"{settings.WECHAT_USER_INFO_API}?access_token={access_info['access_token']}&openid={access_info['openid']}"
)
client = httpx.AsyncClient()
client = httpx.Client()
try:
resp = await client.get(url)
resp = client.get(url)
user_info = resp.json()
except Exception as err:
logger.exception("[CallWeChatAPIFailed] %s", url, err)
raise WeChatLoginFailed() from err
finally:
await client.aclose()
client.close()

code = uniq_id()
cache_key = WECHAT_USER_INFO_KEY.format(code=code)
cache.set(cache_key, json.dumps(user_info, ensure_ascii=False), timeout=settings.WECHAT_SCOPE_TIMEOUT)

# load user
user: User = await database_sync_to_async(USER_MODEL.load_user_by_union_id)(union_id=user_info["unionid"])
user: User = USER_MODEL.load_user_by_union_id(union_id=user_info["unionid"])
if user:
await self.update_user_by_wechat(user, code)
await database_sync_to_async(auth.login)(request, user)
self.update_user_by_wechat(user, code)
auth.login(request, user)
return Response({"code": user.generate_oauth_code() if request_data["is_oauth"] else ""})

# need registry
return Response({"wechat_code": code})

async def update_user_by_wechat(self, user: User, wechat_code: str) -> None:
def update_user_by_wechat(self, user: User, wechat_code: str) -> None:
"""
Update User Info By WeChat
"""
Expand All @@ -299,10 +298,10 @@ async def update_user_by_wechat(self, user: User, wechat_code: str) -> None:
user.wechat_union_id = user_info["unionid"]
user.wechat_open_id = user_info["openid"]
user.avatar = user_info["headimgurl"]
await database_sync_to_async(user.save)(update_fields=["wechat_union_id", "wechat_open_id", "avatar"])
user.save(update_fields=["wechat_union_id", "wechat_open_id", "avatar"])

@action(methods=["POST"], detail=False, authentication_classes=[SessionAuthenticate])
async def reset_password(self, request, *args, **kwargs) -> Response:
def reset_password(self, request, *args, **kwargs) -> Response:
"""
Reset Password
"""
Expand All @@ -314,19 +313,19 @@ async def reset_password(self, request, *args, **kwargs) -> Response:

# load user
try:
user: User = await database_sync_to_async(USER_MODEL.objects.get)(
user: User = USER_MODEL.objects.get(
username=request_data["username"], phone_number=request_data["phone_number"]
)
except USER_MODEL.DoesNotExist as err:
raise UserNotExist() from err

# set new password
await database_sync_to_async(user.reset_password)(request_data["password"])
user.reset_password(request_data["password"])

return Response()

@action(methods=["GET"], detail=False, authentication_classes=[SessionAuthenticate])
async def phone_areas(self, request, *args, **kwargs) -> Response:
def phone_areas(self, request, *args, **kwargs) -> Response:
"""
Phone Number Areas
"""
Expand Down
2 changes: 1 addition & 1 deletion apps/application/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from adrf.serializers import ModelSerializer
from django.contrib.auth import get_user_model
from rest_framework.serializers import ModelSerializer

from apps.account.models import User
from apps.application.models import Application
Expand Down
4 changes: 2 additions & 2 deletions apps/application/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ApplicationViewSet(MainViewSet):
serializer_class = ApplicationSerializer

@action(methods=["GET"], detail=False, authentication_classes=[SessionAuthenticate])
async def all(self, request, *args, **kwargs):
def all(self, request, *args, **kwargs):
"""
list all applications
"""
Expand All @@ -33,4 +33,4 @@ async def all(self, request, *args, **kwargs):

# response
serializer = ApplicationListSerializer(queryset, many=True)
return Response(await serializer.adata)
return Response(serializer.data)
Loading
Loading