From 736eafbe2801d3b24a23c4ba8a1ee2c5c51ee40b Mon Sep 17 00:00:00 2001 From: zichun Date: Fri, 15 May 2026 09:42:13 +0800 Subject: [PATCH] feat(usr): mapper 唯一查询排除自身 + 权限分类查/删辅助 REQ-USR-003 --- backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserMapper.java | 5 +++++ backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapper.java | 17 +++++++++++++++++ backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserMapperTest.java | 19 +++++++++++++++++++ backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapperTest.java | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 0 deletions(-) create mode 100644 backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapperTest.java diff --git a/backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserMapper.java b/backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserMapper.java index 35d2b11..98b9096 100644 --- a/backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserMapper.java +++ b/backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserMapper.java @@ -48,4 +48,9 @@ public interface SysUserMapper extends BaseMapper { @Select("SELECT EXISTS(SELECT 1 FROM sys_user WHERE sUserCode = #{userCode})") boolean existsByUserCode(@Param("userCode") String userCode); + + @Select("SELECT EXISTS(SELECT 1 FROM sys_user " + + "WHERE sUserCode = #{userCode} AND iIncrement <> #{excludedUserId})") + boolean existsByUserCodeExcludingId(@Param("userCode") String userCode, + @Param("excludedUserId") Integer excludedUserId); } diff --git a/backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapper.java b/backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapper.java index 733c747..e8fbaea 100644 --- a/backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapper.java +++ b/backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapper.java @@ -2,8 +2,25 @@ package com.xly.erp.module.usr.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xly.erp.module.usr.entity.SysUserPermissionCategory; +import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; @Mapper public interface SysUserPermissionCategoryMapper extends BaseMapper { + + @Select("SELECT iPermissionCategoryId FROM sys_user_permission_category WHERE iUserId = #{userId}") + List selectPermissionCategoryIdsByUserId(@Param("userId") Integer userId); + + @Delete({ + "" + }) + int deleteByUserAndCategoryIds(@Param("userId") Integer userId, + @Param("ids") List categoryIds); } diff --git a/backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserMapperTest.java b/backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserMapperTest.java index 2b11924..d4efb2f 100644 --- a/backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserMapperTest.java +++ b/backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserMapperTest.java @@ -63,4 +63,23 @@ class SysUserMapperTest { void existsByUserCode_falseForUnknown() { assertFalse(userMapper.existsByUserCode("UXXX")); } + + @Test + void existsByUserCodeExcludingId_otherUserHasCode_returnsTrue() { + // alice has U001 / admin has U000;查 U001 排除 admin → 找到 alice → true + assertTrue(userMapper.existsByUserCodeExcludingId("U001", + seeder.reset().adminId())); + } + + @Test + void existsByUserCodeExcludingId_selfHasCode_returnsFalse() { + LoginTestSeeder.Fixture f = seeder.reset(); + // 查 alice 的 userCode 排除 alice 本身 → false + assertFalse(userMapper.existsByUserCodeExcludingId("U001", f.aliceId())); + } + + @Test + void existsByUserCodeExcludingId_unknownCode_returnsFalse() { + assertFalse(userMapper.existsByUserCodeExcludingId("UXXX", 1)); + } } diff --git a/backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapperTest.java b/backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapperTest.java new file mode 100644 index 0000000..d33cdf2 --- /dev/null +++ b/backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapperTest.java @@ -0,0 +1,82 @@ +package com.xly.erp.module.usr.mapper; + +import com.xly.erp.module.usr.entity.SysUserPermissionCategory; +import com.xly.erp.module.usr.support.LoginTestSeeder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@ActiveProfiles("test") +class SysUserPermissionCategoryMapperTest { + + @Autowired private SysUserPermissionCategoryMapper mapper; + @Autowired private LoginTestSeeder seeder; + + private LoginTestSeeder.Fixture fx; + + @BeforeEach + void setUp() { + fx = seeder.reset(); + // 给 alice 授权两个活跃分类 + for (Integer pcId : fx.activePermissionCategoryIds()) { + SysUserPermissionCategory link = new SysUserPermissionCategory(); + link.setIUserId(fx.aliceId()); + link.setIPermissionCategoryId(pcId); + link.setSGrantedBy("system"); + mapper.insert(link); + } + } + + @Test + void selectPermissionCategoryIdsByUserId_returnsAllCurrent() { + List ids = mapper.selectPermissionCategoryIdsByUserId(fx.aliceId()); + assertEquals(fx.activePermissionCategoryIds().size(), ids.size()); + assertTrue(ids.containsAll(fx.activePermissionCategoryIds())); + } + + @Test + void selectPermissionCategoryIdsByUserId_emptyForNoGrants() { + List ids = mapper.selectPermissionCategoryIdsByUserId(fx.adminId()); + assertTrue(ids.isEmpty()); + } + + @Test + void deleteByUserAndCategoryIds_onlyDeletesGivenSubset() { + Integer pur = fx.activePermissionCategoryIds().get(0); + int rows = mapper.deleteByUserAndCategoryIds(fx.aliceId(), List.of(pur)); + assertEquals(1, rows); + + List remaining = mapper.selectPermissionCategoryIdsByUserId(fx.aliceId()); + assertEquals(fx.activePermissionCategoryIds().size() - 1, remaining.size()); + assertFalse(remaining.contains(pur)); + } + + @Test + void deleteByUserAndCategoryIds_nonMatchingIds_returns0() { + int rows = mapper.deleteByUserAndCategoryIds(fx.aliceId(), List.of(99999)); + assertEquals(0, rows); + } + + @Test + void deleteByUserAndCategoryIds_doesNotAffectOtherUser() { + // 给 admin 也授权一条 + SysUserPermissionCategory link = new SysUserPermissionCategory(); + link.setIUserId(fx.adminId()); + link.setIPermissionCategoryId(fx.activePermissionCategoryIds().get(0)); + link.setSGrantedBy("system"); + mapper.insert(link); + + // 删 alice 的某个分类不应影响 admin + mapper.deleteByUserAndCategoryIds(fx.aliceId(), + List.of(fx.activePermissionCategoryIds().get(0))); + + assertEquals(1, mapper.selectPermissionCategoryIdsByUserId(fx.adminId()).size()); + } +} -- libgit2 0.22.2