Compare commits

...

10 Commits

Author SHA1 Message Date
sangeethailango b4acaa2086 chore: test cases 2025-09-04 17:04:06 +05:30
sangeethailango 00e38a7149 chore: move validation to serializer 2025-09-03 16:40:17 +05:30
sangeethailango 04e14f32bf chore: move validation to viewset 2025-09-03 16:21:41 +05:30
gakshita 56795bbcba fix: allowed empty screen for last name 2025-09-03 16:14:10 +05:30
gakshita 03bbe79320 Merge branch 'fix-user-name-validation' of https://github.com/makeplane/plane into fix-user-name-validation 2025-08-28 19:21:59 +05:30
gakshita 9ef0de4848 fix: allowed spaces 2025-08-28 19:21:57 +05:30
sangeethailango 4e4e3ef659 Merge branch 'fix-user-name-validation' of github.com:makeplane/plane into fix-user-name-validation 2025-08-28 19:18:23 +05:30
sangeethailango 43cdaec895 chore: allow space 2025-08-28 19:15:09 +05:30
gakshita fde6de3fcf fix: handled fe to not allow special characters in first_name and last_name 2025-08-28 16:04:50 +05:30
sangeethailango 33d3e032b3 fix: user name validation 2025-08-21 14:57:59 +05:30
4 changed files with 152 additions and 0 deletions
+15
View File
@@ -7,16 +7,31 @@ from plane.utils.url import contains_url
from .base import BaseSerializer
# Django import
import re
class UserSerializer(BaseSerializer):
def validate_first_name(self, value):
if contains_url(value):
raise serializers.ValidationError("First name cannot contain a URL.")
if not re.match(r"^[a-zA-Z0-9_\- ]+$", value):
raise serializers.ValidationError(
"first name can only contain letters, numbers, hyphens (-), and underscores (_)"
)
return value
def validate_last_name(self, value):
if contains_url(value):
raise serializers.ValidationError("Last name cannot contain a URL.")
if not re.match(r"^[a-zA-Z0-9_\- ]+$", value) and not value == "":
raise serializers.ValidationError(
"last name can only contain letters, numbers, hyphens (-), and underscores (_)"
)
return value
class Meta:
@@ -0,0 +1,118 @@
import pytest
from rest_framework import serializers
from plane.app.serializers.user import UserSerializer
@pytest.mark.unit
class TestUserSerializer:
"""Test the UserSerializer"""
def test_validate_first_name_valid(self):
"""Test that valid first names are accepted"""
serializer = UserSerializer()
valid_names = [
"John",
"John Doe",
"John-Doe",
"John_Doe",
"John123",
]
for name in valid_names:
result = serializer.validate_first_name(name)
assert result == name
def test_validate_first_name_with_url(self):
"""Test that first names containing URLs are rejected"""
serializer = UserSerializer()
invalid_names = [
"http://example.com",
"John https://test.com",
"www.test.com",
]
for name in invalid_names:
with pytest.raises(serializers.ValidationError) as exc_info:
serializer.validate_first_name(name)
assert str(exc_info.value.detail[0]) == "First name cannot contain a URL."
def test_validate_first_name_with_special_chars(self):
"""Test that first names with special characters are rejected"""
serializer = UserSerializer()
invalid_names = [
"John@Doe",
"John#Doe",
"John$Doe",
"John!Doe",
"John&Doe",
]
for name in invalid_names:
with pytest.raises(serializers.ValidationError) as exc_info:
serializer.validate_first_name(name)
assert str(exc_info.value.detail[0]) == (
"first name can only contain letters, numbers, "
"hyphens (-), and underscores (_)"
)
def test_validate_last_name_valid(self):
"""Test that valid last names are accepted"""
serializer = UserSerializer()
valid_names = [
"Smith",
"Smith Jr",
"Smith-Jr",
"Smith_Jr",
"Smith123",
"",
]
for name in valid_names:
result = serializer.validate_last_name(name)
assert result == name
def test_validate_last_name_with_url(self):
"""Test that last names containing URLs are rejected"""
serializer = UserSerializer()
invalid_names = [
"http://example.com",
"Smith https://test.com",
"www.test.com",
]
for name in invalid_names:
with pytest.raises(serializers.ValidationError) as exc_info:
serializer.validate_last_name(name)
assert str(exc_info.value.detail[0]) == "Last name cannot contain a URL."
def test_validate_last_name_with_special_chars(self):
"""Test that last names with special characters are rejected"""
serializer = UserSerializer()
invalid_names = [
"Smith@Jr",
"Smith#Jr",
"Smith$Jr",
"Smith!Jr",
"Smith&Jr",
]
for name in invalid_names:
with pytest.raises(serializers.ValidationError) as exc_info:
serializer.validate_last_name(name)
assert str(exc_info.value.detail[0]) == (
"last name can only contain letters, numbers, "
"hyphens (-), and underscores (_)"
)
@@ -213,6 +213,11 @@ export const ProfileSetupStep: FC<Props> = observer(({ handleStepChange }) => {
value: 24,
message: "Name must be within 24 characters.",
},
validate: (value) => {
if (!/^[a-zA-Z0-9 _-]+$/.test(value))
return "First name can only contain letters, numbers, hyphens, and underscores.";
return true;
},
}}
render={({ field: { value, onChange, ref } }) => (
<input
+14
View File
@@ -247,6 +247,11 @@ export const ProfileForm = observer((props: TProfileFormProps) => {
name="first_name"
rules={{
required: "Please enter first name",
validate: (value) => {
if (!/^[a-zA-Z0-9 _-]+$/.test(value))
return "First name can only contain letters, numbers, hyphens, and underscores.";
return true;
},
}}
render={({ field: { value, onChange, ref } }) => (
<Input
@@ -271,6 +276,14 @@ export const ProfileForm = observer((props: TProfileFormProps) => {
<Controller
control={control}
name="last_name"
rules={{
validate: (value) => {
if (value === "") return true;
if (!/^[a-zA-Z0-9 _-]+$/.test(value))
return "Last name can only contain letters, numbers, hyphens, and underscores.";
return true;
},
}}
render={({ field: { value, onChange, ref } }) => (
<Input
id="last_name"
@@ -287,6 +300,7 @@ export const ProfileForm = observer((props: TProfileFormProps) => {
/>
)}
/>
{errors?.last_name && <span className="text-xs text-red-500">{errors?.last_name?.message}</span>}
</div>
<div className="flex flex-col gap-1">
<h4 className="text-sm font-medium text-custom-text-200">