diff --git a/Makefile b/Makefile index 130f0986..f03a2938 100644 --- a/Makefile +++ b/Makefile @@ -263,7 +263,8 @@ staging: ## 构建并启动 staging 环境,运行 smoke test(混合模式: @echo "=== [4/5] Starting staging services ===" $(STAGING_COMPOSE) up -d --wait server web @echo "=== [5/5] Running smoke tests ===" - @if bash scripts/smoke-test.sh $(STAGING_API_URL); then \ + @if BOOTSTRAP_ADMIN_USERNAME=admin BOOTSTRAP_ADMIN_PASSWORD='Admin@staging2026' \ + bash scripts/smoke-test.sh $(STAGING_API_URL); then \ echo ""; \ echo "Staging passed. Environment is running:"; \ echo " Web UI: $(STAGING_WEB_URL)"; \ diff --git a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/label/LabelDefinitionService.java b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/label/LabelDefinitionService.java index 76dd163b..d836dab9 100644 --- a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/label/LabelDefinitionService.java +++ b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/label/LabelDefinitionService.java @@ -28,7 +28,7 @@ public class LabelDefinitionService { this.labelDefinitionRepository = labelDefinitionRepository; this.labelTranslationRepository = labelTranslationRepository; this.labelPermissionChecker = labelPermissionChecker; - this.maxLabelDefinitions = maxLabelDefinitions; + this.maxLabelDefinitions = requirePositive(maxLabelDefinitions, "skillhub.label.max-definitions"); } public List listAll() { @@ -206,6 +206,13 @@ public class LabelDefinitionService { return new DomainBadRequestException("label.slug.duplicate", slug); } + private int requirePositive(int value, String propertyName) { + if (value <= 0) { + throw new IllegalArgumentException(propertyName + " must be greater than 0"); + } + return value; + } + public record LabelSortOrderUpdate(Long labelId, int sortOrder) { } } diff --git a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/label/SkillLabelService.java b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/label/SkillLabelService.java index f169401f..9c699cb5 100644 --- a/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/label/SkillLabelService.java +++ b/server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/label/SkillLabelService.java @@ -31,7 +31,7 @@ public class SkillLabelService { this.labelDefinitionRepository = labelDefinitionRepository; this.skillLabelRepository = skillLabelRepository; this.labelPermissionChecker = labelPermissionChecker; - this.maxLabelsPerSkill = maxLabelsPerSkill; + this.maxLabelsPerSkill = requirePositive(maxLabelsPerSkill, "skillhub.label.max-per-skill"); } public List listSkillLabels(Long skillId) { @@ -95,4 +95,11 @@ public class SkillLabelService { throw new DomainForbiddenException("label.skill.no_permission"); } } + + private int requirePositive(int value, String propertyName) { + if (value <= 0) { + throw new IllegalArgumentException(propertyName + " must be greater than 0"); + } + return value; + } } diff --git a/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/label/LabelDefinitionServiceTest.java b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/label/LabelDefinitionServiceTest.java index 3ea93306..f4252ad0 100644 --- a/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/label/LabelDefinitionServiceTest.java +++ b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/label/LabelDefinitionServiceTest.java @@ -26,6 +26,18 @@ class LabelDefinitionServiceTest { 100 ); + @Test + void constructorShouldRejectNonPositiveDefinitionLimit() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> new LabelDefinitionService( + labelDefinitionRepository, + labelTranslationRepository, + labelPermissionChecker, + 0 + )); + + assertEquals("skillhub.label.max-definitions must be greater than 0", ex.getMessage()); + } + @Test void createShouldRejectDuplicateLocalesIgnoringCase() { when(labelPermissionChecker.canManageDefinitions(Set.of("SUPER_ADMIN"))).thenReturn(true); diff --git a/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/label/SkillLabelServiceTest.java b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/label/SkillLabelServiceTest.java new file mode 100644 index 00000000..ea3db73d --- /dev/null +++ b/server/skillhub-domain/src/test/java/com/iflytek/skillhub/domain/label/SkillLabelServiceTest.java @@ -0,0 +1,29 @@ +package com.iflytek.skillhub.domain.label; + +import com.iflytek.skillhub.domain.skill.SkillRepository; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; + +class SkillLabelServiceTest { + + private final SkillRepository skillRepository = mock(SkillRepository.class); + private final LabelDefinitionRepository labelDefinitionRepository = mock(LabelDefinitionRepository.class); + private final SkillLabelRepository skillLabelRepository = mock(SkillLabelRepository.class); + private final LabelPermissionChecker labelPermissionChecker = mock(LabelPermissionChecker.class); + + @Test + void constructorShouldRejectNonPositivePerSkillLimit() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> new SkillLabelService( + skillRepository, + labelDefinitionRepository, + skillLabelRepository, + labelPermissionChecker, + 0 + )); + + assertEquals("skillhub.label.max-per-skill must be greater than 0", ex.getMessage()); + } +}