version 0.0.5.6: added method to sign up
This commit is contained in:
parent
687b4d3a82
commit
4fbee551c3
|
|
@ -2,6 +2,7 @@ from django.contrib.auth.models import AbstractUser, UserManager as BaseUserMana
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
|
|
||||||
from utils.models import ImageMixin
|
from utils.models import ImageMixin
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,11 +15,11 @@ class UserManager(BaseUserManager):
|
||||||
password: str, newsletter: bool) -> object:
|
password: str, newsletter: bool) -> object:
|
||||||
"""Register new user"""
|
"""Register new user"""
|
||||||
obj = self.model(
|
obj = self.model(
|
||||||
email=email,
|
|
||||||
username=username,
|
username=username,
|
||||||
password=password,
|
email=email,
|
||||||
newsletter=newsletter
|
newsletter=newsletter
|
||||||
)
|
)
|
||||||
|
obj.set_password(password)
|
||||||
obj.save()
|
obj.save()
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
@ -66,8 +67,3 @@ class User(ImageMixin, AbstractUser):
|
||||||
application__source=source)
|
application__source=source)
|
||||||
for token in refresh_tokens:
|
for token in refresh_tokens:
|
||||||
token.revoke()
|
token.revoke()
|
||||||
|
|
||||||
@property
|
|
||||||
def get_username(self):
|
|
||||||
"""Get user username"""
|
|
||||||
return self.username
|
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,59 @@ class ClassicAuthSerializerMixin(BaseAuthSerializerMixin):
|
||||||
newsletter = serializers.BooleanField()
|
newsletter = serializers.BooleanField()
|
||||||
|
|
||||||
|
|
||||||
# Classic
|
# Serializers
|
||||||
|
class SignupSerializer(BaseAuthSerializerMixin, serializers.ModelSerializer):
|
||||||
|
"""Signup serializer serializer mixin"""
|
||||||
|
# REQUEST
|
||||||
|
username = serializers.CharField(
|
||||||
|
validators=(rest_validators.UniqueValidator(queryset=account_models.User.objects.all()),),
|
||||||
|
write_only=True
|
||||||
|
)
|
||||||
|
password = serializers.CharField(write_only=True)
|
||||||
|
email = serializers.EmailField(write_only=True)
|
||||||
|
newsletter = serializers.BooleanField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = account_models.User
|
||||||
|
fields = (
|
||||||
|
'username', 'first_name', 'last_name', 'password',
|
||||||
|
'newsletter', 'email', 'source'
|
||||||
|
)
|
||||||
|
|
||||||
|
def validate_password(self, data):
|
||||||
|
"""Custom password validation"""
|
||||||
|
try:
|
||||||
|
password_validators.validate_password(password=data)
|
||||||
|
except serializers.ValidationError as e:
|
||||||
|
raise serializers.ValidationError(str(e))
|
||||||
|
else:
|
||||||
|
return data
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
"""Override create method"""
|
||||||
|
obj = account_models.User.objects.make(
|
||||||
|
username=validated_data.get('username'),
|
||||||
|
password=validated_data.get('password'),
|
||||||
|
email=validated_data.get('email'),
|
||||||
|
newsletter=validated_data.get('newsletter')
|
||||||
|
)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
class LoginSerializer(BaseAuthSerializerMixin, serializers.ModelSerializer):
|
||||||
|
"""Serializer for login user"""
|
||||||
|
username = serializers.CharField(write_only=True)
|
||||||
|
password = serializers.CharField(write_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta-class"""
|
||||||
|
model = account_models.User
|
||||||
|
fields = ('username', 'password', 'source')
|
||||||
|
|
||||||
|
|
||||||
class LoginByEmailSerializer(LoginSerializerMixin, serializers.ModelSerializer):
|
class LoginByEmailSerializer(LoginSerializerMixin, serializers.ModelSerializer):
|
||||||
"""Serializer for signing up user by email"""
|
"""Serializer for signing up user by email"""
|
||||||
email = serializers.CharField(write_only=True)
|
email = serializers.EmailField(write_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta-class"""
|
"""Meta-class"""
|
||||||
|
|
@ -46,44 +95,6 @@ class LoginByEmailSerializer(LoginSerializerMixin, serializers.ModelSerializer):
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class UsernameSignUpSerializer(ClassicAuthSerializerMixin, serializers.ModelSerializer):
|
|
||||||
"""Serializer for signing up user by username"""
|
|
||||||
username = serializers.CharField(
|
|
||||||
validators=(rest_validators.UniqueValidator(queryset=account_models.User.objects.all()), ),
|
|
||||||
write_only=True
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Meta-class"""
|
|
||||||
model = account_models.User
|
|
||||||
fields = ('username', 'newsletter', 'password', 'source')
|
|
||||||
|
|
||||||
def validate_password(self, data):
|
|
||||||
"""Custom password validation"""
|
|
||||||
try:
|
|
||||||
password_validators.validate_password(password=data)
|
|
||||||
except serializers.ValidationError as e:
|
|
||||||
raise serializers.ValidationError(e)
|
|
||||||
else:
|
|
||||||
return data
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
"""Override create method"""
|
|
||||||
obj = account_models.User.objects.make(**validated_data)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
|
||||||
class LoginSerializer(BaseAuthSerializerMixin, serializers.ModelSerializer):
|
|
||||||
"""Serializer for login user"""
|
|
||||||
username = serializers.CharField(write_only=True)
|
|
||||||
password = serializers.CharField(write_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Meta-class"""
|
|
||||||
model = account_models.User
|
|
||||||
fields = ('username', 'password', 'source')
|
|
||||||
|
|
||||||
|
|
||||||
class LogoutSerializer(BaseAuthSerializerMixin):
|
class LogoutSerializer(BaseAuthSerializerMixin):
|
||||||
"""Serializer for logout"""
|
"""Serializer for logout"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ urlpatterns_rest_framework_social_oauth2 = [
|
||||||
urlpatterns_api = [
|
urlpatterns_api = [
|
||||||
# sign up
|
# sign up
|
||||||
path('social/signup/', views.SocialSignUpView.as_view(), name='signup-social'),
|
path('social/signup/', views.SocialSignUpView.as_view(), name='signup-social'),
|
||||||
|
path('signup/', views.SignUpView.as_view(), name='signup'),
|
||||||
# sign in
|
# sign in
|
||||||
path('login/username/', views.LoginByUsernameView.as_view(), name='login-username'),
|
path('login/username/', views.LoginByUsernameView.as_view(), name='login-username'),
|
||||||
path('login/email/', views.LoginByEmailView.as_view(), name='login-email'),
|
path('login/email/', views.LoginByEmailView.as_view(), name='login-email'),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
"""Common views for application Account"""
|
"""Common views for application Account"""
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from rest_framework import status
|
|
||||||
from braces.views import CsrfExemptMixin
|
from braces.views import CsrfExemptMixin
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
@ -9,12 +8,12 @@ from oauth2_provider.oauth2_backends import OAuthLibCore
|
||||||
from oauth2_provider.settings import oauth2_settings
|
from oauth2_provider.settings import oauth2_settings
|
||||||
from oauth2_provider.views.mixins import OAuthLibMixin
|
from oauth2_provider.views.mixins import OAuthLibMixin
|
||||||
from rest_framework import permissions
|
from rest_framework import permissions
|
||||||
|
from rest_framework import status
|
||||||
from rest_framework.generics import GenericAPIView
|
from rest_framework.generics import GenericAPIView
|
||||||
from rest_framework.views import APIView
|
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework_social_oauth2.oauth2_backends import KeepRequestCore
|
from rest_framework_social_oauth2.oauth2_backends import KeepRequestCore
|
||||||
from rest_framework_social_oauth2.oauth2_endpoints import SocialTokenServer
|
from rest_framework_social_oauth2.oauth2_endpoints import SocialTokenServer
|
||||||
from account import models as account_models
|
|
||||||
from authorization.models import Application
|
from authorization.models import Application
|
||||||
from authorization.serializers import common as serializers
|
from authorization.serializers import common as serializers
|
||||||
from utils import exceptions as utils_exceptions
|
from utils import exceptions as utils_exceptions
|
||||||
|
|
@ -29,7 +28,7 @@ class BaseViewMixin(GenericAPIView):
|
||||||
if qs.exists():
|
if qs.exists():
|
||||||
return qs.first().client_id
|
return qs.first().client_id
|
||||||
else:
|
else:
|
||||||
raise utils_exceptions.SerivceError(data={
|
raise utils_exceptions.ServiceError(data={
|
||||||
'detail': _('Application is not found')})
|
'detail': _('Application is not found')})
|
||||||
|
|
||||||
def get_client_secret(self, source) -> str:
|
def get_client_secret(self, source) -> str:
|
||||||
|
|
@ -39,7 +38,7 @@ class BaseViewMixin(GenericAPIView):
|
||||||
if qs.exists:
|
if qs.exists:
|
||||||
return qs.first().client_secret
|
return qs.first().client_secret
|
||||||
else:
|
else:
|
||||||
raise utils_exceptions.SerivceError(data={
|
raise utils_exceptions.ServiceError(data={
|
||||||
'detail': _('Not found an application with this source')})
|
'detail': _('Not found an application with this source')})
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -68,6 +67,73 @@ class OAuth2ViewMixin(CsrfExemptMixin, OAuthLibMixin, BaseViewMixin):
|
||||||
raise utils_exceptions.ServiceError()
|
raise utils_exceptions.ServiceError()
|
||||||
|
|
||||||
|
|
||||||
|
# Sign in
|
||||||
|
class SocialSignUpView(OAuth2ViewMixin, GenericAPIView):
|
||||||
|
"""
|
||||||
|
Implements an endpoint to convert a provider token to an access token
|
||||||
|
|
||||||
|
The endpoint is used in the following flows:
|
||||||
|
|
||||||
|
* Authorization code
|
||||||
|
* Client credentials
|
||||||
|
"""
|
||||||
|
server_class = SocialTokenServer
|
||||||
|
oauthlib_backend_class = KeepRequestCore
|
||||||
|
permission_classes = (permissions.AllowAny, )
|
||||||
|
serializer_class = serializers.OAuth2Serialzier
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
"""Override POST method"""
|
||||||
|
# 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)
|
||||||
|
request_data.update({
|
||||||
|
'grant_type': settings.OAUTH2_SOCIAL_AUTH_GRANT_TYPE,
|
||||||
|
'backend': settings.OAUTH2_SOCIAL_AUTH_BACKEND_NAME
|
||||||
|
})
|
||||||
|
# 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, oauth2_status = self.create_token_response(request._request)
|
||||||
|
response = Response(data=json.loads(body), status=oauth2_status)
|
||||||
|
|
||||||
|
for k, v in headers.items():
|
||||||
|
response[k] = v
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class SignUpView(OAuth2ViewMixin, GenericAPIView):
|
||||||
|
"""View for classic signup"""
|
||||||
|
permission_classes = (permissions.AllowAny, )
|
||||||
|
serializer_class = serializers.SignupSerializer
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
"""Post-method to sign up new user"""
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
serializer.save()
|
||||||
|
request_data = self.prepare_request_data(serializer.validated_data)
|
||||||
|
request_data.update({
|
||||||
|
'grant_type': 'password',
|
||||||
|
'username': serializer.validated_data.get('username'),
|
||||||
|
'password': serializer.validated_data.get('password'),
|
||||||
|
})
|
||||||
|
# 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, oauth2_status = self.create_token_response(request._request)
|
||||||
|
response = Response(data=json.loads(body), status=oauth2_status)
|
||||||
|
|
||||||
|
for k, v in headers.items():
|
||||||
|
response[k] = v
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
# Login
|
# Login
|
||||||
class LoginByUsernameView(OAuth2ViewMixin, GenericAPIView):
|
class LoginByUsernameView(OAuth2ViewMixin, GenericAPIView):
|
||||||
"""
|
"""
|
||||||
|
|
@ -97,8 +163,8 @@ class LoginByUsernameView(OAuth2ViewMixin, GenericAPIView):
|
||||||
for key, value in request_data.items():
|
for key, value in request_data.items():
|
||||||
request._request.POST[key] = value
|
request._request.POST[key] = value
|
||||||
|
|
||||||
url, headers, body, status = self.create_token_response(request._request)
|
url, headers, body, oauth2_status = self.create_token_response(request._request)
|
||||||
response = Response(data=json.loads(body), status=status)
|
response = Response(data=json.loads(body), status=oauth2_status)
|
||||||
|
|
||||||
for k, v in headers.items():
|
for k, v in headers.items():
|
||||||
response[k] = v
|
response[k] = v
|
||||||
|
|
@ -152,51 +218,16 @@ class RevokeTokenView(OAuth2ViewMixin, GenericAPIView):
|
||||||
for key, value in request_data.items():
|
for key, value in request_data.items():
|
||||||
request._request.POST[key] = value
|
request._request.POST[key] = value
|
||||||
|
|
||||||
url, headers, body, status = self.create_revocation_response(request._request)
|
url, headers, body, oauth2_status = self.create_revocation_response(request._request)
|
||||||
response = Response(data=json.loads(body) if body else '', status=status if body else 204)
|
response = Response(data=json.loads(body) if body else '',
|
||||||
|
status=oauth2_status if body else status.HTTP_204_NO_CONTENT)
|
||||||
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
|
|
||||||
|
|
||||||
The endpoint is used in the following flows:
|
|
||||||
|
|
||||||
* Authorization code
|
|
||||||
* Client credentials
|
|
||||||
"""
|
|
||||||
server_class = SocialTokenServer
|
|
||||||
oauthlib_backend_class = KeepRequestCore
|
|
||||||
permission_classes = (permissions.AllowAny,)
|
|
||||||
serializer_class = serializers.OAuth2Serialzier
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
"""Override POST method"""
|
|
||||||
# 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)
|
|
||||||
request_data.update({
|
|
||||||
'grant_type': settings.OAUTH2_SOCIAL_AUTH_GRANT_TYPE,
|
|
||||||
'backend': settings.OAUTH2_SOCIAL_AUTH_BACKEND_NAME
|
|
||||||
})
|
|
||||||
# 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_token_response(request._request)
|
|
||||||
response = Response(data=json.loads(body), status=status)
|
|
||||||
|
|
||||||
for k, v in headers.items():
|
for k, v in headers.items():
|
||||||
response[k] = v
|
response[k] = v
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
# Utils
|
||||||
class TokenView(CsrfExemptMixin, OAuthLibMixin, GenericAPIView):
|
class TokenView(CsrfExemptMixin, OAuthLibMixin, GenericAPIView):
|
||||||
"""
|
"""
|
||||||
Implements an endpoint to provide access tokens
|
Implements an endpoint to provide access tokens
|
||||||
|
|
@ -215,8 +246,8 @@ class TokenView(CsrfExemptMixin, OAuthLibMixin, GenericAPIView):
|
||||||
for key, value in request.data.items():
|
for key, value in request.data.items():
|
||||||
request._request.POST[key] = value
|
request._request.POST[key] = value
|
||||||
|
|
||||||
url, headers, body, status = self.create_token_response(request._request)
|
url, headers, body, oauth2_status = self.create_token_response(request._request)
|
||||||
response = Response(data=json.loads(body), status=status)
|
response = Response(data=json.loads(body), status=oauth2_status)
|
||||||
|
|
||||||
for k, v in headers.items():
|
for k, v in headers.items():
|
||||||
response[k] = v
|
response[k] = v
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ INSTALLED_APPS = CONTRIB_APPS + PROJECT_APPS + EXTERNAL_APPS
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'oauth2_provider.middleware.OAuth2TokenMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
|
@ -259,6 +260,13 @@ SMS_LOGIN = 'GM2019'
|
||||||
SMS_PASSWORD = '}#6%Qe7CYG7n'
|
SMS_PASSWORD = '}#6%Qe7CYG7n'
|
||||||
SMS_SENDER = 'GM'
|
SMS_SENDER = 'GM'
|
||||||
|
|
||||||
|
# EMAIL
|
||||||
|
EMAIL_USE_TLS = True
|
||||||
|
EMAIL_HOST = 'smtp.gmail.com'
|
||||||
|
EMAIL_HOST_USER = 'anatolyfeteleu@gmail.com'
|
||||||
|
EMAIL_HOST_PASSWORD = 'MA1gu4YNiT'
|
||||||
|
EMAIL_PORT = 587
|
||||||
|
|
||||||
# Django Rest Swagger
|
# Django Rest Swagger
|
||||||
SWAGGER_SETTINGS = {
|
SWAGGER_SETTINGS = {
|
||||||
# "DEFAULT_GENERATOR_CLASS": "rest_framework.schemas.generators.BaseSchemaGenerator",
|
# "DEFAULT_GENERATOR_CLASS": "rest_framework.schemas.generators.BaseSchemaGenerator",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user