Compare commits

...

1 Commits

Author SHA1 Message Date
pablohashescobar
c65e0a6668 chore: add workspace creation validation 2025-05-29 14:51:13 +05:30
4 changed files with 70 additions and 10 deletions

View File

@@ -3,11 +3,18 @@ from rest_framework import serializers
# Module import
from plane.db.models import Account, Profile, User, Workspace, WorkspaceMemberInvite
from plane.utils.url import clean_value
from .base import BaseSerializer
class UserSerializer(BaseSerializer):
def validate_first_name(self, value):
return clean_value(value)
def validate_last_name(self, value):
return clean_value(value)
class Meta:
model = User
# Exclude password field from the serializer

View File

@@ -1,7 +1,11 @@
# Django imports
from django.core.validators import URLValidator
from django.core.exceptions import ValidationError
from django.template.defaultfilters import slugify
# Third party imports
from rest_framework import serializers
from rest_framework import status
from rest_framework.response import Response
# Module imports
from .base import BaseSerializer, DynamicBaseSerializer
@@ -25,10 +29,7 @@ from plane.db.models import (
WorkspaceUserPreference,
)
from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS
# Django imports
from django.core.validators import URLValidator
from django.core.exceptions import ValidationError
from plane.utils.url import clean_value
class WorkSpaceSerializer(DynamicBaseSerializer):
@@ -40,7 +41,30 @@ class WorkSpaceSerializer(DynamicBaseSerializer):
# Check if the slug is restricted
if value in RESTRICTED_WORKSPACE_SLUGS:
raise serializers.ValidationError("Slug is not valid")
return value
# Clean the slug
slug = clean_value(value)
# If the slug is empty, return an error
if not slug:
raise serializers.ValidationError("Slug cannot be empty")
# Slugify the slug
slug = slugify(slug)
# Return the slug
return slug
def validate_name(self, value):
# Clean the name
name = clean_value(value)
# If the name is empty, return an error
if not name:
raise serializers.ValidationError("Name cannot be empty")
# Return the name
return name
class Meta:
model = Workspace

View File

@@ -92,8 +92,6 @@ class WorkSpaceViewSet(BaseViewSet):
status=status.HTTP_403_FORBIDDEN,
)
serializer = WorkSpaceSerializer(data=request.data)
slug = request.data.get("slug", False)
name = request.data.get("name", False)
@@ -109,6 +107,9 @@ class WorkSpaceViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
# Validate the serializer
serializer = WorkSpaceSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(owner=request.user)
# Create Workspace member

View File

@@ -77,3 +77,31 @@ def normalize_url_path(url: str) -> str:
normalized_path = re.sub(r"/+", "/", parts.path)
# Reconstruct the URL
return urlunparse(parts._replace(path=normalized_path))
def clean_value(value: str) -> str:
"""
Clean the value by removing URLs and domain patterns.
Args:
value (str): The value to clean.
Returns:
str: The cleaned value.
"""
if not value:
return value
url_pattern = r"(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" # noqa
# Remove URLs and domains
cleaned_value = re.sub(url_pattern, "", value)
# Keep only alphanumeric characters and spaces
cleaned_value = re.sub(r"[^a-zA-Z0-9\s]", "", cleaned_value)
# Remove extra spaces and trim
cleaned_value = " ".join(cleaned_value.split())
return cleaned_value