Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions apiserver/plane/app/views/workspace/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS
from plane.license.utils.instance_value import get_configuration_value


class WorkSpaceViewSet(BaseViewSet):
model = Workspace
serializer_class = WorkSpaceSerializer
Expand Down Expand Up @@ -81,12 +82,12 @@ def get_queryset(self):

def create(self, request):
try:
DISABLE_WORKSPACE_CREATION, = get_configuration_value(
(DISABLE_WORKSPACE_CREATION,) = get_configuration_value(
[
{
"key": "DISABLE_WORKSPACE_CREATION",
"default": os.environ.get("DISABLE_WORKSPACE_CREATION", "0"),
},
}
]
)

Expand Down Expand Up @@ -144,8 +145,24 @@ def partial_update(self, request, *args, **kwargs):
return super().partial_update(request, *args, **kwargs)

@allow_permission([ROLE.ADMIN], level="WORKSPACE")
def destroy(self, request, *args, **kwargs):
return super().destroy(request, *args, **kwargs)
def destroy(self, request, slug):
try:
workspace = Workspace.objects.get(slug=slug)
except Workspace.DoesNotExist:
return Response(
{"error": "Workspace not found"}, status=status.HTTP_404_NOT_FOUND
)

# Trash the workspace by appending the epoch and `trash` to the slug
epoch = int(timezone.now().timestamp())
updated_workspace_slug = f"trash-{epoch}-{workspace.slug}"
if len(updated_workspace_slug) > 48:
updated_workspace_slug = updated_workspace_slug[:48]

workspace.slug = updated_workspace_slug
workspace.save()
workspace.delete()
Comment on lines +156 to +164
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add transaction management and improve slug handling.

Several improvements needed for robustness:

  1. The slug truncation might affect uniqueness by cutting off the epoch
  2. Operations should be atomic
  3. Should validate against restricted slugs

Consider this implementation:

+from django.db import transaction
+from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS

-        # Trash the workspace by appending the epoch and `trash` to the slug
-        epoch = int(timezone.now().timestamp())
-        updated_workspace_slug = f"trash-{epoch}-{workspace.slug}"
-        if len(updated_workspace_slug) > 48:
-            updated_workspace_slug = updated_workspace_slug[:48]
-
-        workspace.slug = updated_workspace_slug
-        workspace.save()
-        workspace.delete()
+        with transaction.atomic():
+            epoch = int(timezone.now().timestamp())
+            base_slug = workspace.slug[:20]  # Preserve start of original slug
+            updated_workspace_slug = f"trash-{epoch}-{base_slug}"
+            
+            # Ensure the new slug isn't in restricted list
+            if updated_workspace_slug in RESTRICTED_WORKSPACE_SLUGS:
+                updated_workspace_slug = f"deleted-{updated_workspace_slug}"
+                
+            workspace.slug = updated_workspace_slug[:48]
+            workspace.save()
+            workspace.delete()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Trash the workspace by appending the epoch and `trash` to the slug
epoch = int(timezone.now().timestamp())
updated_workspace_slug = f"trash-{epoch}-{workspace.slug}"
if len(updated_workspace_slug) > 48:
updated_workspace_slug = updated_workspace_slug[:48]
workspace.slug = updated_workspace_slug
workspace.save()
workspace.delete()
from django.db import transaction
from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS
with transaction.atomic():
epoch = int(timezone.now().timestamp())
base_slug = workspace.slug[:20] # Preserve start of original slug
updated_workspace_slug = f"trash-{epoch}-{base_slug}"
# Ensure the new slug isn't in restricted list
if updated_workspace_slug in RESTRICTED_WORKSPACE_SLUGS:
updated_workspace_slug = f"deleted-{updated_workspace_slug}"
workspace.slug = updated_workspace_slug[:48]
workspace.save()
workspace.delete()

return Response(status=status.HTTP_204_NO_CONTENT)


class UserWorkSpacesEndpoint(BaseAPIView):
Expand Down