Commit 736eafbe2801d3b24a23c4ba8a1ee2c5c51ee40b

Authored by zichun
1 parent 14050e57

feat(usr): mapper 唯一查询排除自身 + 权限分类查/删辅助 REQ-USR-003

backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserMapper.java
@@ -48,4 +48,9 @@ public interface SysUserMapper extends BaseMapper<SysUser> { @@ -48,4 +48,9 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
48 48
49 @Select("SELECT EXISTS(SELECT 1 FROM sys_user WHERE sUserCode = #{userCode})") 49 @Select("SELECT EXISTS(SELECT 1 FROM sys_user WHERE sUserCode = #{userCode})")
50 boolean existsByUserCode(@Param("userCode") String userCode); 50 boolean existsByUserCode(@Param("userCode") String userCode);
  51 +
  52 + @Select("SELECT EXISTS(SELECT 1 FROM sys_user " +
  53 + "WHERE sUserCode = #{userCode} AND iIncrement <> #{excludedUserId})")
  54 + boolean existsByUserCodeExcludingId(@Param("userCode") String userCode,
  55 + @Param("excludedUserId") Integer excludedUserId);
51 } 56 }
backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapper.java
@@ -2,8 +2,25 @@ package com.xly.erp.module.usr.mapper; @@ -2,8 +2,25 @@ package com.xly.erp.module.usr.mapper;
2 2
3 import com.baomidou.mybatisplus.core.mapper.BaseMapper; 3 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 import com.xly.erp.module.usr.entity.SysUserPermissionCategory; 4 import com.xly.erp.module.usr.entity.SysUserPermissionCategory;
  5 +import org.apache.ibatis.annotations.Delete;
5 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
  7 +import org.apache.ibatis.annotations.Param;
  8 +import org.apache.ibatis.annotations.Select;
  9 +
  10 +import java.util.List;
