From 099709227b55922f371bd2189fea5a973552b09a Mon Sep 17 00:00:00 2001 From: Yanic Olivier Date: Mon, 25 Jan 2021 11:08:25 -0500 Subject: [PATCH] Add private_note field to User for admins --- api_volontaria/apps/user/admin.py | 5 +- .../user/migrations/0006_add_private_note.py | 18 +++++ api_volontaria/apps/user/models.py | 6 +- api_volontaria/apps/user/serializers.py | 80 +++++++++++++++---- .../apps/user/tests/tests_view_users.py | 64 +++++++++++++-- api_volontaria/apps/user/views.py | 8 +- 6 files changed, 152 insertions(+), 29 deletions(-) create mode 100644 api_volontaria/apps/user/migrations/0006_add_private_note.py diff --git a/api_volontaria/apps/user/admin.py b/api_volontaria/apps/user/admin.py index 7026585d..31937b53 100644 --- a/api_volontaria/apps/user/admin.py +++ b/api_volontaria/apps/user/admin.py @@ -9,6 +9,7 @@ class UserAdmin(DjangoUserAdmin): fieldsets = ( (None, {'fields': ('email', 'password')}), (_('Personal info'), {'fields': ('first_name', 'last_name')}), + (_('General'), {'fields': ('private_note', )}), (_('Permissions'), { 'fields': ( 'is_active', 'is_staff', 'is_superuser', @@ -24,7 +25,9 @@ class UserAdmin(DjangoUserAdmin): }), ) - list_display = ('email', 'first_name', 'last_name', 'is_staff') + list_display = ( + 'email', 'first_name', 'last_name', 'is_staff', 'private_note' + ) search_fields = ('first_name', 'last_name', 'email') ordering = ('email',) diff --git a/api_volontaria/apps/user/migrations/0006_add_private_note.py b/api_volontaria/apps/user/migrations/0006_add_private_note.py new file mode 100644 index 00000000..4900cc62 --- /dev/null +++ b/api_volontaria/apps/user/migrations/0006_add_private_note.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2021-01-18 14:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('user', '0005_delete_temporarytoken'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='private_note', + field=models.TextField(blank=True, null=True, verbose_name='private note'), + ), + ] diff --git a/api_volontaria/apps/user/models.py b/api_volontaria/apps/user/models.py index 1d196cb8..d96bdf8d 100644 --- a/api_volontaria/apps/user/models.py +++ b/api_volontaria/apps/user/models.py @@ -10,7 +10,6 @@ from rest_framework.authtoken.models import Token from django.utils import timezone from django.conf import settings -from django.template.loader import render_to_string class User(AbstractUser): @@ -18,6 +17,8 @@ class User(AbstractUser): username = None email = models.EmailField(_('email address'), unique=True) + private_note = models.TextField(_('private note'), blank=True, null=True) + USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] @@ -34,9 +35,6 @@ def display_name(self): @staticmethod def create(email, password, validated_data): - print(email) - print(password) - print(validated_data) user, created = User.objects.get_or_create( email=email, defaults=validated_data diff --git a/api_volontaria/apps/user/serializers.py b/api_volontaria/apps/user/serializers.py index 18f390d8..14f2a34f 100644 --- a/api_volontaria/apps/user/serializers.py +++ b/api_volontaria/apps/user/serializers.py @@ -1,22 +1,11 @@ -import re - -from django.contrib.auth import get_user_model, password_validation -from django.contrib.auth.models import Permission -from django.core.exceptions import ValidationError, ObjectDoesNotExist -from django.contrib.auth import authenticate +from django.contrib.auth import get_user_model +from django.core.exceptions import ObjectDoesNotExist from django.utils.translation import ugettext_lazy as _ - -from rest_framework.settings import api_settings - from rest_framework import serializers -from rest_framework.validators import UniqueValidator -from rest_framework.authtoken.serializers import AuthTokenSerializer from dry_rest_permissions.generics import DRYGlobalPermissionsField from rest_auth.registration.serializers import RegisterSerializer from rest_auth.serializers import PasswordResetSerializer -from api_volontaria.apps.user.models import ActionToken - User = get_user_model() @@ -84,7 +73,70 @@ class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = User - fields = '__all__' + fields = ( + 'id', + 'url', + 'is_staff', + 'is_superuser', + 'is_active', + 'date_joined', + 'last_login', + 'groups', + 'user_permissions', + 'email', + 'permissions', + 'first_name', + 'last_name', + ) + extra_kwargs = { + 'password': { + 'write_only': True, + 'required': False, + 'help_text': _("A valid password."), + }, + 'first_name': { + 'allow_blank': False, + 'help_text': _("A valid first name."), + }, + 'last_name': { + 'allow_blank': False, + 'help_text': _("A valid last name."), + }, + } + read_only_fields = ( + 'id', + 'url', + 'is_staff', + 'is_superuser', + 'is_active', + 'date_joined', + 'last_login', + 'groups', + 'user_permissions', + 'email', + 'permissions' + ) + + +class AdminUserSerializer(UserSerializer): + class Meta: + model = User + fields = ( + 'id', + 'url', + 'is_staff', + 'is_superuser', + 'is_active', + 'date_joined', + 'last_login', + 'groups', + 'user_permissions', + 'email', + 'permissions', + 'private_note', + 'first_name', + 'last_name', + ) extra_kwargs = { 'password': { 'write_only': True, diff --git a/api_volontaria/apps/user/tests/tests_view_users.py b/api_volontaria/apps/user/tests/tests_view_users.py index eb2f4db8..027682d9 100644 --- a/api_volontaria/apps/user/tests/tests_view_users.py +++ b/api_volontaria/apps/user/tests/tests_view_users.py @@ -1,17 +1,11 @@ import json -from datetime import timedelta -from unittest import mock - from rest_framework import status -from rest_framework.test import APIClient, APITestCase +from rest_framework.test import APIClient -from django.urls import reverse -from django.test.utils import override_settings from django.contrib.auth import get_user_model from api_volontaria.factories import UserFactory, AdminFactory -from ..models import ActionToken from ....testClasses import CustomAPITestCase User = get_user_model() @@ -32,15 +26,21 @@ class UsersTests(CustomAPITestCase): 'is_active', 'first_name', 'permissions', - 'email' + 'email', ] + ATTRIBUTES_ADMIN = ATTRIBUTES + ['private_note', ] + def setUp(self): self.client = APIClient() self.user = UserFactory() self.user.set_password('Test123!') self.user.save() + self.admin = AdminFactory() + self.admin.set_password('Test123!') + self.admin.save() + def test_profile(self): self.client.force_authenticate(user=self.user) response = self.client.get( @@ -89,6 +89,54 @@ def test_profile(self): permissions ) + def test_get_user_as_admin(self): + self.client.force_authenticate(user=self.admin) + response = self.client.get( + 'http://api.example.org/users/' + str(self.user.id) + ) + + # HTTP code is good + self.assertEqual( + response.status_code, + status.HTTP_200_OK, + response.content + ) + + # Number of results is good + content = json.loads(response.content) + + self.check_attributes(content, self.ATTRIBUTES_ADMIN) + permissions = { + 'cell': { + 'create': True, + }, + 'event': { + 'create': True, + }, + 'participation': { + 'create': True, + 'update': True, + 'destroy': True, + }, + 'tasktype': { + 'create': True, + }, + 'application': { + 'create': True, + 'update': True, + 'destroy': True, + }, + 'position': { + 'create': True, + 'update': True, + 'destroy': True, + }, + } + self.assertEqual( + content['permissions'], + permissions + ) + def test_register(self): response = self.client.post( 'http://api.example.org/rest-auth/registration/', diff --git a/api_volontaria/apps/user/views.py b/api_volontaria/apps/user/views.py index 5631ce36..61325891 100644 --- a/api_volontaria/apps/user/views.py +++ b/api_volontaria/apps/user/views.py @@ -51,8 +51,12 @@ class UserViewSet(viewsets.ModelViewSet): filter_fields = '__all__' def get_serializer_class(self): - if (self.action == 'update') | (self.action == 'partial_update'): - return serializers.UserUpdateSerializer + # TODO Commented section, the UserUpdateSerializer does not exist ! + # if (self.action == 'update') | (self.action == 'partial_update'): + # return serializers.UserUpdateSerializer + + if self.request.user.is_staff: + return serializers.AdminUserSerializer return serializers.UserSerializer def get_queryset(self):