Skip to content

Commit

Permalink
Merge pull request #840 from ita-social-projects/#822ViewUsersList
Browse files Browse the repository at this point in the history
#822 view users list
  • Loading branch information
romanmyko authored Oct 22, 2024
2 parents 7ba91a0 + 1286c25 commit 4080fd9
Show file tree
Hide file tree
Showing 5 changed files with 286 additions and 9 deletions.
3 changes: 3 additions & 0 deletions BackEnd/administration/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
class AdminUserFactory(factory.django.DjangoModelFactory):
class Meta:
model = CustomUser
django_get_or_create = ("email",)

id = factory.Sequence(lambda n: n + 1)
email = factory.Sequence(lambda n: f"test{n + 1}@test.com")
name = factory.Sequence(lambda n: f"Test person {n + 1}")
surname = factory.Sequence(lambda n: f"Test person {n + 1} surname")
password = ""

is_active = True
is_staff = True
is_superuser = False


class AdminProfileFactory(factory.django.DjangoModelFactory):
Expand Down
46 changes: 46 additions & 0 deletions BackEnd/administration/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from django_filters import filters
from django_filters.rest_framework import FilterSet


class UsersFilter(FilterSet):
"""
Filters
/?id= , /?surname=, /?email= , /?is_active= , /?is_staff=,
/?is_superuser=, /?is_deleted=True or False, /?company_name=, /?registration_date=,
Ordering sample
/?ordering=id asc or /?ordering=-id desc
"""

id = filters.CharFilter(lookup_expr="icontains")
surname = filters.CharFilter(lookup_expr="icontains")
email = filters.CharFilter(lookup_expr="icontains")
is_active = filters.CharFilter(lookup_expr="icontains")
is_staff = filters.CharFilter(lookup_expr="icontains")
is_superuser = filters.CharFilter(lookup_expr="icontains")
is_deleted = filters.BooleanFilter(method="filter_is_deleted")
company_name = filters.CharFilter(
field_name="profile__name", lookup_expr="icontains"
)
registration_date = filters.CharFilter(
field_name="profile__created_at", lookup_expr="icontains"
)

def filter_is_deleted(self, queryset, name, value):
if value:
queryset = queryset.filter(email__startswith="is_deleted_")
return queryset

ordering = filters.OrderingFilter(
fields=(
("id", "id"),
("name", "name"),
("surname", "surname"),
("email", "email"),
("is_active", "is_active"),
("is_staff", "is_staff"),
("is_superuser", "is_superuser"),
("is_deleted", "is_deleted"),
("profile__name", "company_name"),
("profile__created_at", "registration_date"),
)
)
22 changes: 22 additions & 0 deletions BackEnd/administration/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,37 @@ def create(self, validated_data):


class AdminUserListSerializer(serializers.ModelSerializer):
company_name = serializers.SerializerMethodField()
registration_date = serializers.SerializerMethodField()
status = serializers.SerializerMethodField()

class Meta:
model = CustomUser
fields = (
"id",
"email",
"name",
"surname",
"status",
"company_name",
"registration_date",
)

def get_company_name(self, obj) -> str:
return obj.profile.name if hasattr(obj, "profile") else None

def get_registration_date(self, obj) -> str:
return obj.profile.created_at if hasattr(obj, "profile") else None

def get_status(self, obj) -> dict:
data = {
"is_active": obj.is_active,
"is_staff": obj.is_staff,
"is_superuser": obj.is_superuser,
"is_deleted": obj.email.startswith("is_deleted_"),
}
return data


class AdminUserDetailSerializer(serializers.ModelSerializer):
company_name = serializers.SerializerMethodField()
Expand Down
201 changes: 194 additions & 7 deletions BackEnd/administration/tests/test_admin_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,165 @@ def test_get_user_id_not_staff(self):
self.assertEqual(status.HTTP_403_FORBIDDEN, response.status_code)


class TestAdminUsersOrderingFilterAPITests(APITestCase):
def setUp(self):
self.users = AdminUserFactory.create_batch(2)
AdminUserFactory.reset_sequence(1)
self.user = self.users[0]

def test_get_users_ordering_desc(self):
self.client.force_authenticate(self.user)
response = self.client.get(path="/api/admin/users/?ordering=-id")
data = [
{
"id": 3,
"email": "test3@test.com",
"name": "Test person 3",
"surname": "Test person 3 surname",
"status": {
"is_active": True,
"is_staff": True,
"is_superuser": False,
"is_deleted": False,
},
"company_name": None,
"registration_date": None,
},
{
"id": 2,
"email": "test2@test.com",
"name": "Test person 2",
"surname": "Test person 2 surname",
"status": {
"is_active": True,
"is_staff": True,
"is_superuser": False,
"is_deleted": False,
},
"company_name": None,
"registration_date": None,
},
]
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(data, response.json())

def test_get_users_ordering_asc(self):
self.client.force_authenticate(self.user)
response = self.client.get(path="/api/admin/users/?ordering=id")
data = [
{
"id": 2,
"email": "test2@test.com",
"name": "Test person 2",
"surname": "Test person 2 surname",
"status": {
"is_active": True,
"is_staff": True,
"is_superuser": False,
"is_deleted": False,
},
"company_name": None,
"registration_date": None,
},
{
"id": 3,
"email": "test3@test.com",
"name": "Test person 3",
"surname": "Test person 3 surname",
"status": {
"is_active": True,
"is_staff": True,
"is_superuser": False,
"is_deleted": False,
},
"company_name": None,
"registration_date": None,
},
]
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(data, response.json())

