diff --git a/httprequest_lego_provider/serializers.py b/httprequest_lego_provider/serializers.py index fab6d4f..cbe99a8 100644 --- a/httprequest_lego_provider/serializers.py +++ b/httprequest_lego_provider/serializers.py @@ -2,6 +2,9 @@ # See LICENSE file for licensing details. """Serializers.""" +# imported-auth-user has to be disabled as the import is needed for UserSerializer +# pylint:disable=imported-auth-user +from django.contrib.auth.models import User from rest_framework import serializers from .models import Domain, DomainUserPermission @@ -35,3 +38,18 @@ class Meta: model = DomainUserPermission fields = "__all__" + + +class UserSerializer(serializers.ModelSerializer): + """Serializer for the User objects.""" + + class Meta: + """Serializer configuration. + + Attributes: + model: the model to serialize. + fields: fields to serialize. + """ + + model = User + fields = "__all__" diff --git a/httprequest_lego_provider/tests/test_views.py b/httprequest_lego_provider/tests/test_views.py index 61f49f4..8dd5bb2 100644 --- a/httprequest_lego_provider/tests/test_views.py +++ b/httprequest_lego_provider/tests/test_views.py @@ -453,3 +453,60 @@ def test_post_domain_user_permission_when_logged_in_as_admin_user( assert DomainUserPermission.objects.filter(user=99, domain=domain) is not None assert response.status_code == 201 + + +@pytest.mark.django_db +def test_post_user_when_logged_in_as_non_admin_user(client: Client, user_auth_token: str): + """ + arrange: log in a non-admin user. + act: submit a POST request for the user URL. + assert: a 403 is returned and the user is not inserted in the database. + """ + response = client.post( + "/api/v1/users/", + data={"username": "non-existing-user"}, + format="json", + headers={"AUTHORIZATION": f"Basic {user_auth_token}"}, + ) + + with pytest.raises(User.DoesNotExist): + User.objects.get(name="non-existing-user") + assert response.status_code == 403 + + +@pytest.mark.django_db +def test_post_user_when_logged_in_as_admin_user(client: Client, admin_user_auth_token: str): + """ + arrange: log in an admin user. + act: submit a POST request for the user URL. + assert: a 201 is returned and the user is inserted in the database. + """ + response = client.post( + "/api/v1/users/", + data={"username": "new-user"}, + format="json", + headers={"AUTHORIZATION": f"Basic {admin_user_auth_token}"}, + ) + + assert User.objects.get(name="new-user") is not None + assert response.status_code == 201 + + +@pytest.mark.django_db +def test_post_user_when_logged_in_as_admin_user_and_user_invalid( + client: Client, admin_user_auth_token: str +): + """ + arrange: log in a admin user. + act: submit a POST request with an invalid value for the user URL. + assert: a 400 is returned. + """ + existing = User.objects.all()[0] + response = client.post( + "/api/v1/users/", + data={"username": existing.name}, + format="json", + headers={"AUTHORIZATION": f"Basic {admin_user_auth_token}"}, + ) + + assert response.status_code == 400 diff --git a/httprequest_lego_provider/urls.py b/httprequest_lego_provider/urls.py index 364ca70..5c6d4b8 100644 --- a/httprequest_lego_provider/urls.py +++ b/httprequest_lego_provider/urls.py @@ -10,6 +10,7 @@ router = DefaultRouter() router.register("domains", views.DomainViewSet) router.register("domain-user-permissions", views.DomainUserPermissionViewSet) +router.register("users", views.UserViewSet) urlpatterns = [ path("cleanup", views.handle_cleanup, name="cleanup"), diff --git a/httprequest_lego_provider/views.py b/httprequest_lego_provider/views.py index 00fc9cd..fde2506 100644 --- a/httprequest_lego_provider/views.py +++ b/httprequest_lego_provider/views.py @@ -7,6 +7,9 @@ from typing import Optional +# imported-auth-user has to be disabled as the import is needed for UserViewSet +# pylint:disable=imported-auth-user +from django.contrib.auth.models import User from django.http import HttpRequest, HttpResponse from rest_framework import viewsets from rest_framework.decorators import api_view @@ -15,7 +18,7 @@ from .dns import remove_dns_record, write_dns_record from .forms import CleanupForm, PresentForm from .models import Domain, DomainUserPermission -from .serializers import DomainSerializer, DomainUserPermissionSerializer +from .serializers import DomainSerializer, DomainUserPermissionSerializer, UserSerializer @api_view(["POST"]) @@ -101,3 +104,17 @@ class DomainUserPermissionViewSet(viewsets.ModelViewSet): queryset = DomainUserPermission.objects.all() serializer_class = DomainUserPermissionSerializer permission_classes = [IsAdminUser] + + +class UserViewSet(viewsets.ModelViewSet): + """Views for the User. + + Attributes: + queryset: query for the objects in the model. + serializer_class: class used for serialization. + permission_classes: list of classes to match permissions. + """ + + queryset = User.objects.all().order_by("-date_joined") + serializer_class = UserSerializer + permission_classes = [IsAdminUser]