Skip to content

Commit

Permalink
feat(account): remove ticket verify
Browse files Browse the repository at this point in the history
  • Loading branch information
OrenZhang committed Dec 30, 2024
1 parent ce8dc56 commit e58f449
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 24 deletions.
2 changes: 2 additions & 0 deletions apps/account/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
PHONE_VERIFY_CODE_TIMEOUT = 60 * 60 # second
PHONE_VERIFY_CODE_KEY = "phone_verify_code:{phone_number}"

LOGIN_CODE_KEY = "login_code:{code}"

WECHAT_LOGIN_STATE_KEY = "wechat_login_state:{state}"
WECHAT_USER_INFO_KEY = "wechat_user_info:{code}"

Expand Down
33 changes: 18 additions & 15 deletions apps/account/models.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import abc
import hashlib
from importlib import import_module
from typing import Union

from django.conf import settings
from django.contrib.auth import SESSION_KEY
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import AbstractUser, AnonymousUser, PermissionsMixin
from django.contrib.auth.models import UserManager as _UserManager
from django.contrib.sessions.backends.cache import SessionStore
from django.core.cache import cache
from django.db import models
from django.utils import timezone
Expand All @@ -21,9 +18,10 @@
SHORT_CHAR_LENGTH,
)
from ovinc_client.core.models import SoftDeletedManager, SoftDeletedModel
from ovinc_client.core.utils import num_code
from ovinc_client.core.utils import num_code, uniq_id

