Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
36 changes: 36 additions & 0 deletions apps/api/plane/api/serializers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
import random
from rest_framework import serializers


# Python imports
import re

# Module imports
from plane.db.models import Project, ProjectIdentifier, WorkspaceMember, State, Estimate

Expand All @@ -10,6 +14,11 @@
)
from .base import BaseSerializer

# Regex pattern to block the following special characters in names and identifiers:
# & + , : ; $ ^ } { * = ? @ # | ' < > . ( ) % !

FORBIDDEN_NAME_CHARS_PATTERN = r"^.*[&+,:;$^}{*=?@#|'<>.()%!].*$"


class ProjectCreateSerializer(BaseSerializer):
"""
Expand Down Expand Up @@ -97,6 +106,15 @@ class Meta:
]

def validate(self, data):
project_name = data.get("name", None)
project_identifier = data.get("identifier", None)

if project_name is not None and re.match(FORBIDDEN_NAME_CHARS_PATTERN, project_name):
raise serializers.ValidationError("Project name cannot contain special characters.")

if project_identifier is not None and re.match(FORBIDDEN_NAME_CHARS_PATTERN, project_identifier):
raise serializers.ValidationError("Project identifier cannot contain special characters.")

if data.get("project_lead", None) is not None:
# Check if the project lead is a member of the workspace
if not WorkspaceMember.objects.filter(
Expand Down Expand Up @@ -156,6 +174,15 @@ class Meta(ProjectCreateSerializer.Meta):
read_only_fields = ProjectCreateSerializer.Meta.read_only_fields

def update(self, instance, validated_data):
project_name = validated_data.get("name", None)
project_identifier = validated_data.get("identifier", None)

if project_name is not None and re.match(FORBIDDEN_NAME_CHARS_PATTERN, project_name):
raise serializers.ValidationError("Project name cannot contain special characters.")

if project_identifier is not None and re.match(FORBIDDEN_NAME_CHARS_PATTERN, project_identifier):
raise serializers.ValidationError("Project identifier cannot contain special characters.")

"""Update a project"""
if (
validated_data.get("default_state", None) is not None
Expand Down Expand Up @@ -206,6 +233,15 @@ class Meta:
]

def validate(self, data):
project_name = data.get("name", None)
project_identifier = data.get("identifier", None)

if project_name is not None and re.match(FORBIDDEN_NAME_CHARS_PATTERN, project_name):
raise serializers.ValidationError("Project name cannot contain special characters.")

if project_identifier is not None and re.match(FORBIDDEN_NAME_CHARS_PATTERN, project_identifier):
raise serializers.ValidationError("Project identifier cannot contain special characters.")

# Check project lead should be a member of the workspace
if (
data.get("project_lead", None) is not None
Expand Down
14 changes: 14 additions & 0 deletions apps/api/plane/app/serializers/project.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Third party imports
from rest_framework import serializers

# Python imports
import re

# Module imports
from .base import BaseSerializer, DynamicBaseSerializer
from django.db.models import Max
Expand All @@ -19,6 +22,11 @@
validate_html_content,
)

# Regex pattern to block the following special characters in names and identifiers:
# & + , : ; $ ^ } { * = ? @ # | ' < > . ( ) % !

FORBIDDEN_NAME_CHARS_PATTERN = r"^.*[&+,:;$^}{*=?@#|'<>.()%!].*$"


class ProjectSerializer(BaseSerializer):
workspace_detail = WorkspaceLiteSerializer(source="workspace", read_only=True)
Expand All @@ -33,6 +41,9 @@ def validate_name(self, name):
project_id = self.instance.id if self.instance else None
workspace_id = self.context["workspace_id"]

if re.match(FORBIDDEN_NAME_CHARS_PATTERN, name):
raise serializers.ValidationError("Project name cannot contain special characters.")

project = Project.objects.filter(name=name, workspace_id=workspace_id)

if project_id:
Expand All @@ -49,6 +60,9 @@ def validate_identifier(self, identifier):
project_id = self.instance.id if self.instance else None
workspace_id = self.context["workspace_id"]

if re.match(FORBIDDEN_NAME_CHARS_PATTERN, identifier):
raise serializers.ValidationError("Project identifier cannot contain special characters.")

project = Project.objects.filter(identifier=identifier, workspace_id=workspace_id)

if project_id:
Expand Down
Loading