diff --git a/companies/models.py b/companies/models.py index 4ad357c..15944e0 100644 --- a/companies/models.py +++ b/companies/models.py @@ -38,11 +38,13 @@ class Company(models.Model): shipping_cost = models.DecimalField('Gastos de envĂ­o', max_digits=10, decimal_places=2, null=True, blank=True) tags = TagField(force_lowercase=True,max_count=5, tree=True) sync = models.BooleanField('Sincronizar tienda', default=False, null=True, blank=True) + is_validated = models.BooleanField('Validado', default=False, null=True, blank=True) + is_active = models.BooleanField('Activado', default=False, null=True, blank=True) # Accesible on site # internal created = models.DateTimeField('date of creation', auto_now_add=True) updated = models.DateTimeField('date last update', auto_now=True) - creator = models.ForeignKey('core.CustomUser', on_delete=models.DO_NOTHING, null=True, related_name='company') + creator = models.ForeignKey('core.CustomUser', on_delete=models.DO_NOTHING, null=True, related_name='company_creator') def __str__(self): return self.company_name diff --git a/core/models.py b/core/models.py index e5f9b61..111900b 100644 --- a/core/models.py +++ b/core/models.py @@ -2,9 +2,11 @@ from django.db import models from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager from django.contrib.auth.models import PermissionsMixin +from companies.models import Company + # Create your models here. -class UserManager(BaseUserManager): +class CustomUserManager(BaseUserManager): use_in_migrations = True def _create_user(self, email, password, **extra_fields): @@ -16,7 +18,7 @@ class UserManager(BaseUserManager): email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) - user.save(using=self._db) + user.save() return user def create_user(self, email, password=None, **extra_fields): @@ -42,7 +44,7 @@ class CustomUser(AbstractBaseUser, PermissionsMixin): notify = models.BooleanField('Notificar', default=False, null=True) provider = models.CharField('Proveedor', max_length=1000, blank=True, null=True) # red social de registro email_verified = models.BooleanField('Email verificado', default=False, null=True) - company = None # models.ForeignKey(Empresa, null=True, on_delete=models.DO_NOTHING) + company = models.ForeignKey(Company, null=True, on_delete=models.DO_NOTHING, related_name='custom_user') is_active = models.BooleanField('Activo', default=True) is_staff = models.BooleanField('Empleado',default=False ) @@ -51,7 +53,7 @@ class CustomUser(AbstractBaseUser, PermissionsMixin): created = models.DateTimeField(auto_now_add=True, null=True, blank=True) last_visit = models.DateTimeField(auto_now=True) - objects = UserManager() + objects = CustomUserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] diff --git a/core/serializers.py b/core/serializers.py index 83b7f60..b1443f7 100644 --- a/core/serializers.py +++ b/core/serializers.py @@ -1,17 +1,28 @@ +from django.contrib.auth import get_user_model + from rest_framework import serializers from . import models +User = get_user_model() -class CustomUserSerializer(serializers.ModelSerializer): + +class CustomUserReadSerializer(serializers.ModelSerializer): class Meta: - model = models.CustomUser - fields = ('email', 'full_name', 'role', 'is_active') + model = User + fields = ('email', 'full_name', 'role', 'is_active',) + + +class CustomUserWriteSerializer(serializers.ModelSerializer): + + class Meta: + model = User + fields = ('email', 'full_name', 'role', 'is_active', 'password') class CreatorSerializer(serializers.ModelSerializer): class Meta: - model = models.CustomUser + model = User fields = ('email',) diff --git a/core/tests.py b/core/tests.py index 6765222..822e900 100644 --- a/core/tests.py +++ b/core/tests.py @@ -1,6 +1,8 @@ import random import string import json +import hashlib +import base64 from django.test import TestCase @@ -13,6 +15,7 @@ from . import models from . import factories # Create your tests here. + class CustomUserViewSetTest(APITestCase): """CustomUser viewset tests """ @@ -35,13 +38,11 @@ class CustomUserViewSetTest(APITestCase): # anon user def test_anon_user_can_create_inactive_instance(self): """Not logged-in user can create new instance of User but it's inactive - TODO: should create inactive user """ data = { 'email': 'test@email.com', 'full_name': 'TEST NAME', - 'password1': 'VENTILADORES1234499.89', - 'password2': 'VENTILADORES1234499.89', + 'password': 'VENTILADORES1234499.89', } # Query endpoint @@ -49,8 +50,14 @@ class CustomUserViewSetTest(APITestCase): # Assert creation is successful self.assertEqual(response.status_code, status.HTTP_201_CREATED) + # check for new user instance created + self.assertEquals(1, self.model.objects.filter(email=data['email']).count()) + # assert password has been set + new_user = self.model.objects.get(email=data['email']) + self.assertNotEqual('', new_user.password) # assert instance is inactive info = json.loads(response.content) + self.assertFalse(info['is_active']) def test_anon_user_cannot_modify_existing_instance(self): @@ -151,6 +158,25 @@ class CustomUserViewSetTest(APITestCase): # Assert access is forbidden self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + def test_user_update_password(self): + '''Test the modification of PASSWORD field value for an instance of User ''' + # modify values of alert instance + new_password = "updated_super secret password" + self.user.set_password(new_password) + self.user.save() + # get updated intance using PK + updated_user = self.model.objects.get(pk=self.user.pk) + # assert fields exist, and data matches + stored_value = updated_user.__dict__['password'] + hash_type, iteration, salt, stored_password_hash = stored_value.split('$') + new_password_hash = hashlib.pbkdf2_hmac( + hash_name='sha256', + password=new_password.encode(), + salt=salt.encode(), + iterations=int(iteration), + ) + self.assertEqual(stored_password_hash, base64.b64encode(new_password_hash).decode()) + # admin user def test_admin_user_can_create_instance(self): """Admin user can create new instance @@ -163,8 +189,7 @@ class CustomUserViewSetTest(APITestCase): data = { 'email': 'test@email.com', 'full_name': 'TEST NAME', - 'password1': 'VENTILADORES1234499.89', - 'password2': 'VENTILADORES1234499.89', + 'password': 'VENTILADORES1234499.89', } # Authenticate user diff --git a/core/views.py b/core/views.py index 3588a04..e8265e3 100644 --- a/core/views.py +++ b/core/views.py @@ -15,7 +15,32 @@ from back_latienda.permissions import CustomUserPermissions class CustomUserViewSet(viewsets.ModelViewSet): model = models.CustomUser - serializer_class = serializers.CustomUserSerializer + serializer_class = serializers.CustomUserReadSerializer + write_serializer_class =serializers.CustomUserWriteSerializer model_name = 'custom_user' queryset = models.CustomUser.objects.all() permission_classes = [CustomUserPermissions,] + + def create(self, request): + """ + Create Instance + """ + try: + serializer = self.write_serializer_class( + data=request.data, + ) + if serializer.is_valid(): + # save model instance data + password = serializer.validated_data.pop('password') + instance = self.model(**serializer.validated_data) + instance.set_password(password) + instance.save() + + return Response(self.serializer_class( + instance, many=False, context={'request': request}).data, + status=status.HTTP_201_CREATED) + else: + return Response( + serializer.errors, status=status.HTTP_406_NOT_ACCEPTABLE) + except Exception as e: + return Response(str(e), status=status.HTTP_500_INTERNAL_SERVER_ERROR)