from apps.account.constants import (
LOGIN_CODE_KEY,
PHONE_VERIFY_CODE_KEY,
PHONE_VERIFY_CODE_LENGTH,
PHONE_VERIFY_CODE_TIMEOUT,
Expand Down Expand Up @@ -98,22 +96,27 @@ class Meta:
verbose_name_plural = verbose_name
ordering = ["username"]

def generate_oauth_code(self) -> str:
"""
Generate OAuth User Code
"""

code = uniq_id()
cache_key = LOGIN_CODE_KEY.format(code=code)
cache.set(cache_key, self.username, timeout=settings.OAUTH_CODE_TIMEOUT)
return code

@classmethod
def check_ticket(cls, ticket: str) -> (bool, Union[models.Model, None]):
def check_oauth_code(cls, code: str) -> (bool, Union[models.Model, None]):
"""
Check Ticket
Check OAuth User Code
"""

engine = import_module(settings.SESSION_ENGINE)
session: SessionStore = engine.SessionStore(session_key=ticket)
if not session.load():
return False, None
user_id = session.get(SESSION_KEY)
if not user_id:
return False, None
cache_key = LOGIN_CODE_KEY.format(code=code)
username = cache.get(cache_key)
cache.delete(cache_key)
try:
user = cls.objects.get(pk=user_id)
return True, user
return True, cls.objects.get(username=username)
except cls.DoesNotExist: # pylint: disable=E1101
return False, None

Expand Down
10 changes: 7 additions & 3 deletions apps/account/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SignInSerializer(Serializer):

username = serializers.CharField(label=gettext_lazy("Username"))
password = serializers.CharField(label=gettext_lazy("Password"))
is_oauth = serializers.BooleanField(label=gettext_lazy("Is OAuth"), default=False)
wechat_code = serializers.CharField(label=gettext_lazy("WeChat Code"), required=False)
tcaptcha = serializers.JSONField(label=gettext_lazy("Tencent Captcha"), required=False, default=dict)

Expand All @@ -56,6 +57,7 @@ class UserRegistrySerializer(ModelSerializer):
"""

username = serializers.RegexField(label=gettext_lazy("Username"), regex=USERNAME_REGEX)
is_oauth = serializers.BooleanField(label=gettext_lazy("Is OAuth"), default=False)
wechat_code = serializers.CharField(label=gettext_lazy("WeChat Code"), required=False)
phone_area = serializers.ChoiceField(label=gettext_lazy("Phone Area"), choices=PhoneNumberAreas.choices)
phone_number = serializers.CharField(label=gettext_lazy("Phone Number"))
Expand All @@ -72,6 +74,7 @@ class Meta:
"username",
"nick_name",
"password",
"is_oauth",
"wechat_code",
"phone_area",
"phone_number",
Expand Down Expand Up @@ -105,12 +108,12 @@ def validate_phone_number(self, phone_number: str) -> str:
return phone_number


class VerifyTicketRequestSerializer(Serializer):
class VerifyCodeRequestSerializer(Serializer):
"""
Verify Ticket
Verify Code
"""

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


class WeChatLoginReqSerializer(Serializer):
Expand All @@ -120,6 +123,7 @@ class WeChatLoginReqSerializer(Serializer):

code = serializers.CharField(label=gettext_lazy("Code"))
state = serializers.CharField(label=gettext_lazy("State"))
is_oauth = serializers.BooleanField(label=gettext_lazy("Is OAuth"), default=False)


class ResetPasswordRequestSerializer(Serializer):
Expand Down
28 changes: 22 additions & 6 deletions apps/account/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
SignInSerializer,
UserInfoSerializer,
UserRegistrySerializer,
VerifyTicketRequestSerializer,
VerifyCodeRequestSerializer,
WeChatLoginReqSerializer,
)
from core.auth import ApplicationAuthenticate
Expand Down Expand Up @@ -92,6 +92,10 @@ async def sign_in(self, request, *args, **kwargs):
# auth session
await database_sync_to_async(auth.login)(request, user)

# oauth
if request_data["is_oauth"]:
return Response({"code": user.generate_oauth_code()})

return Response()

@action(methods=["GET"], detail=False)
Expand Down Expand Up @@ -130,6 +134,10 @@ async def sign_up(self, request, *args, **kwargs):
# login session
await database_sync_to_async(auth.login)(request, user)

# oauth
if request_data["is_oauth"]:
return Response({"code": user.generate_oauth_code()})

# response
return Response()

Expand All @@ -155,19 +163,27 @@ async def phone_verify_code(self, request, *args, **kwargs):
# response
return Response()

@action(methods=["GET"], detail=False)
async 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_ticket(self, request, *args, **kwargs):
async def verify_code(self, request, *args, **kwargs):
"""
verify ticket
verify oauth code
"""

# validate request
request_serializer = VerifyTicketRequestSerializer(data=request.data)
request_serializer = VerifyCodeRequestSerializer(data=request.data)
request_serializer.is_valid(raise_exception=True)
request_data = request_serializer.validated_data

# load user
is_success, user = await database_sync_to_async(USER_MODEL.check_ticket)(request_data["ticket"])
is_success, user = await database_sync_to_async(USER_MODEL.check_oauth_code)(request_data["code"])
if is_success:
return Response(await UserInfoSerializer(instance=user).adata)
raise WrongToken()
Expand Down Expand Up @@ -262,7 +278,7 @@ async def wechat_login(self, request, *args, **kwargs):
if user:
await self.update_user_by_wechat(user, code)
await database_sync_to_async(auth.login)(request, user)
return Response()
return Response({"code": user.generate_oauth_code() if request_data["is_oauth"] else ""})

# need registry
return Response({"wechat_code": code})
Expand Down
3 changes: 3 additions & 0 deletions entry/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@
# TCI Callback
TCI_AUDIT_CALLBACK_PREFIX = os.getenv("TCI_AUDIT_CALLBACK_PREFIX", "")

# OAuth
OAUTH_CODE_TIMEOUT = int(os.getenv("OAUTH_CODE_TIMEOUT", str(60 * 5)))

# WeChat
WECHAT_APP_ID = os.getenv("WECHAT_APP_ID")
WECHAT_APP_KEY = os.getenv("WECHAT_APP_KEY")
Expand Down

0 comments on commit e58f449

Please sign in to comment.