-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' into feature/persistent_shopping_cart
- Loading branch information
Showing
13 changed files
with
1,272 additions
and
646 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from django.urls import path | ||
|
||
from .api_views import RegistrationViewSet, LoginView | ||
|
||
urlpatterns = [ | ||
path('register/', RegistrationViewSet.as_view({'post': 'create'}), name='api-register'), | ||
path('login/', LoginView.as_view(), name='api-login'), | ||
] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
from django.contrib.auth import get_user_model | ||
from django.contrib.auth import login | ||
from rest_framework import viewsets, mixins, status | ||
from rest_framework.authtoken.models import Token | ||
from rest_framework.generics import GenericAPIView | ||
from rest_framework.permissions import AllowAny | ||
from rest_framework.response import Response | ||
|
||
from .models import CustomUser | ||
from .serializers import RegistrationSerializer, LoginSerializer | ||
|
||
User = get_user_model() | ||
|
||
|
||
class RegistrationViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet): | ||
queryset = User.objects.all() | ||
permission_classes = (AllowAny,) | ||
throttle_scope = 'registration' | ||
serializer_class = RegistrationSerializer | ||
|
||
def perform_create(self, serializer): | ||
user = serializer.save() | ||
custom_user = CustomUser(user=user) | ||
custom_user.save() | ||
|
||
|
||
class LoginView(GenericAPIView): | ||
permission_classes = (AllowAny,) | ||
serializer_class = LoginSerializer | ||
throttle_scope = 'login' | ||
|
||
def post(self, request): | ||
serializer = self.get_serializer(data=self.request.data) | ||
serializer.is_valid(raise_exception=True) | ||
user = serializer.validated_data.get('user') | ||
login(request, user) | ||
|
||
token, _ = Token.objects.get_or_create(user=user) | ||
if token: | ||
data = { | ||
"token": token.key, | ||
"username": user.username, | ||
"email": user.email | ||
} | ||
return Response(data, status=status.HTTP_200_OK) | ||
else: | ||
msg = {'detail': _('Unable to retrieve user auth token')} | ||
return Response(msg, status=status.HTTP_400_BAD_REQUEST) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import pytest | ||
from rest_framework.test import APIClient | ||
|
||
|
||
@pytest.fixture | ||
def api_client(): | ||
return APIClient() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
from django.contrib.auth import authenticate, get_user_model | ||
from django.utils.translation import gettext_lazy as _ | ||
from rest_framework import serializers | ||
from rest_framework.serializers import ValidationError | ||
|
||
User = get_user_model() | ||
|
||
|
||
class RegistrationSerializer(serializers.ModelSerializer): | ||
""" | ||
Serializer related to registration of a new user | ||
""" | ||
password = serializers.CharField(style={'input_type': 'password'}) | ||
password_again = serializers.CharField(style={'input_type': 'password'}) | ||
|
||
class Meta: | ||
model = User | ||
fields = ('username', 'email', 'password', 'password_again') | ||
|
||
def validate(self, attrs): | ||
if attrs['password'] and attrs['password_again']: | ||
if attrs['password'] != attrs['password_again']: | ||
raise ValidationError(_('Passwords does not match!')) | ||
return attrs | ||
|
||
def save(self, **kwargs): | ||
validated_data = self.validated_data | ||
return User.objects.create_user( | ||
username=validated_data['username'], | ||
email=validated_data['email'], | ||
password=validated_data['password'] | ||
) | ||
|
||
|
||
class LoginSerializer(serializers.Serializer): | ||
""" | ||
Login Serializer for User model | ||
""" | ||
username = serializers.CharField() | ||
password = serializers.CharField(style={'input_type': 'password'}) | ||
|
||
def validate(self, attrs): | ||
username = attrs.pop('username') | ||
password = attrs.pop('password') | ||
|
||
user = authenticate(username=username, password=password) | ||
|
||
if not user: | ||
raise ValidationError(_('Unable to log in with provided credentials')) | ||
attrs['user'] = user | ||
return attrs |
This file was deleted.
Oops, something went wrong.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import json | ||
|
||
import pytest | ||
from django.contrib.auth import get_user_model | ||
from django.urls import reverse | ||
from rest_framework import status | ||
from rest_framework.authtoken.models import Token | ||
|
||
User = get_user_model() | ||
|
||
|
||
@pytest.fixture | ||
def login_url(): | ||
return reverse('api-login') | ||
|
||
|
||
@pytest.fixture | ||
def login_data(): | ||
return { | ||
'username': 'testuser', | ||
'password': 'testpassword', | ||
} | ||
|
||
|
||
@pytest.fixture | ||
def user_instance(login_data): | ||
return User.objects.create_user(**login_data) | ||
|
||
|
||
@pytest.fixture | ||
def user_instance_token(user_instance): | ||
return Token.objects.get_or_create(user=user_instance)[0] | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_login_success(api_client, login_url, login_data, user_instance, user_instance_token): | ||
response = api_client.post(login_url, login_data, format='json') | ||
content = json.loads(response.content.decode('utf-8')) | ||
assert response.status_code == status.HTTP_200_OK | ||
assert content['username'] == user_instance.username | ||
assert content['email'] == user_instance.email | ||
assert content['token'] == user_instance_token.key | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_login_empty_data(api_client, login_url): | ||
response = api_client.post(login_url, {}, format='json') | ||
field_errors = json.loads(response.content).keys() | ||
assert response.status_code == status.HTTP_400_BAD_REQUEST | ||
assert len(field_errors) == 2 | ||
assert "username" in field_errors | ||
assert "password" in field_errors | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_login_with_only_username(api_client, login_url, user_instance): | ||
response = api_client.post(login_url, {'username': 'testuser'}, format='json') | ||
field_errors = json.loads(response.content).keys() | ||
assert response.status_code == status.HTTP_400_BAD_REQUEST | ||
assert len(field_errors) == 1 | ||
assert "password" in field_errors | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_login_with_only_password(api_client, login_url, user_instance): | ||
response = api_client.post(login_url, {'password': 'testpassword'}, format='json') | ||
field_errors = json.loads(response.content).keys() | ||
assert response.status_code == status.HTTP_400_BAD_REQUEST | ||
assert len(field_errors) == 1 | ||
assert "username" in field_errors | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_login_with_username_and_empty_password(api_client, login_url, login_data, user_instance): | ||
login_data['password'] = '' | ||
response = api_client.post(login_url, login_data, format='json') | ||
field_errors = json.loads(response.content).keys() | ||
assert response.status_code == status.HTTP_400_BAD_REQUEST | ||
assert len(field_errors) == 1 | ||
assert "password" in field_errors | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_login_wrong_password(api_client, login_url, login_data, user_instance): | ||
login_data['password'] = 'different_password' | ||
response = api_client.post(login_url, login_data, format='json') | ||
field_errors = json.loads(response.content).keys() | ||
assert response.status_code == status.HTTP_400_BAD_REQUEST | ||
assert len(field_errors) == 1 |
Oops, something went wrong.