Fakultas Ilmu Komputer UI

Commit 01ac021e authored by Kefas Satrio Bangkit Solidedantyo's avatar Kefas Satrio Bangkit Solidedantyo
Browse files

Merge branch 'user-roles' into 'staging'

User roles

See merge request !41
parents 6bf91940 2dbb635b
Pipeline #72464 passed with stages
in 9 minutes and 14 seconds
from django.contrib.auth.base_user import BaseUserManager from django.contrib.auth.base_user import BaseUserManager
from django.contrib.auth.models import Group
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
...@@ -17,6 +18,8 @@ class CustomUserManager(BaseUserManager): ...@@ -17,6 +18,8 @@ class CustomUserManager(BaseUserManager):
user = self.model(email=email, **extra_fields) user = self.model(email=email, **extra_fields)
user.set_password(password) user.set_password(password)
user.save() user.save()
client_role, _created = Group.objects.get_or_create(name='client')
user.groups.add(client_role)
return user return user
def create_superuser(self, email, password, **extra_fields): def create_superuser(self, email, password, **extra_fields):
......
...@@ -26,4 +26,4 @@ class CustomUser(AbstractBaseUser, PermissionsMixin): ...@@ -26,4 +26,4 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
objects = CustomUserManager() objects = CustomUserManager()
def __str__(self): def __str__(self):
return self.email return str(self.email)
from rest_framework import serializers from rest_framework import serializers, exceptions
from dj_rest_auth.serializers import LoginSerializer
from .models import CustomUser from .models import CustomUser
class CustomUserDetailsSerializer(serializers.ModelSerializer): class CustomUserDetailsSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
result = super().to_representation(instance)
if instance.groups.exists():
result['role'] = instance.groups.first().name
return result
class Meta: class Meta:
model = CustomUser model = CustomUser
fields = ('id', 'name', 'email',) fields = ('id', 'name', 'email',)
read_only_fields = ('id', 'email',) read_only_fields = ('id', 'email',)
class CustomLoginSerializer(LoginSerializer):
def validate_auth_user_status(self, user):
request = self.context.get('request')
if not request.data.get('role'):
msg = 'Role is missing from the payload.'
raise exceptions.ValidationError(msg)
if not user.groups.filter(name=request.data.get('role')).exists():
msg = 'Invalid role for the user.'
raise exceptions.ValidationError(msg)
def create(self, validated_data):
pass
def update(self, instance, validated_data):
pass
...@@ -6,6 +6,7 @@ from django.test import TestCase ...@@ -6,6 +6,7 @@ from django.test import TestCase
from django.http import JsonResponse from django.http import JsonResponse
from dietela_quiz.models import DietProfile from dietela_quiz.models import DietProfile
from .models import CustomUser from .models import CustomUser
from .serializers import CustomLoginSerializer
from .google_utils import validate_google_token from .google_utils import validate_google_token
class UserModelTests(APITestCase): class UserModelTests(APITestCase):
...@@ -60,6 +61,10 @@ class UserModelTests(APITestCase): ...@@ -60,6 +61,10 @@ class UserModelTests(APITestCase):
cls.custom_user_2 = CustomUser.objects.create_user(name='tes', email='email2@gmail.com', password='abc') cls.custom_user_2 = CustomUser.objects.create_user(name='tes', email='email2@gmail.com', password='abc')
cls.inactive_user = CustomUser.objects.create_user(name='inactive', email='inactive@gmail.com', password='abc')
cls.inactive_user.is_active = False
cls.inactive_user.save()
cls.num_of_diet_profile = DietProfile.objects.count() cls.num_of_diet_profile = DietProfile.objects.count()
cls.num_of_custom_user = CustomUser.objects.count() cls.num_of_custom_user = CustomUser.objects.count()
...@@ -68,6 +73,7 @@ class UserModelTests(APITestCase): ...@@ -68,6 +73,7 @@ class UserModelTests(APITestCase):
password='tes', diet_profile=self.diet_profile_1,) password='tes', diet_profile=self.diet_profile_1,)
self.assertEqual(str(user), 'email2@email.com') self.assertEqual(str(user), 'email2@email.com')
self.assertEqual(user.email, 'email2@email.com') self.assertEqual(user.email, 'email2@email.com')
self.assertTrue(user.groups.filter(name='client').exists())
self.assertTrue(user.is_active) self.assertTrue(user.is_active)
self.assertFalse(user.is_staff) self.assertFalse(user.is_staff)
self.assertFalse(user.is_superuser) self.assertFalse(user.is_superuser)
...@@ -188,14 +194,16 @@ class UserModelTests(APITestCase): ...@@ -188,14 +194,16 @@ class UserModelTests(APITestCase):
data = { data = {
'email': 'email@email.com', 'email': 'email@email.com',
'password': 'abc', 'password': 'abc',
'role': 'client',
} }
response = self.client.post('/auth/login/', data, format='json') response = self.client.post('/auth/user-login/', data, format='json')
json_response = json.loads(response.content) json_response = json.loads(response.content)
self.assertIn('access_token', json_response) self.assertIn('access_token', json_response)
self.assertIn('refresh_token', json_response) self.assertIn('refresh_token', json_response)
self.assertIn('user', json_response) self.assertIn('user', json_response)
self.assertTrue('id' in json_response.get('user')) self.assertIn('id', json_response.get('user'))
self.assertIn('role', json_response.get('user'))
self.assertEquals(json_response.get('user').get('name'), 'tes') self.assertEquals(json_response.get('user').get('name'), 'tes')
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
...@@ -203,18 +211,30 @@ class UserModelTests(APITestCase): ...@@ -203,18 +211,30 @@ class UserModelTests(APITestCase):
data = { data = {
'email': 'email123123123@email.com', 'email': 'email123123123@email.com',
'password': 'abc', 'password': 'abc',
'role': 'client'
} }
response = self.client.post('/auth/login/', data, format='json') response = self.client.post('/auth/user-login/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_post_login_user_failed_because_invalid_role(self):
data = {
'email': 'email@email.com',
'password': 'abc',
'role': 'artist'
}
response = self.client.post('/auth/user-login/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_post_login_user_failed_because_invalid_email_format(self): def test_post_login_user_failed_because_invalid_email_format(self):
data = { data = {
'email': 'email123123123@email', 'email': 'email123123123@email',
'password': 'abc', 'password': 'abc',
'role': 'client'
} }
response = self.client.post('/auth/login/', data, format='json') response = self.client.post('/auth/user-login/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
...@@ -222,11 +242,37 @@ class UserModelTests(APITestCase): ...@@ -222,11 +242,37 @@ class UserModelTests(APITestCase):
data = { data = {
'email': 'email@email.com', 'email': 'email@email.com',
'password': 'abc1234', 'password': 'abc1234',
'role': 'client'
}
response = self.client.post('/auth/user-login/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_post_login_user_failed_because_inactive_account(self):
data = {
'email': 'inactive@gmail.com',
'password': 'abc',
'role': 'client'
} }
response = self.client.post('/auth/user-login/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
response = self.client.post('/auth/login/', data, format='json') def test_post_login_user_failed_because_no_role_in_payload(self):
data = {
'email': 'email@email.com',
'password': 'abc',
}
response = self.client.post('/auth/user-login/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_create_login_serializer_to_do_nothing(self):
serializer = CustomLoginSerializer()
self.assertEqual(serializer.create({}), None)
def test_update_login_serializer_to_do_nothing(self):
serializer = CustomLoginSerializer()
self.assertEqual(serializer.update(None, {}), None)
@patch('authentication.google_utils.requests.get') @patch('authentication.google_utils.requests.get')
@patch('authentication.google_utils.json.loads') @patch('authentication.google_utils.json.loads')
class TestValidateGoogleToken(TestCase): class TestValidateGoogleToken(TestCase):
......
from rest_framework import routers from rest_framework import routers
from django.urls import path, include from django.urls import path, include
from .views import LinkUserAndDietProfileViewSet, GoogleView from .views import LinkUserAndDietProfileViewSet, GoogleView, CustomLoginView
router = routers.SimpleRouter() router = routers.SimpleRouter()
router.register('auth/link-user-and-diet-profile', LinkUserAndDietProfileViewSet, \ router.register('auth/link-user-and-diet-profile', LinkUserAndDietProfileViewSet, \
...@@ -9,6 +9,7 @@ router.register('auth/link-user-and-diet-profile', LinkUserAndDietProfileViewSet ...@@ -9,6 +9,7 @@ router.register('auth/link-user-and-diet-profile', LinkUserAndDietProfileViewSet
urlpatterns = [ urlpatterns = [
path('auth/registration/', include('dj_rest_auth.registration.urls')), path('auth/registration/', include('dj_rest_auth.registration.urls')),
path('auth/', include('dj_rest_auth.urls')), path('auth/', include('dj_rest_auth.urls')),
path('auth/user-login/', CustomLoginView.as_view(), name='custom_user_login'),
path('auth/google/', GoogleView.as_view(), name='google'), path('auth/google/', GoogleView.as_view(), name='google'),
] ]
......
...@@ -2,14 +2,18 @@ from rest_framework import viewsets, status ...@@ -2,14 +2,18 @@ from rest_framework import viewsets, status
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
from dj_rest_auth.views import LoginView
from django.contrib.auth.base_user import BaseUserManager from django.contrib.auth.base_user import BaseUserManager
from django.contrib.auth.hashers import make_password from django.contrib.auth.hashers import make_password
from dietela_quiz.models import DietProfile from dietela_quiz.models import DietProfile
from dietela_quiz.serializers import DietProfileSerializer from dietela_quiz.serializers import DietProfileSerializer
from .models import CustomUser from .models import CustomUser
from .serializers import CustomUserDetailsSerializer from .serializers import CustomUserDetailsSerializer, CustomLoginSerializer
from .google_utils import validate_google_token from .google_utils import validate_google_token
class CustomLoginView(LoginView):
serializer_class = CustomLoginSerializer
class LinkUserAndDietProfileViewSet(viewsets.ViewSet): class LinkUserAndDietProfileViewSet(viewsets.ViewSet):
......
...@@ -24,6 +24,7 @@ coverage==4.5.4 ...@@ -24,6 +24,7 @@ coverage==4.5.4
# linter # linter
pylint==2.7.2 pylint==2.7.2
pylint-django==2.4.2 pylint-django==2.4.2
astroid==2.5.1
#auth #auth
dj-rest-auth==2.1.4 dj-rest-auth==2.1.4
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment