(back) new endpoint document can_edit

The endpoint can_edit is added to the DocumentViewset, it will give the
information to the frontend application id the current user can edit the
Docs based on the no-websocket rules.
This commit is contained in:
Manuel Raynaud
2025-06-26 07:17:00 +02:00
parent 651f2d1d75
commit 118804e810
7 changed files with 289 additions and 32 deletions

View File

@@ -635,54 +635,76 @@ class DocumentViewSet(
"""Override to implement a soft delete instead of dumping the record in database."""
instance.soft_delete()
def perform_update(self, serializer):
"""Check rules about collaboration."""
if serializer.validated_data.get("websocket"):
return super().perform_update(serializer)
def _can_user_edit_document(self, document_id, set_cache=False):
"""Check if the user can edit the document."""
try:
connection_info = CollaborationService().get_document_connection_info(
serializer.instance.id,
count, exists = CollaborationService().get_document_connection_info(
document_id,
self.request.session.session_key,
)
except requests.HTTPError as e:
capture_exception(e)
connection_info = {
"count": 0,
"exists": False,
}
logger.exception("Failed to call collaboration server: %s", e)
count = 0
exists = False
if connection_info["count"] == 0:
# No websocket mode
if count == 0:
# Nobody is connected to the websocket server
logger.debug("update without connection found in the websocket server")
cache_key = f"docs:no-websocket:{serializer.instance.id}"
cache_key = f"docs:no-websocket:{document_id}"
current_editor = cache.get(cache_key)
if not current_editor:
cache.set(
cache_key,
self.request.session.session_key,
settings.NO_WEBSOCKET_CACHE_TIMEOUT,
)
elif current_editor != self.request.session.session_key:
raise drf.exceptions.PermissionDenied(
"You are not allowed to edit this document."
)
cache.touch(cache_key, settings.NO_WEBSOCKET_CACHE_TIMEOUT)
return super().perform_update(serializer)
if connection_info["exists"]:
# Websocket mode
if not current_editor:
if set_cache:
cache.set(
cache_key,
self.request.session.session_key,
settings.NO_WEBSOCKET_CACHE_TIMEOUT,
)
return True
if current_editor != self.request.session.session_key:
return False
if set_cache:
cache.touch(cache_key, settings.NO_WEBSOCKET_CACHE_TIMEOUT)
return True
if exists:
# Current user is connected to the websocket server
logger.debug("session key found in the websocket server")
return super().perform_update(serializer)
return True
logger.debug(
"Users connected to the websocket but current editor not connected to it. Can not edit."
)
return False
def perform_update(self, serializer):
"""Check rules about collaboration."""
if serializer.validated_data.get("websocket", False):
return super().perform_update(serializer)
if self._can_user_edit_document(serializer.instance.id, set_cache=True):
return super().perform_update(serializer)
raise drf.exceptions.PermissionDenied(
"You are not allowed to edit this document."
)
@drf.decorators.action(
detail=True,
methods=["get"],
url_path="can-edit",
)
def can_edit(self, request, *args, **kwargs):
"""Check if the current user can edit the document."""
document = self.get_object()
return drf.response.Response(
{"can_edit": self._can_user_edit_document(document.id)}
)
@drf.decorators.action(
detail=False,
methods=["get"],