6 11
7 @Mapper 12 @Mapper
8 public interface SysUserPermissionCategoryMapper extends BaseMapper<SysUserPermissionCategory> { 13 public interface SysUserPermissionCategoryMapper extends BaseMapper<SysUserPermissionCategory> {
  14 +
  15 + @Select("SELECT iPermissionCategoryId FROM sys_user_permission_category WHERE iUserId = #{userId}")
  16 + List<Integer> selectPermissionCategoryIdsByUserId(@Param("userId") Integer userId);
  17 +
  18 + @Delete({
  19 + "<script>",
  20 + "DELETE FROM sys_user_permission_category WHERE iUserId = #{userId} AND iPermissionCategoryId IN ",
  21 + "<foreach item='id' collection='ids' open='(' separator=',' close=')'>#{id}</foreach>",
  22 + "</script>"
  23 + })
  24 + int deleteByUserAndCategoryIds(@Param("userId") Integer userId,
  25 + @Param("ids") List<Integer> categoryIds);
9 } 26 }
backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserMapperTest.java
@@ -63,4 +63,23 @@ class SysUserMapperTest { @@ -63,4 +63,23 @@ class SysUserMapperTest {
63 void existsByUserCode_falseForUnknown() { 63 void existsByUserCode_falseForUnknown() {
64 assertFalse(userMapper.existsByUserCode("UXXX")); 64 assertFalse(userMapper.existsByUserCode("UXXX"));
65 } 65 }
  66 +
  67 + @Test
  68 + void existsByUserCodeExcludingId_otherUserHasCode_returnsTrue() {
  69 + // alice has U001 / admin has U000;查 U001 排除 admin → 找到 alice → true
  70 + assertTrue(userMapper.existsByUserCodeExcludingId("U001",
  71 + seeder.reset().adminId()));
  72 + }
  73 +
  74 + @Test
  75 + void existsByUserCodeExcludingId_selfHasCode_returnsFalse() {
  76 + LoginTestSeeder.Fixture f = seeder.reset();
  77 + // 查 alice 的 userCode 排除 alice 本身 → false
  78 + assertFalse(userMapper.existsByUserCodeExcludingId("U001", f.aliceId()));
  79 + }
  80 +
  81 + @Test
  82 + void existsByUserCodeExcludingId_unknownCode_returnsFalse() {
  83 + assertFalse(userMapper.existsByUserCodeExcludingId("UXXX", 1));
  84 + }
66 } 85 }
backend/src/test/java/com/xly/erp/module/usr/mapper/SysUserPermissionCategoryMapperTest.java 0 → 100644
  1 +package com.xly.erp.module.usr.mapper;
  2 +
  3 +import com.xly.erp.module.usr.entity.SysUserPermissionCategory;
  4 +import com.xly.erp.module.usr.support.LoginTestSeeder;
  5 +import org.junit.jupiter.api.BeforeEach;
  6 +import org.junit.jupiter.api.Test;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.boot.test.context.SpringBootTest;
  9 +import org.springframework.test.context.ActiveProfiles;
  10 +
  11 +import java.util.List;
  12 +
  13 +import static org.junit.jupiter.api.Assertions.*;
  14 +
  15 +@SpringBootTest
  16 +@ActiveProfiles("test")
  17 +class SysUserPermissionCategoryMapperTest {
  18 +
  19 + @Autowired private SysUserPermissionCategoryMapper mapper;
  20 + @Autowired private LoginTestSeeder seeder;
  21 +
  22 + private LoginTestSeeder.Fixture fx;
  23 +
  24 + @BeforeEach
  25 + void setUp() {
  26 + fx = seeder.reset();
  27 + // 给 alice 授权两个活跃分类
  28 + for (Integer pcId : fx.activePermissionCategoryIds()) {
  29 + SysUserPermissionCategory link = new SysUserPermissionCategory();
  30 + link.setIUserId(fx.aliceId());
  31 + link.setIPermissionCategoryId(pcId);
  32 + link.setSGrantedBy("system");
  33 + mapper.insert(link);
  34 + }
  35 + }
  36 +
  37 + @Test
  38 + void selectPermissionCategoryIdsByUserId_returnsAllCurrent() {
  39 + List<Integer> ids = mapper.selectPermissionCategoryIdsByUserId(fx.aliceId());
  40 + assertEquals(fx.activePermissionCategoryIds().size(), ids.size());
  41 + assertTrue(ids.containsAll(fx.activePermissionCategoryIds()));
  42 + }
  43 +
  44 + @Test
  45 + void selectPermissionCategoryIdsByUserId_emptyForNoGrants() {
  46 + List<Integer> ids = mapper.selectPermissionCategoryIdsByUserId(fx.adminId());
  47 + assertTrue(ids.isEmpty());
  48 + }
  49 +
  50 + @Test
  51 + void deleteByUserAndCategoryIds_onlyDeletesGivenSubset() {
  52 + Integer pur = fx.activePermissionCategoryIds().get(0);
  53 + int rows = mapper.deleteByUserAndCategoryIds(fx.aliceId(), List.of(pur));
  54 + assertEquals(1, rows);
  55 +
  56 + List<Integer> remaining = mapper.selectPermissionCategoryIdsByUserId(fx.aliceId());
  57 + assertEquals(fx.activePermissionCategoryIds().size() - 1, remaining.size());
  58 + assertFalse(remaining.contains(pur));
  59 + }
  60 +
  61 + @Test
  62 + void deleteByUserAndCategoryIds_nonMatchingIds_returns0() {
  63 + int rows = mapper.deleteByUserAndCategoryIds(fx.aliceId(), List.of(99999));
  64 + assertEquals(0, rows);
  65 + }
  66 +
  67 + @Test
  68 + void deleteByUserAndCategoryIds_doesNotAffectOtherUser() {
  69 + // 给 admin 也授权一条
  70 + SysUserPermissionCategory link = new SysUserPermissionCategory();
  71 + link.setIUserId(fx.adminId());
  72 + link.setIPermissionCategoryId(fx.activePermissionCategoryIds().get(0));
  73 + link.setSGrantedBy("system");
  74 + mapper.insert(link);
  75 +
  76 + // 删 alice 的某个分类不应影响 admin
  77 + mapper.deleteByUserAndCategoryIds(fx.aliceId(),
  78 + List.of(fx.activePermissionCategoryIds().get(0)));
  79 +
  80 + assertEquals(1, mapper.selectPermissionCategoryIdsByUserId(fx.adminId()).size());
  81 + }
  82 +}