From 2e9ddd5f8d5002f6557a112c84105faeacfc353d Mon Sep 17 00:00:00 2001 From: behruz-dev Date: Wed, 6 Aug 2025 16:00:35 +0500 Subject: [PATCH] fix --- .../management/commands/seed_permissions.py | 4 +- core/apps/accounts/serializers/role.py | 9 ++++ core/apps/accounts/serializers/user.py | 48 ++++++++++++++++- core/apps/accounts/urls.py | 21 ++++++-- core/apps/accounts/views/role.py | 14 +++++ core/apps/accounts/views/user.py | 53 +++++++++++++++++-- 6 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 core/apps/accounts/serializers/role.py create mode 100644 core/apps/accounts/views/role.py diff --git a/core/apps/accounts/management/commands/seed_permissions.py b/core/apps/accounts/management/commands/seed_permissions.py index b32ada4..4b82b80 100644 --- a/core/apps/accounts/management/commands/seed_permissions.py +++ b/core/apps/accounts/management/commands/seed_permissions.py @@ -13,7 +13,9 @@ class Command(BaseCommand): "code": "project_folder", "name": "project folder all access" }, - {'code': 'delete_user', "name": 'can delete user permissions'} + {'code': 'delete_user', "name": 'can delete user permissions'}, + {'code': 'user', 'name': 'all user access'}, + {'code': 'settings', 'name': 'all settings access'}, ] for perm in permissions: diff --git a/core/apps/accounts/serializers/role.py b/core/apps/accounts/serializers/role.py new file mode 100644 index 0000000..34d9b5a --- /dev/null +++ b/core/apps/accounts/serializers/role.py @@ -0,0 +1,9 @@ +from rest_framework import serializers + +from core.apps.accounts.models.role import Role + + +class RoleListSerializer(serializers.ModelSerializer): + class Meta: + model = Role + fields = ['id', 'name'] \ No newline at end of file diff --git a/core/apps/accounts/serializers/user.py b/core/apps/accounts/serializers/user.py index b0e3bd9..9afdc18 100644 --- a/core/apps/accounts/serializers/user.py +++ b/core/apps/accounts/serializers/user.py @@ -1,6 +1,9 @@ +from django.db import transaction + from rest_framework import serializers from core.apps.accounts.models import User +from core.apps.accounts.models.role import Role class UserProfileSerializer(serializers.ModelSerializer): @@ -26,4 +29,47 @@ class UserProfileSerializer(serializers.ModelSerializer): instance.phone_number = validated_data.get('phone_number', instance.phone_number) instance.profile_image = validated_data.get('profile_image', instance.profile_image) instance.save() - return instance \ No newline at end of file + return instance + + +class UserCreateSerializer(serializers.Serializer): + full_name = serializers.CharField() + username = serializers.CharField() + phone_number = serializers.CharField() + profile_image = serializers.ImageField() + role_id = serializers.UUIDField() + is_blocked = serializers.BooleanField() + password = serializers.CharField(write_only=True) + + def validate(self, data): + role = Role.objects.filter(id=data['role_id']).first() + if not role: + raise serializers.ValidationError("role not found") + data['role'] = role + if User.objects.filter(username=data['username']).exists(): + raise serializers.ValidationError("User with this username already exists") + return data + + def create(self, validated_data): + with transaction.atomic(): + user = User.objects.create( + username=validated_data.get('username'), + full_name=validated_data.get('full_name'), + phone_number=validated_data.get('phone_number'), + profile_image=validated_data.get('profile_image'), + role=validated_data.get('role'), + is_blocked=validated_data.get('is_blocked'), + ) + user.set_password(validated_data.get('password')) + user.save() + return user + + +class UserListSerializer(serializers.ModelSerializer): + role = serializers.CharField(source='role.name') + + class Meta: + model = User + fields = [ + 'id', 'full_name', 'profile_image', 'phone_number', 'role', 'username', 'is_blocked' + ] \ No newline at end of file diff --git a/core/apps/accounts/urls.py b/core/apps/accounts/urls.py index 3419062..d9d6a57 100644 --- a/core/apps/accounts/urls.py +++ b/core/apps/accounts/urls.py @@ -1,16 +1,29 @@ from django.urls import path, include from core.apps.accounts.views.login import LoginApiView -from core.apps.accounts.views.user import UserProfileApiView, UserProfileUpdateApiView, UserDeleteApiView +from core.apps.accounts.views import user as user_views +from core.apps.accounts.views import role as role_views urlpatterns = [ path('auth/login/', LoginApiView.as_view(), name='login'), + path('user_profile/', include( + [ + path('profile/', user_views.UserProfileApiView.as_view()), + path('profile/update/', user_views.UserProfileUpdateApiView.as_view()), + ] + )), path('user/', include( [ - path('profile/', UserProfileApiView.as_view()), - path('profile/update/', UserProfileUpdateApiView.as_view()), - path('delete//', UserDeleteApiView.as_view()), + path('/delete/', user_views.UserDeleteApiView.as_view()), + path('create/', user_views.UserCreateApiView.as_view()), + path('list/', user_views.UserListApiView.as_view()), + path('/', user_views.UserUpdateApiView.as_view()), + ] + )), + path('role/', include( + [ + path('list/', role_views.RoleListApiView.as_view()), ] )) ] \ No newline at end of file diff --git a/core/apps/accounts/views/role.py b/core/apps/accounts/views/role.py new file mode 100644 index 0000000..a47549d --- /dev/null +++ b/core/apps/accounts/views/role.py @@ -0,0 +1,14 @@ +from rest_framework import generics +from rest_framework.response import Response + +from core.apps.accounts.permissions.permissions import HasRolePermission +from core.apps.accounts.models.role import Role +from core.apps.accounts.serializers import role as serializers + + +class RoleListApiView(generics.ListAPIView): + serializer_class = serializers.RoleListSerializer + queryset = Role.objects.all() + permission_classes = [HasRolePermission] + required_permissions = ['settings', 'user'] + diff --git a/core/apps/accounts/views/user.py b/core/apps/accounts/views/user.py index f2998fc..755d498 100644 --- a/core/apps/accounts/views/user.py +++ b/core/apps/accounts/views/user.py @@ -1,12 +1,13 @@ from django.shortcuts import get_object_or_404 -from rest_framework import generics, views +from rest_framework import generics, views, parsers from rest_framework.response import Response from core.apps.accounts.models import User from core.apps.accounts.serializers import user as serializers from core.apps.accounts.permissions.permissions import HasRolePermission from core.apps.accounts.utils.permission import get_permissions_with_tabs +from core.apps.shared.paginations.custom import CustomPageNumberPagination class UserProfileApiView(generics.GenericAPIView): @@ -30,6 +31,7 @@ class UserProfileUpdateApiView(generics.GenericAPIView): queryset = User.objects.all() permission_classes = [HasRolePermission] required_permissions = [] + parser_classes = [parsers.MultiPartParser, parsers.FormParser] def patch(self, request): user = request.user @@ -42,9 +44,54 @@ class UserProfileUpdateApiView(generics.GenericAPIView): class UserDeleteApiView(views.APIView): permission_classes = [HasRolePermission] - required_permissions = ['delete_user'] + required_permissions = ['settings', 'user'] def delete(self, request, id): user = get_object_or_404(User, id=id) user.delete() - return Response(status=204) \ No newline at end of file + return Response(status=204) + + +class UserCreateApiView(generics.GenericAPIView): + serializer_class = serializers.UserCreateSerializer + queryset = User.objects.all() + permission_classes = [HasRolePermission] + required_permissions = ['settings', 'user'] + parser_classes = [parsers.MultiPartParser, parsers.FormParser] + + def post(self, request): + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response( + {"success": True, 'message': 'created'}, + status=201 + ) + return Response( + {'success': False, 'message': serializer.errors}, + status=400 + ) + + +class UserListApiView(generics.ListAPIView): + serializer_class = serializers.UserListSerializer + queryset = User.objects.select_related('role') + permission_classes = [HasRolePermission] + required_permissions = ['settings', 'user'] + pagination_class = CustomPageNumberPagination + + +class UserUpdateApiView(generics.GenericAPIView): + serializer_class = serializers.UserProfileSerializer + queryset = User.objects.all() + permission_classes = [HasRolePermission] + required_permissions = [] + parser_classes = [parsers.MultiPartParser, parsers.FormParser] + + def patch(self, request, id): + user = get_object_or_404(User, id=id) + serializer = self.serializer_class(data=request.data, instance=user, partial=True) + if serializer.is_valid(): + serializer.save() + return Response({'success': True, 'message': 'updated'}, status=200) + return Response({"success": False, "message": serializer.errors}, status=400)