Skip to content

Commit f2b993c

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 733ba56 commit f2b993c

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
@@ -70,6 +70,7 @@ and this project adheres to
7070

7171
### Added
7272

73+
- ✨(backend) Comments on text editor #1309
7374
- 👷(CI) add bundle size check job #1268
7475
- ✨(frontend) use title first emoji as doc icon in tree #1289
7576

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
@@ -877,3 +877,47 @@ class MoveDocumentSerializer(serializers.Serializer):
877877
choices=enums.MoveNodePositionChoices.choices,
878878
default=enums.MoveNodePositionChoices.LAST_CHILD,
879879
)
880+
881+
882+
class CommentSerializer(serializers.ModelSerializer):
883+
"""Serialize comments."""
884+
885+
user = UserLightSerializer(read_only=True)
886+
abilities = serializers.SerializerMethodField(read_only=True)
887+
888+
class Meta:
889+
model = models.Comment
890+
fields = [
891+
"id",
892+
"content",
893+
"created_at",
894+
"updated_at",
895+
"user",
896+
"document",
897+
"abilities",
898+
]
899+
read_only_fields = [
900+
"id",
901+
"created_at",
902+
"updated_at",
903+
"user",
904+
"document",
905+
"abilities",
906+
]
907+
908+
def get_abilities(self, comment) -> dict:
909+
"""Return abilities of the logged-in user on the instance."""
910+
request = self.context.get("request")
911+
if request:
912+
return comment.get_abilities(request.user)
913+
return {}
914+
915+
def validate(self, attrs):
916+
"""Validate invitation data."""
917+
request = self.context.get("request")
918+
user = getattr(request, "user", None)
919+
920+
attrs["document_id"] = self.context["resource_id"]
921+
attrs["user_id"] = user.id if user else None
922+
923+
return attrs

src/backend/core/api/viewsets.py

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

22032203
return theme_customization
2204+
2205+
2206+
class CommentViewSet(
2207+
viewsets.ModelViewSet,
2208+
):
2209+
"""API ViewSet for comments."""
2210+
2211+
permission_classes = [permissions.CommentPermission]
2212+
queryset = models.Comment.objects.select_related("user", "document").all()
2213+
serializer_class = serializers.CommentSerializer
2214+
pagination_class = Pagination
2215+
_document = None
2216+
2217+
def get_document_or_404(self):
2218+
"""Get the document related to the viewset or raise a 404 error."""
2219+
if self._document is None:
2220+
try:
2221+
self._document = models.Document.objects.get(
2222+
pk=self.kwargs["resource_id"],
2223+
)
2224+
except models.Document.DoesNotExist as e:
2225+
raise drf.exceptions.NotFound("Document not found.") from e
2226+
return self._document
2227+
2228+
def get_serializer_context(self):
2229+
"""Extra context provided to the serializer class."""
2230+
context = super().get_serializer_context()
2231+
context["resource_id"] = self.kwargs["resource_id"]
2232+
return context
2233+
2234+
def get_queryset(self):
2235+
"""Return the queryset according to the action."""
2236+
return super().get_queryset().filter(document=self.kwargs["resource_id"])

0 commit comments

Comments
 (0)