From 6a62fec9e8fab6c162c57915f3629ec8beff937e Mon Sep 17 00:00:00 2001 From: Xudong Sun Date: Thu, 19 Mar 2026 11:13:52 +0800 Subject: [PATCH] feat: allow spaces in profile display names (#97) --- .../skillhub/dto/UpdateProfileRequest.java | 4 ++-- .../src/main/resources/messages.properties | 3 +-- .../src/main/resources/messages_zh.properties | 3 +-- .../controller/UserProfileControllerTest.java | 19 +++++++++++++++++++ web/src/i18n/locales/en.json | 2 +- web/src/i18n/locales/zh.json | 2 +- web/src/pages/settings/profile.tsx | 4 ++-- 7 files changed, 27 insertions(+), 10 deletions(-) diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/UpdateProfileRequest.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/UpdateProfileRequest.java index 3f264b02..b9aed821 100644 --- a/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/UpdateProfileRequest.java +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/UpdateProfileRequest.java @@ -12,14 +12,14 @@ import jakarta.validation.constraints.Size; *

Validation rules for displayName: *

* * @param displayName new display name (nullable — omit to leave unchanged) */ public record UpdateProfileRequest( @Size(min = 2, max = 32, message = "error.profile.displayName.length") - @Pattern(regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9_-]+$", + @Pattern(regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9_ -]+$", message = "error.profile.displayName.pattern") String displayName ) { diff --git a/server/skillhub-app/src/main/resources/messages.properties b/server/skillhub-app/src/main/resources/messages.properties index 7467829e..1ecfbac6 100644 --- a/server/skillhub-app/src/main/resources/messages.properties +++ b/server/skillhub-app/src/main/resources/messages.properties @@ -127,8 +127,7 @@ error.skill.approve.nameConflict=Cannot approve: a published skill with name ''{ # Profile update error.profile.displayName.length=Display name must be between 2 and 32 characters -error.profile.displayName.pattern=Display name can only contain Chinese characters, English letters, numbers, underscores, and hyphens +error.profile.displayName.pattern=Display name can only contain Chinese characters, English letters, numbers, spaces, underscores, and hyphens error.profile.noChanges=At least one field must be provided response.profile.updated=Profile updated successfully response.profile.pendingReview=Profile changes submitted for review - diff --git a/server/skillhub-app/src/main/resources/messages_zh.properties b/server/skillhub-app/src/main/resources/messages_zh.properties index 5075d0ae..c09516be 100644 --- a/server/skillhub-app/src/main/resources/messages_zh.properties +++ b/server/skillhub-app/src/main/resources/messages_zh.properties @@ -127,8 +127,7 @@ error.skill.approve.nameConflict=无法通过审核:该命名空间下已存 # 用户资料修改 error.profile.displayName.length=昵称长度需在 2-32 个字符之间 -error.profile.displayName.pattern=昵称仅允许中文、英文、数字、下划线和连字符 +error.profile.displayName.pattern=昵称仅允许中文、英文、数字、空格、下划线和连字符 error.profile.noChanges=至少需要提供一个修改字段 response.profile.updated=资料已更新 response.profile.pendingReview=资料变更已提交审核 - diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/UserProfileControllerTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/UserProfileControllerTest.java index fcd240df..b4c25934 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/UserProfileControllerTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/UserProfileControllerTest.java @@ -135,6 +135,25 @@ class UserProfileControllerTest { .andExpect(jsonPath("$.data.status").value("APPLIED")); } + @Test + void updateProfile_displayNameWithSpaces_shouldReturn200() throws Exception { + var principal = testPrincipal(); + var user = new UserAccount("user-1", "OldName", "user@example.com", "https://example.com/avatar.png"); + + given(userAccountRepository.findById("user-1")).willReturn(Optional.of(user)); + given(namespaceMemberRepository.findByUserId("user-1")).willReturn(List.of()); + given(userRoleBindingRepository.findByUserId("user-1")).willReturn(List.of()); + + mockMvc.perform(patch("/api/v1/user/profile") + .with(authentication(testAuth(principal))) + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content("{\"displayName\":\"New Name\"}")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)) + .andExpect(jsonPath("$.data.status").value("APPLIED")); + } + // ===== AC-E-001: Display name too short ===== @Test diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index 5b6c6336..39f4d5e2 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -525,7 +525,7 @@ "defaultError": "Failed to update profile. Please try again.", "validation": { "length": "Display name must be 2-32 characters.", - "pattern": "Display name can only contain Chinese, English, digits, underscores, and hyphens." + "pattern": "Display name can only contain Chinese, English, digits, spaces, underscores, and hyphens." } }, "security": { diff --git a/web/src/i18n/locales/zh.json b/web/src/i18n/locales/zh.json index 7a6d7a3e..01651211 100644 --- a/web/src/i18n/locales/zh.json +++ b/web/src/i18n/locales/zh.json @@ -525,7 +525,7 @@ "defaultError": "修改失败,请稍后重试。", "validation": { "length": "昵称长度需为 2-32 个字符。", - "pattern": "昵称只能包含中文、英文、数字、下划线和连字符。" + "pattern": "昵称只能包含中文、英文、数字、空格、下划线和连字符。" } }, "security": { diff --git a/web/src/pages/settings/profile.tsx b/web/src/pages/settings/profile.tsx index ce9327ff..b54f235a 100644 --- a/web/src/pages/settings/profile.tsx +++ b/web/src/pages/settings/profile.tsx @@ -9,8 +9,8 @@ import { Button } from '@/shared/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/ui/card' import { Input } from '@/shared/ui/input' -/** Regex matching allowed display name characters: Chinese, English, digits, underscore, hyphen. */ -const DISPLAY_NAME_PATTERN = /^[\u4e00-\u9fa5a-zA-Z0-9_-]+$/ +/** Regex matching allowed display name characters: Chinese, English, digits, spaces, underscore, hyphen. */ +const DISPLAY_NAME_PATTERN = /^[\u4e00-\u9fa5a-zA-Z0-9_ -]+$/ export function ProfileSettingsPage() { const { t } = useTranslation()