def test_get_users_filter_id_surname(self):
self.client.force_authenticate(self.user)
response = self.client.get(path="/api/admin/users/?id=5&surname=5")
data = [
{
"id": 5,
"email": "test5@test.com",
"name": "Test person 5",
"surname": "Test person 5 surname",
"status": {
"is_active": True,
"is_staff": True,
"is_superuser": False,
"is_deleted": False,
},
"company_name": None,
"registration_date": None,
},
]
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(data, response.json())


class TestAdminUsersStatusAPITests(APITestCase):
def setUp(self):
self.users = AdminUserFactory.create_batch(2)
AdminUserFactory.reset_sequence(1)
self.user = self.users[0]

def test_get_users_filter_status_active_staff(self):
self.client.force_authenticate(self.user)
response = self.client.get(
path="/api/admin/users/?is_active=True&is_staff=True"
)
data = [
{
"id": 2,
"email": "test2@test.com",
"name": "Test person 2",
"surname": "Test person 2 surname",
"status": {
"is_active": True,
"is_staff": True,
"is_superuser": False,
"is_deleted": False,
},
"company_name": None,
"registration_date": None,
},
{
"id": 3,
"email": "test3@test.com",
"name": "Test person 3",
"surname": "Test person 3 surname",
"status": {
"is_active": True,
"is_staff": True,
"is_superuser": False,
"is_deleted": False,
},
"company_name": None,
"registration_date": None,
},
]
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(data, response.json())

def test_get_users_filter_status_superuser_staff_active(self):
self.client.force_authenticate(self.user)
response = self.client.get(
path="/api/admin/users/?is_superuser=True&is_deleted=True&is_active=False"
)
data = []
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(data, response.json())


class TestAdminUsersAPITests(APITestCase):
def setUp(self):
self.user = AdminUserFactory()
AdminUserFactory.reset_sequence(1)

def test_get_users_not_authorized(self):
response = self.client.get(path="/api/admin/users/?page=1&page_size=1")
Expand All @@ -40,10 +196,40 @@ def test_get_users_authenticated(self):
response = self.client.get(path="/api/admin/users/")
data = [
{
"id": 39,
"email": "test39@test.com",
"name": "Test person 39",
"surname": "Test person 39 surname",
"id": 2,
"email": "test2@test.com",
"name": "Test person 2",
"surname": "Test person 2 surname",
"status": {
"is_active": True,
"is_staff": True,
"is_superuser": False,
"is_deleted": False,
},
"company_name": None,
"registration_date": None,
}
]
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(data, response.json())

def test_get_users_filter(self):
self.client.force_authenticate(self.user)
response = self.client.get(path="/api/admin/users/?ordering=id")
data = [
{
"id": 2,
"email": "test2@test.com",
"name": "Test person 2",
"surname": "Test person 2 surname",
"status": {
"is_active": True,
"is_staff": True,
"is_superuser": False,
"is_deleted": False,
},
"company_name": None,
"registration_date": None,
}
]
self.assertEqual(response.status_code, status.HTTP_200_OK)
Expand All @@ -52,11 +238,12 @@ def test_get_users_authenticated(self):
def test_get_user_id_authenticated(self):
self.client.force_authenticate(self.user)
response = self.client.get(path=f"/api/admin/users/{self.user.id}/")
AdminUserFactory.reset_sequence(1)

data = {
"name": "Test person 37",
"surname": "Test person 37 surname",
"email": "test37@test.com",
"name": f"Test person {self.user.id}",
"surname": f"Test person {self.user.id} surname",
"email": f"test{self.user.id}@test.com",
"is_active": True,
"is_staff": True,
"is_superuser": False,
Expand Down
23 changes: 21 additions & 2 deletions BackEnd/administration/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,35 @@
from profiles.models import Profile
from .permissions import IsStaffUser, IsStaffUserOrReadOnly, IsSuperUser

from django_filters.rest_framework import DjangoFilterBackend
from .filters import UsersFilter


class UsersListView(ListAPIView):
"""
List of users.
View to list users with optional filtering and ordering.
### Query Parameters:
- **id** / **surname** / **email** / **is_active** / **is_staff** / **is_superuser** / **is_deleted**
- **company_name** / **registration_date**
### Ordering:
- Use the `ordering` parameter to sort the results.
- Example: `/users/?ordering=id` (ascending by ID) or `/users/?ordering=-id` (descending by ID).
### Filters:
- Filters are applied using `DjangoFilterBackend`. All the above query parameters are supported for filtering.
**Without is_deleted**
"""

permission_classes = [IsStaffUser]
pagination_class = ListPagination
serializer_class = AdminUserListSerializer
queryset = CustomUser.objects.all().order_by("id")
filter_backends = [DjangoFilterBackend]
filterset_class = UsersFilter

def get_queryset(self):
return CustomUser.objects.select_related("profile")


class UserDetailView(RetrieveUpdateDestroyAPIView):
Expand Down

0 comments on commit 4080fd9

Please sign in to comment.