version 0.0.5.5: added method to logout, refactored existed serializers and views a lot
This commit is contained in:
parent
cb3fbcac93
commit
687b4d3a82
|
|
@ -55,6 +55,19 @@ class User(ImageMixin, AbstractUser):
|
|||
def remove_token(self):
|
||||
Token.objects.filter(user=self).delete()
|
||||
|
||||
def remove_access_tokens(self, source):
|
||||
"""Method to remove user access tokens"""
|
||||
self.oauth2_provider_accesstoken.filter(application__source=source)\
|
||||
.delete()
|
||||
|
||||
def revoke_refresh_tokens(self, source):
|
||||
"""Method to remove user refresh tokens"""
|
||||
refresh_tokens = self.oauth2_provider_refreshtoken.filter(
|
||||
application__source=source)
|
||||
for token in refresh_tokens:
|
||||
token.revoke()
|
||||
|
||||
@property
|
||||
def get_username(self):
|
||||
"""Get user username"""
|
||||
return self.username
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ from rest_framework import serializers
|
|||
from rest_framework import validators as rest_validators
|
||||
|
||||
from account import models as account_models
|
||||
from utils import exceptions as utils_exceptions
|
||||
from authorization.models import Application
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from utils import exceptions as utils_exceptions
|
||||
|
||||
|
||||
# Mixins
|
||||
|
|
@ -85,6 +84,10 @@ class LoginSerializer(BaseAuthSerializerMixin, serializers.ModelSerializer):
|
|||
fields = ('username', 'password', 'source')
|
||||
|
||||
|
||||
class LogoutSerializer(BaseAuthSerializerMixin):
|
||||
"""Serializer for logout"""
|
||||
|
||||
|
||||
# OAuth
|
||||
class OAuth2Serialzier(BaseAuthSerializerMixin):
|
||||
"""Serializer OAuth2 authorization"""
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from django.conf import settings
|
|||
from django.conf.urls import url, include
|
||||
from django.urls import path
|
||||
from oauth2_provider.views import AuthorizationView
|
||||
from rest_framework_social_oauth2.views import invalidate_sessions
|
||||
from rest_framework_social_oauth2 import views as drf_social_oauth2_views
|
||||
from social_core.utils import setting_name
|
||||
from social_django import views as social_django_views
|
||||
|
||||
|
|
@ -30,15 +30,21 @@ urlpatterns_social_django = [
|
|||
urlpatterns_rest_framework_social_oauth2 = [
|
||||
url(r'^authorize/?$', AuthorizationView.as_view(), name="authorize"),
|
||||
url('', include('social_django.urls', namespace="social")),
|
||||
url(r'^invalidate-sessions/?$', invalidate_sessions, name="invalidate_sessions")
|
||||
url(r'^invalidate-sessions/?$', drf_social_oauth2_views.invalidate_sessions,
|
||||
name="invalidate_sessions")
|
||||
]
|
||||
|
||||
urlpatterns_api = [
|
||||
# sign up
|
||||
path('social/signup/', views.SocialSignUpView.as_view(), name='signup-social'),
|
||||
# sign in
|
||||
path('login/username/', views.LoginByUsernameView.as_view(), name='login-username'),
|
||||
path('login/email/', views.LoginByEmailView.as_view(), name='login-email'),
|
||||
path('revoke-token/', views.RevokeTokenView.as_view(), name="revoke_token"),
|
||||
path('token/', views.TokenView.as_view(), name="token"), # for admin login page
|
||||
# for admin sign in page
|
||||
path('token/', drf_social_oauth2_views .TokenView.as_view(), name="token"),
|
||||
# logout
|
||||
path('logout/', views.LogoutView.as_view(), name="logout"),
|
||||
path('revoke-token/', views.RevokeTokenView.as_view(), name="revoke-token"),
|
||||
]
|
||||
|
||||
urlpatterns = urlpatterns_api + \
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"""Common views for application Account"""
|
||||
import json
|
||||
|
||||
from rest_framework import status
|
||||
from braces.views import CsrfExemptMixin
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
|
@ -8,20 +9,20 @@ from oauth2_provider.oauth2_backends import OAuthLibCore
|
|||
from oauth2_provider.settings import oauth2_settings
|
||||
from oauth2_provider.views.mixins import OAuthLibMixin
|
||||
from rest_framework import permissions
|
||||
from rest_framework.generics import GenericAPIView, CreateAPIView
|
||||
from rest_framework.generics import GenericAPIView
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework_social_oauth2.oauth2_backends import KeepRequestCore
|
||||
from rest_framework_social_oauth2.oauth2_endpoints import SocialTokenServer
|
||||
|
||||
from account import models as account_models
|
||||
from authorization.models import Application
|
||||
from authorization.serializers import common as serializers
|
||||
from utils import exceptions as utils_exceptions
|
||||
|
||||
|
||||
# Mixins
|
||||
class OAuth2ViewMixin(GenericAPIView):
|
||||
"""Basic mixin for OAuth2 views"""
|
||||
|
||||
class BaseViewMixin(GenericAPIView):
|
||||
"""BaseMixin for classic auth views"""
|
||||
def get_client_id(self, source) -> str:
|
||||
"""Get application client id"""
|
||||
qs = Application.objects.by_source(source=source)
|
||||
|
|
@ -41,6 +42,13 @@ class OAuth2ViewMixin(GenericAPIView):
|
|||
raise utils_exceptions.SerivceError(data={
|
||||
'detail': _('Not found an application with this source')})
|
||||
|
||||
|
||||
class OAuth2ViewMixin(CsrfExemptMixin, OAuthLibMixin, BaseViewMixin):
|
||||
"""Basic mixin for OAuth2 views"""
|
||||
server_class = oauth2_settings.OAUTH2_SERVER_CLASS
|
||||
validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
|
||||
oauthlib_backend_class = OAuthLibCore
|
||||
|
||||
def prepare_request_data(self, validated_data: dict) -> dict:
|
||||
"""Preparing request data"""
|
||||
source = validated_data.get('source')
|
||||
|
|
@ -60,9 +68,8 @@ class OAuth2ViewMixin(GenericAPIView):
|
|||
raise utils_exceptions.ServiceError()
|
||||
|
||||
|
||||
# Create your views here.
|
||||
class LoginByUsernameView(CsrfExemptMixin, OAuthLibMixin,
|
||||
OAuth2ViewMixin, GenericAPIView):
|
||||
# Login
|
||||
class LoginByUsernameView(OAuth2ViewMixin, GenericAPIView):
|
||||
"""
|
||||
Implements an endpoint to provide access tokens
|
||||
|
||||
|
|
@ -72,9 +79,6 @@ class LoginByUsernameView(CsrfExemptMixin, OAuthLibMixin,
|
|||
* Password
|
||||
* Client credentials
|
||||
"""
|
||||
server_class = oauth2_settings.OAUTH2_SERVER_CLASS
|
||||
validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
|
||||
oauthlib_backend_class = OAuthLibCore
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = serializers.LoginSerializer
|
||||
|
||||
|
|
@ -114,8 +118,49 @@ class LoginByEmailView(LoginByUsernameView):
|
|||
serializer_class = serializers.LoginByEmailSerializer
|
||||
|
||||
|
||||
class SocialSignUpView(CsrfExemptMixin, OAuthLibMixin,
|
||||
OAuth2ViewMixin, GenericAPIView):
|
||||
# Logout
|
||||
class LogoutView(GenericAPIView):
|
||||
"""Logout view"""
|
||||
permission_classes = (permissions.IsAuthenticated, )
|
||||
serializer_class = serializers.LogoutSerializer
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Method to logout user by deleting access tokens by source"""
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
# Setup attributes
|
||||
source = serializer.validated_data.get('source')
|
||||
request.user.revoke_refresh_tokens(source=source)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class RevokeTokenView(OAuth2ViewMixin, GenericAPIView):
|
||||
"""
|
||||
Implements an endpoint to revoke access or refresh tokens
|
||||
"""
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = serializers.OAuth2Serialzier
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
# Use the rest framework `.data` to fake the post body of the django request.
|
||||
# Preparing request data
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
request_data = self.prepare_request_data(serializer.validated_data)
|
||||
# Use the rest framework `.data` to fake the post body of the django request.
|
||||
request._request.POST = request._request.POST.copy()
|
||||
for key, value in request_data.items():
|
||||
request._request.POST[key] = value
|
||||
|
||||
url, headers, body, status = self.create_revocation_response(request._request)
|
||||
response = Response(data=json.loads(body) if body else '', status=status if body else 204)
|
||||
|
||||
for k, v in headers.items():
|
||||
response[k] = v
|
||||
return response
|
||||
|
||||
|
||||
class SocialSignUpView(OAuth2ViewMixin, GenericAPIView):
|
||||
"""
|
||||
Implements an endpoint to convert a provider token to an access token
|
||||
|
||||
|
|
@ -125,7 +170,6 @@ class SocialSignUpView(CsrfExemptMixin, OAuthLibMixin,
|
|||
* Client credentials
|
||||
"""
|
||||
server_class = SocialTokenServer
|
||||
validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
|
||||
oauthlib_backend_class = KeepRequestCore
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = serializers.OAuth2Serialzier
|
||||
|
|
@ -153,36 +197,6 @@ class SocialSignUpView(CsrfExemptMixin, OAuthLibMixin,
|
|||
return response
|
||||
|
||||
|
||||
class RevokeTokenView(CsrfExemptMixin, OAuthLibMixin,
|
||||
OAuth2ViewMixin, GenericAPIView):
|
||||
"""
|
||||
Implements an endpoint to revoke access or refresh tokens
|
||||
"""
|
||||
server_class = oauth2_settings.OAUTH2_SERVER_CLASS
|
||||
validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
|
||||
oauthlib_backend_class = OAuthLibCore
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = serializers.OAuth2Serialzier
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
# Use the rest framework `.data` to fake the post body of the django request.
|
||||
# Preparing request data
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
request_data = self.prepare_request_data(serializer.validated_data)
|
||||
# Use the rest framework `.data` to fake the post body of the django request.
|
||||
request._request.POST = request._request.POST.copy()
|
||||
for key, value in request_data.items():
|
||||
request._request.POST[key] = value
|
||||
|
||||
url, headers, body, status = self.create_revocation_response(request._request)
|
||||
response = Response(data=json.loads(body) if body else '', status=status if body else 204)
|
||||
|
||||
for k, v in headers.items():
|
||||
response[k] = v
|
||||
return response
|
||||
|
||||
|
||||
class TokenView(CsrfExemptMixin, OAuthLibMixin, GenericAPIView):
|
||||
"""
|
||||
Implements an endpoint to provide access tokens
|
||||
|
|
@ -193,9 +207,6 @@ class TokenView(CsrfExemptMixin, OAuthLibMixin, GenericAPIView):
|
|||
* Password
|
||||
* Client credentials
|
||||
"""
|
||||
server_class = oauth2_settings.OAUTH2_SERVER_CLASS
|
||||
validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
|
||||
oauthlib_backend_class = OAuthLibCore
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user