Skip to content

Commit 437d50f

Browse files
lunikaAntoLC
authored andcommitted
✨(backend) add comment viewset
This commit add the CRUD part to manage comment lifeycle. Permissions are relying on the Document and Comment abilities. Comment viewset depends on the Document route and is added to the document_related_router. Dedicated serializer and permission are created.
1 parent 7a715ad commit 437d50f

File tree

6 files changed

+687
-1
lines changed

6 files changed

+687
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ and this project adheres to
3838

3939
### Added
4040

41+
- ✨(backend) Comments on text editor #1309
4142
- 👷(CI) add bundle size check job #1268
4243
- ✨(frontend) use title first emoji as doc icon in tree #1289
4344

src/backend/core/api/permissions.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,19 @@ def has_object_permission(self, request, view, obj):
171171

172172
action = view.action
173173
return abilities.get(action, False)
174+
175+
176+
class CommentPermission(permissions.BasePermission):
177+
"""Permission class for comments."""
178+
179+
def has_permission(self, request, view):
180+
"""Check permission for a given object."""
181+
if view.action in ["create", "list"]:
182+
document_abilities = view.get_document_or_404().get_abilities(request.user)
183+
return document_abilities["comment"]
184+
185+
return True
186+
187+
def has_object_permission(self, request, view, obj):
188+
"""Check permission for a given object."""
189+
return obj.get_abilities(request.user).get(view.action, False)

src/backend/core/api/serializers.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,3 +821,47 @@ class MoveDocumentSerializer(serializers.Serializer):
821821
choices=enums.MoveNodePositionChoices.choices,
822822
default=enums.MoveNodePositionChoices.LAST_CHILD,
823823
)
824+
825+
826+
class CommentSerializer(serializers.ModelSerializer):
827+
"""Serialize comments."""
828+
829+
user = UserLightSerializer(read_only=True)
830+
abilities = serializers.SerializerMethodField(read_only=True)
831+
832+
class Meta:
833+
model = models.Comment
834+
fields = [
835+
"id",
836+
"content",
837+
"created_at",
838+
"updated_at",
839+
"user",
840+
"document",
841+
"abilities",
842+
]
843+
read_only_fields = [
844+
"id",
845+
"created_at",
846+
"updated_at",
847+
"user",
848+
"document",
849+
"abilities",
850+
]
851+
852+
def get_abilities(self, comment) -> dict:
853+
"""Return abilities of the logged-in user on the instance."""
854+
request = self.context.get("request")
855+
if request:
856+
return comment.get_abilities(request.user)
857+
return {}
858+
859+
def validate(self, attrs):
860+
"""Validate invitation data."""
861+
request = self.context.get("request")
862+
user = getattr(request, "user", None)
863+
864+
attrs["document_id"] = self.context["resource_id"]
865+
attrs["user_id"] = user.id if user else None
866+
867+
return attrs

src/backend/core/api/viewsets.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,3 +2174,36 @@ def _load_theme_customization(self):
21742174
)
21752175

21762176
return theme_customization
2177+
2178+
2179+
class CommentViewSet(
2180+
viewsets.ModelViewSet,
2181+
):
2182+
"""API ViewSet for comments."""
2183+
2184+
permission_classes = [permissions.CommentPermission]
2185+
queryset = models.Comment.objects.select_related("user", "document").all()
2186+
serializer_class = serializers.CommentSerializer
2187+
pagination_class = Pagination
2188+
_document = None
2189+
2190+
def get_document_or_404(self):
2191+
"""Get the document related to the viewset or raise a 404 error."""
2192+
if self._document is None:
2193+
try:
2194+
self._document = models.Document.objects.get(
2195+
pk=self.kwargs["resource_id"],
2196+
)
2197+
except models.Document.DoesNotExist as e:
2198+
raise drf.exceptions.NotFound("Document not found.") from e
2199+
return self._document
2200+
2201+
def get_serializer_context(self):
2202+
"""Extra context provided to the serializer class."""
2203+
context = super().get_serializer_context()
2204+
context["resource_id"] = self.kwargs["resource_id"]
2205+
return context
2206+
2207+
def get_queryset(self):
2208+
"""Return the queryset according to the action."""
2209+
return super().get_queryset().filter(document=self.kwargs["resource_id"])

0 commit comments

Comments
 (0)