Browse Source

perf: 修改用户确认

pull/11885/head
ibuler 1 year ago
parent
commit
452ee1224c
  1. 17
      apps/authentication/api/confirm.py
  2. 15
      apps/authentication/backends/passkey/api.py
  3. 1
      apps/authentication/confirm/relogin.py
  4. 1
      apps/authentication/const.py
  5. 2
      apps/authentication/serializers/confirm.py
  6. 2
      apps/authentication/urls/api_urls.py
  7. 3
      apps/common/exceptions.py

17
apps/authentication/api/confirm.py

@ -4,10 +4,12 @@ import time
from django.utils.translation import gettext_lazy as _
from rest_framework import status
from rest_framework.generics import RetrieveAPIView, CreateAPIView
from rest_framework.decorators import action
from rest_framework.generics import RetrieveAPIView
from rest_framework.response import Response
from authentication.permissions import UserConfirmation
from common.api import JMSGenericViewSet
from common.permissions import IsValidUser
from ..const import ConfirmType
from ..serializers import ConfirmSerializer
@ -20,10 +22,17 @@ class ConfirmBindORUNBindOAuth(RetrieveAPIView):
return Response('ok')
class ConfirmApi(RetrieveAPIView, CreateAPIView):
class UserConfirmationViewSet(JMSGenericViewSet):
permission_classes = (IsValidUser,)
serializer_class = ConfirmSerializer
@action(methods=['get'], detail=False)
def check(self, request):
confirm_type = request.query_params.get('confirm_type', 'password')
permission = UserConfirmation.require(confirm_type)()
permission.has_permission(request, self)
return Response('ok')
def get_confirm_backend(self, confirm_type):
backend_classes = ConfirmType.get_prop_backends(confirm_type)
if not backend_classes:
@ -34,12 +43,12 @@ class ConfirmApi(RetrieveAPIView, CreateAPIView):
continue
return backend
def retrieve(self, request, *args, **kwargs):
def list(self, request, *args, **kwargs):
confirm_type = request.query_params.get('confirm_type', 'password')
backend = self.get_confirm_backend(confirm_type)
if backend is None:
msg = _('This action require verify your MFA')
return Response(data={'error': msg}, status=status.HTTP_404_NOT_FOUND)
return Response(data={'error': msg}, status=status.HTTP_400_BAD_REQUEST)
data = {
'confirm_type': backend.name,

15
apps/authentication/backends/passkey/api.py

@ -4,19 +4,30 @@ from django.shortcuts import render
from django.utils.translation import gettext as _
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.viewsets import ModelViewSet
from authentication.mixins import AuthMixin
from common.api import JMSModelViewSet
from .fido import register_begin, register_complete, auth_begin, auth_complete
from .models import Passkey
from .serializer import PasskeySerializer
from ...const import ConfirmType
from ...permissions import UserConfirmation
from ...views import FlashMessageMixin
class PasskeyViewSet(AuthMixin, FlashMessageMixin, ModelViewSet):
class PasskeyViewSet(AuthMixin, FlashMessageMixin, JMSModelViewSet):
serializer_class = PasskeySerializer
permission_classes = (IsAuthenticated,)
def get_permissions(self):
if self.is_swagger_request():
return super().get_permissions()
if self.action == 'register':
self.permission_classes = [
IsAuthenticated, UserConfirmation.require(ConfirmType.PASSWORD)
]
return super().get_permissions()
def get_queryset(self):
return Passkey.objects.filter(user=self.request.user)

1
apps/authentication/confirm/relogin.py

@ -15,6 +15,7 @@ class ConfirmReLogin(BaseConfirm):
display_name = 'Re-Login'
def check(self):
return True
return not self.user.is_password_authenticate()
def authenticate(self, secret_key, mfa_type):

1
apps/authentication/const.py

@ -19,6 +19,7 @@ class ConfirmType(TextChoices):
def get_can_confirm_types(cls, confirm_type):
start = cls.values.index(confirm_type)
types = cls.values[start:]
types = [tp for tp in types if tp != 'password']
types.reverse()
return types

2
apps/authentication/serializers/confirm.py

@ -7,4 +7,4 @@ from ..const import ConfirmType, MFAType
class ConfirmSerializer(serializers.Serializer):
confirm_type = serializers.ChoiceField(required=True, allow_blank=True, choices=ConfirmType.choices)
mfa_type = serializers.ChoiceField(required=False, allow_blank=True, choices=MFAType.choices)
secret_key = EncryptedField(allow_blank=True)
secret_key = EncryptedField(allow_blank=True, required=False)

2
apps/authentication/urls/api_urls.py

@ -13,6 +13,7 @@ router.register('sso', api.SSOViewSet, 'sso')
router.register('temp-tokens', api.TempTokenViewSet, 'temp-token')
router.register('connection-token', api.ConnectionTokenViewSet, 'connection-token')
router.register('super-connection-token', api.SuperConnectionTokenViewSet, 'super-connection-token')
router.register('confirm', api.UserConfirmationViewSet, 'confirm')
urlpatterns = [
path('wecom/qr/unbind/', api.WeComQRUnBindForUserApi.as_view(), name='wecom-qr-unbind'),
@ -29,7 +30,6 @@ urlpatterns = [
name='feishu-event-subscription-callback'),
path('auth/', api.TokenCreateApi.as_view(), name='user-auth'),
path('confirm/', api.ConfirmApi.as_view(), name='user-confirm'),
path('confirm-oauth/', api.ConfirmBindORUNBindOAuth.as_view(), name='confirm-oauth'),
path('tokens/', api.TokenCreateApi.as_view(), name='auth-token'),
path('mfa/verify/', api.MFAChallengeVerifyApi.as_view(), name='mfa-verify'),

3
apps/common/exceptions.py

@ -42,8 +42,11 @@ class ReferencedByOthers(JMSException):
class UserConfirmRequired(JMSException):
status_code = status.HTTP_412_PRECONDITION_FAILED
def __init__(self, code=None):
detail = {
'type': 'user_confirm_required',
'code': code,
'detail': _('This action require confirm current user')
}

Loading…
Cancel
Save