From 79e577acd2e5ae5e33d6c23ce6afcc640bc1d364 Mon Sep 17 00:00:00 2001 From: yann Date: Fri, 6 Jun 2025 11:55:41 +0200 Subject: [PATCH] fix call to removed viewset, fix filter on comment --- README.md | 1 + softdesk/softdesk/settings.py | 4 +- softdesk/softdesk/urls.py | 4 +- softdesk/support/serializers.py | 17 --------- softdesk/support/views.py | 67 +++++++++++---------------------- 5 files changed, 26 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index e59d9ca..2dd1765 100644 --- a/README.md +++ b/README.md @@ -67,3 +67,4 @@ YaL MIT License Copyright (c) 2025 + diff --git a/softdesk/softdesk/settings.py b/softdesk/softdesk/settings.py index dcf617e..c489d48 100644 --- a/softdesk/softdesk/settings.py +++ b/softdesk/softdesk/settings.py @@ -129,7 +129,9 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' AUTH_USER_MODEL = 'authentication.User' REST_FRAMEWORK = { - 'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_simplejwt.authentication.JWTAuthentication',) + 'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_simplejwt.authentication.JWTAuthentication',), + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', + 'PAGE_SIZE': 5 } SIMPLE_JWT = { diff --git a/softdesk/softdesk/urls.py b/softdesk/softdesk/urls.py index a70983b..aa56c92 100644 --- a/softdesk/softdesk/urls.py +++ b/softdesk/softdesk/urls.py @@ -17,17 +17,15 @@ Including another URLconf from django.contrib import admin from django.urls import path, include from authentication.views import (UserView, UserCreateView, PasswordUpdateView) -from support.views import ProjectViewSet, IssueViewSet, CommentViewSet, ContributorViewSet +from support.views import ProjectViewSet, IssueViewSet, CommentViewSet from rest_framework import routers from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView router = routers.SimpleRouter() -#router.register('user', UserViewSet, basename='user') router.register('project', ProjectViewSet, basename='project') router.register('issue', IssueViewSet, basename='issue') router.register('comment', CommentViewSet, basename='comment') -router.register('contributors', ContributorViewSet) urlpatterns = [ path('admin/', admin.site.urls), diff --git a/softdesk/support/serializers.py b/softdesk/support/serializers.py index 21ecacf..1035c57 100644 --- a/softdesk/support/serializers.py +++ b/softdesk/support/serializers.py @@ -22,8 +22,6 @@ class ContributorListSerializer(ModelSerializer): fields = ['contributor'] - - class ProjectSerializer(ModelSerializer): author = StringRelatedField(many=False) @@ -60,29 +58,14 @@ class ProjectDetailSerializer(ModelSerializer): class IssueSerializer(ModelSerializer): - author = StringRelatedField(many=False) - class Meta: model = Issue fields = ['id', 'title', 'project', 'date_created', 'priority', 'tag', 'status', 'author'] - - - def validate_project(self, data): - # if data['user'] not in data['project'].contributors: - # raise ValidationError("User must be a contributor to the project") - #print(data.project) - #if self.context['request'].user not in data.contributors: - # raise ValidationError("User must be a contributor to the project") - #print(self.get_contributors(data)) - - return data - - class IssueDetailSerializer(ModelSerializer): comments = SerializerMethodField() diff --git a/softdesk/support/views.py b/softdesk/support/views.py index efe10aa..aca4b5f 100644 --- a/softdesk/support/views.py +++ b/softdesk/support/views.py @@ -1,8 +1,4 @@ -from django.contrib.auth.checks import check_models_permissions -from django.shortcuts import render -from rest_framework.serializers import raise_errors_on_nested_writes from rest_framework.viewsets import ModelViewSet -from rest_framework.views import APIView from support.models import Project, ProjectContributor, Issue, Comment from authentication.models import User from support.serializers import (ProjectSerializer, @@ -20,16 +16,13 @@ from rest_framework.permissions import (IsAuthenticated, IsAuthenticatedOrReadOnly) from support.permissions import IsAuthor, IsContributor from rest_framework.decorators import action -from rest_framework.exceptions import ValidationError from django.core.exceptions import PermissionDenied class ProjectViewSet(ModelViewSet): permission_classes = [IsAuthenticatedOrReadOnly] - serializer_class = ProjectSerializer detail_serializer_class = ProjectDetailSerializer - queryset = Project.objects.filter(active=True) @@ -56,7 +49,6 @@ class ProjectViewSet(ModelViewSet): serialized.save() return Response(serialized.data) - def perform_create(self, serializer): """set authenticated user as author and contributor on creation""" test = serializer.save(author=self.request.user) @@ -65,15 +57,6 @@ class ProjectViewSet(ModelViewSet): if contributor_serializer.is_valid(): contributor_serializer.save() - - @action(detail=True, methods=['patch'], permission_classes=[IsContributor]) - def test(self, request, pk): - """only for testing purpose, should be deleted not published""" - if not request.user in Project.objects.get(id=pk).contributors.all(): - raise PermissionDenied() - print(request.data) - return Response("OK") - @action(detail=True, methods=['patch'], permission_classes=[IsContributor]) def contributor(self, request, pk): """Add a contributor to a project @@ -82,7 +65,6 @@ class ProjectViewSet(ModelViewSet): #check if requestor is contributor if not request.user in Project.objects.get(id=pk).contributors.all(): raise PermissionDenied() - if request.data is None or not 'contributor' in request.data: return Response(f"Key error;`contributor` is expected", status=status.HTTP_400_BAD_REQUEST) @@ -100,10 +82,8 @@ class ProjectViewSet(ModelViewSet): status=status.HTTP_226_IM_USED) - class IssueViewSet(ModelViewSet): - permission_classes = [IsAuthenticatedOrReadOnly] - + permission_classes = [IsAuthenticated] serializer_class = IssueSerializer detail_serializer_class = IssueDetailSerializer @@ -112,7 +92,6 @@ class IssueViewSet(ModelViewSet): return self.detail_serializer_class return super().get_serializer_class() - def get_queryset(self): """ returns only the issues related to projects @@ -128,24 +107,26 @@ class IssueViewSet(ModelViewSet): #query on a list return Issue.objects.filter(project__in=projects) - def perform_update(self, serializer): + """ + Check if requestor is author allows him to partial update + change the author to assign issue + """ issue = self.get_object() if not self.request.user == issue.author: raise PermissionDenied() if serializer.is_valid(raise_exception=True): - requested_author = User.objects.get( - username=self.request.data['author']) - serializer.save(author=requested_author) - return Response(serializer.data) + if self.request.data['author']: + requested_author = User.objects.get( + username=self.request.data['author']) + serializer.save(author=requested_author) + return Response(serializer.data) return Response("Data error", status=status.HTTP_400_BAD_REQUEST) - - @action(detail=True, methods=['get']) def contributors(self, request, pk): """ - check if requestor is contributor then returns the list + Check if requestor is contributor then returns the list of the contributors to the issue's project or raise unauthorized """ issue = Issue.objects.get(id=pk) @@ -154,7 +135,6 @@ class IssueViewSet(ModelViewSet): else: raise PermissionDenied() - def create(self, request, *args, **kwargs): if not 'project' in request.data: return Response("A project id is required", @@ -173,39 +153,34 @@ class IssueViewSet(ModelViewSet): return Response(response, status = status.HTTP_201_CREATED) - class CommentViewSet(ModelViewSet): - permission_classes = [IsAuthenticatedOrReadOnly] - + permission_classes = [IsAuthenticated] serializer_class = CommentListSerializer detail_serializer_class = CommentDetailSerializer - queryset = Comment.objects.all() def get_queryset(self): - """returns only comments associated with issue where the requestor + """ + Returns only comments associated with issue where the requestor is project's contributor """ if self.request.GET.get('issue'): issue_id = int(self.request.GET.get('issue')) - print(issue_id, type(issue_id)) project = Issue.objects.get(id=issue_id).project - if not self.request.user in Issue.objects.get( - id=issue_id).project.contributors.all(): + if not self.request.user in project.contributors.all(): raise PermissionDenied() return Comment.objects.filter(issue=issue_id) - if self.request.data: - return Comment.objects.filter(issue=self.request.data['issue']) - - + #or returns those from projects where requestor is contributing + projects = Project.objects.filter(contributors=self.request.user).values('id') + print(projects) + issues = Issue.objects.filter(project__in=projects) + return Comment.objects.filter(issue__in=issues) def get_serializer_class(self): if self.action == 'retrieve': return self.detail_serializer_class return super().get_serializer_class() - - def create(self, request, *args, **kwargs): user = request.user issue = Issue.objects.get(id=request.data['issue']) @@ -220,4 +195,4 @@ class CommentViewSet(ModelViewSet): return Response(response, status=status.HTTP_201_CREATED) return Response("Not allowed; " f"{user} isn't contributor for project {project}", - status=status.HTTP_403_FORBIDDEN) \ No newline at end of file + status=status.HTTP_403_FORBIDDEN)