diff --git a/apps/authorization/api/v1/api.py b/apps/authorization/api/v1/api.py index 29f05c8..8620083 100644 --- a/apps/authorization/api/v1/api.py +++ b/apps/authorization/api/v1/api.py @@ -30,6 +30,8 @@ class RoleViewSet(SoftDeleteMixin, viewsets.ModelViewSet): queryset = Role.objects.all() serializer_class = RoleSerializer + filter_backends = [filters.SearchFilter] + search_fields = ['role_name', 'type__name'] class PageViewSet(SoftDeleteMixin, viewsets.ModelViewSet): @@ -132,12 +134,13 @@ class UserRelationViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewSet, D 'user__username', 'user__mobile', 'user__phone', + 'user__first_name', + 'user__last_name', 'user__national_code', 'user__province__name', + 'user__city__name', 'user__unit_name', 'user__unit_national_id', - 'user__city__name', - 'role__name' ] def list(self, request, *args, **kwargs): @@ -148,7 +151,7 @@ class UserRelationViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewSet, D else: queryset = self.get_queryset().order_by('-create_date') - queryset = self.filter_query(queryset) # noqa + queryset = self.filter_queryset(queryset) # noqa page = self.paginate_queryset(queryset) if page is not None: diff --git a/apps/authorization/api/v1/serializers.py b/apps/authorization/api/v1/serializers.py index aff45ee..97cd1b3 100644 --- a/apps/authorization/api/v1/serializers.py +++ b/apps/authorization/api/v1/serializers.py @@ -90,6 +90,7 @@ class RoleSerializer(serializers.ModelSerializer): fields = [ 'id', 'role_name', + 'parent_role', 'description', 'type', 'permissions' # noqa diff --git a/apps/authorization/migrations/0020_role_parent_role.py b/apps/authorization/migrations/0020_role_parent_role.py new file mode 100644 index 0000000..af18207 --- /dev/null +++ b/apps/authorization/migrations/0020_role_parent_role.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0 on 2025-10-28 05:33 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authorization', '0019_page_is_active_permissions_is_active'), + ] + + operations = [ + migrations.AddField( + model_name='role', + name='parent_role', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child', to='authorization.role'), + ), + ] diff --git a/apps/authorization/models.py b/apps/authorization/models.py index bd96777..7863af8 100644 --- a/apps/authorization/models.py +++ b/apps/authorization/models.py @@ -1,4 +1,5 @@ from django.db import models + from apps.authentication import models as auth_models from apps.core.models import BaseModel @@ -52,6 +53,12 @@ class Permissions(BaseModel): class Role(BaseModel): + parent_role = models.ForeignKey( + 'self', + on_delete=models.CASCADE, + related_name='child', + null=True + ) role_name = models.CharField(max_length=50, unique=True) description = models.TextField(max_length=500) type = models.ForeignKey( diff --git a/logs/django_requests.log b/logs/django_requests.log index 944dadb..9b193e6 100644 --- a/logs/django_requests.log +++ b/logs/django_requests.log @@ -71,3 +71,210 @@ [2025-10-28 08:33:13,415] WARNING django.server | IP: - | Path: - | "DELETE /auth/api/v1/user/2/ HTTP/1.1" 403 101 [2025-10-28 08:33:17,023] WARNING django.request | IP: 127.0.0.1 | Path: /auth/api/v1/user/2/ | Forbidden: /auth/api/v1/user/2/ [2025-10-28 08:33:17,023] WARNING django.server | IP: - | Path: - | "DELETE /auth/api/v1/user/2/ HTTP/1.1" 403 101 +[2025-10-28 08:33:23,285] WARNING django.request | IP: 127.0.0.1 | Path: /auth/api/v1/user/2/ | Forbidden: /auth/api/v1/user/2/ +[2025-10-28 08:33:23,285] WARNING django.server | IP: - | Path: - | "DELETE /auth/api/v1/user/2/ HTTP/1.1" 403 101 +[2025-10-28 08:42:33,570] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py changed, reloading. +[2025-10-28 08:42:40,520] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader +[2025-10-28 08:43:09,662] ERROR django.request | IP: 127.0.0.1 | Path: /auth/api/v1/user-relations/ | Internal Server Error: /auth/api/v1/user-relations/ +Traceback (most recent call last): + File "D:\Software\env\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\views\decorators\csrf.py", line 65, in _view_wrapper + return view_func(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\viewsets.py", line 125, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\views.py", line 515, in dispatch + response = self.handle_exception(exc) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\views.py", line 472, in handle_exception + response = exception_handler(exc, context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\views.py", line 512, in dispatch + response = handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py", line 151, in list + queryset = self.filter_queryset(queryset) # noqa + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\generics.py", line 154, in filter_queryset + queryset = backend().filter_queryset(self.request, queryset, self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\filters.py", line 167, in filter_queryset + queryset = queryset.filter(reduce(operator.and_, conditions)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\query.py", line 1476, in filter + return self._filter_or_exclude(False, args, kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\query.py", line 1494, in _filter_or_exclude + clone._filter_or_exclude_inplace(negate, args, kwargs) + File "D:\Software\env\Lib\site-packages\django\db\models\query.py", line 1501, in _filter_or_exclude_inplace + self._query.add_q(Q(*args, **kwargs)) + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1600, in add_q + clause, _ = self._add_q(q_object, self.used_aliases) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1632, in _add_q + child_clause, needed_inner = self.build_filter( + ^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1459, in build_filter + return self._add_q( + ^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1632, in _add_q + child_clause, needed_inner = self.build_filter( + ^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1546, in build_filter + condition = self.build_lookup(lookups, col, value) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1363, in build_lookup + lhs = self.try_transform(lhs, name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1414, in try_transform + raise FieldError( +django.core.exceptions.FieldError: Unsupported lookup 'name' for ForeignKey or join on the field not permitted. +[2025-10-28 08:43:09,722] ERROR django.server | IP: - | Path: - | "GET /auth/api/v1/user-relations/?role=&search=%D9%85%D8%AC%D8%AA%D8%A8%DB%8C HTTP/1.1" 500 182573 +[2025-10-28 08:44:02,681] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py changed, reloading. +[2025-10-28 08:44:05,332] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader +[2025-10-28 08:44:51,002] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py changed, reloading. +[2025-10-28 08:44:52,659] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader +[2025-10-28 08:44:57,910] ERROR django.request | IP: 127.0.0.1 | Path: /auth/api/v1/user-relations/ | Internal Server Error: /auth/api/v1/user-relations/ +Traceback (most recent call last): + File "D:\Software\env\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\views\decorators\csrf.py", line 65, in _view_wrapper + return view_func(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\viewsets.py", line 125, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\views.py", line 515, in dispatch + response = self.handle_exception(exc) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\views.py", line 472, in handle_exception + response = exception_handler(exc, context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\views.py", line 512, in dispatch + response = handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py", line 153, in list + queryset = self.filter_queryset(queryset) # noqa + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\generics.py", line 154, in filter_queryset + queryset = backend().filter_queryset(self.request, queryset, self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\filters.py", line 167, in filter_queryset + queryset = queryset.filter(reduce(operator.and_, conditions)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\query.py", line 1476, in filter + return self._filter_or_exclude(False, args, kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\query.py", line 1494, in _filter_or_exclude + clone._filter_or_exclude_inplace(negate, args, kwargs) + File "D:\Software\env\Lib\site-packages\django\db\models\query.py", line 1501, in _filter_or_exclude_inplace + self._query.add_q(Q(*args, **kwargs)) + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1600, in add_q + clause, _ = self._add_q(q_object, self.used_aliases) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1632, in _add_q + child_clause, needed_inner = self.build_filter( + ^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1459, in build_filter + return self._add_q( + ^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1632, in _add_q + child_clause, needed_inner = self.build_filter( + ^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1546, in build_filter + condition = self.build_lookup(lookups, col, value) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1363, in build_lookup + lhs = self.try_transform(lhs, name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1414, in try_transform + raise FieldError( +django.core.exceptions.FieldError: Unsupported lookup 'name' for ForeignKey or join on the field not permitted. +[2025-10-28 08:44:57,972] ERROR django.server | IP: - | Path: - | "GET /auth/api/v1/user-relations/?role=&search=%D9%85%D8%AC%D8%AA%D8%A8%DB%8C HTTP/1.1" 500 183969 +[2025-10-28 08:44:59,982] ERROR django.request | IP: 127.0.0.1 | Path: /auth/api/v1/user-relations/ | Internal Server Error: /auth/api/v1/user-relations/ +Traceback (most recent call last): + File "D:\Software\env\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner + response = get_response(request) + ^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response + response = wrapped_callback(request, *callback_args, **callback_kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\views\decorators\csrf.py", line 65, in _view_wrapper + return view_func(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\viewsets.py", line 125, in view + return self.dispatch(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\views.py", line 515, in dispatch + response = self.handle_exception(exc) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\views.py", line 472, in handle_exception + response = exception_handler(exc, context) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\views.py", line 512, in dispatch + response = handler(request, *args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py", line 153, in list + queryset = self.filter_queryset(queryset) # noqa + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\generics.py", line 154, in filter_queryset + queryset = backend().filter_queryset(self.request, queryset, self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\rest_framework\filters.py", line 167, in filter_queryset + queryset = queryset.filter(reduce(operator.and_, conditions)) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\query.py", line 1476, in filter + return self._filter_or_exclude(False, args, kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\query.py", line 1494, in _filter_or_exclude + clone._filter_or_exclude_inplace(negate, args, kwargs) + File "D:\Software\env\Lib\site-packages\django\db\models\query.py", line 1501, in _filter_or_exclude_inplace + self._query.add_q(Q(*args, **kwargs)) + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1600, in add_q + clause, _ = self._add_q(q_object, self.used_aliases) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1632, in _add_q + child_clause, needed_inner = self.build_filter( + ^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1459, in build_filter + return self._add_q( + ^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1632, in _add_q + child_clause, needed_inner = self.build_filter( + ^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1546, in build_filter + condition = self.build_lookup(lookups, col, value) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1363, in build_lookup + lhs = self.try_transform(lhs, name) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\Software\env\Lib\site-packages\django\db\models\sql\query.py", line 1414, in try_transform + raise FieldError( +django.core.exceptions.FieldError: Unsupported lookup 'name' for ForeignKey or join on the field not permitted. +[2025-10-28 08:45:00,027] ERROR django.server | IP: - | Path: - | "GET /auth/api/v1/user-relations/?role=&search=%D9%85%D8%AC%D8%AA%D8%A8%DB%8C HTTP/1.1" 500 183969 +[2025-10-28 08:55:13,371] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py changed, reloading. +[2025-10-28 08:55:15,178] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader +[2025-10-28 08:55:50,337] INFO django.server | IP: - | Path: - | "GET /auth/api/v1/user-relations/?role=&search=%D9%85%D8%AC%D8%AA%D8%A8%DB%8C HTTP/1.1" 200 11920 +[2025-10-28 08:55:52,620] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py changed, reloading. +[2025-10-28 08:55:54,840] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader +[2025-10-28 08:56:04,191] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py changed, reloading. +[2025-10-28 08:56:06,459] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader +[2025-10-28 08:56:35,853] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py changed, reloading. +[2025-10-28 08:56:38,176] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader +[2025-10-28 08:57:10,038] INFO django.server | IP: - | Path: - | "GET /auth/api/v1/user-relations/?role=&search=%D9%85%D8%AC%D8%AA%D8%A8%DB%8C HTTP/1.1" 200 11920 +[2025-10-28 08:58:26,519] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\api\v1\api.py changed, reloading. +[2025-10-28 08:58:29,070] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader +[2025-10-28 09:03:32,653] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\models.py changed, reloading. +[2025-10-28 09:03:36,050] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader +[2025-10-28 09:07:59,433] INFO django.utils.autoreload | IP: - | Path: - | D:\Project\Rasaddam_Backend\apps\authorization\api\v1\serializers.py changed, reloading. +[2025-10-28 09:08:01,206] INFO django.utils.autoreload | IP: - | Path: - | Watching for file changes with StatReloader