diff --git a/backend/src/main/java/com/xly/test4/module/usr/service/impl/UserServiceImpl.java b/backend/src/main/java/com/xly/test4/module/usr/service/impl/UserServiceImpl.java index bfb4de3..5d0b83f 100644 --- a/backend/src/main/java/com/xly/test4/module/usr/service/impl/UserServiceImpl.java +++ b/backend/src/main/java/com/xly/test4/module/usr/service/impl/UserServiceImpl.java @@ -7,7 +7,11 @@ import com.xly.test4.common.security.CurrentUser; import com.xly.test4.common.security.CurrentUserContext; import com.xly.test4.module.usr.converter.UserConverter; import com.xly.test4.module.usr.dto.UserCreateDTO; +import com.xly.test4.module.usr.entity.Employee; +import com.xly.test4.module.usr.entity.Permission; import com.xly.test4.module.usr.entity.User; +import com.xly.test4.module.usr.mapper.EmployeeMapper; +import com.xly.test4.module.usr.mapper.PermissionMapper; import com.xly.test4.module.usr.mapper.UserMapper; import com.xly.test4.module.usr.service.UserService; import com.xly.test4.module.usr.vo.UserCreateVO; @@ -16,19 +20,27 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service public class UserServiceImpl implements UserService { private final UserMapper userMapper; + private final EmployeeMapper employeeMapper; + private final PermissionMapper permissionMapper; private final UserConverter userConverter; private final PasswordEncoder passwordEncoder; private final String defaultPassword; public UserServiceImpl(UserMapper userMapper, + EmployeeMapper employeeMapper, + PermissionMapper permissionMapper, UserConverter userConverter, PasswordEncoder passwordEncoder, @Value("${app.security.default-password}") String defaultPassword) { this.userMapper = userMapper; + this.employeeMapper = employeeMapper; + this.permissionMapper = permissionMapper; this.userConverter = userConverter; this.passwordEncoder = passwordEncoder; this.defaultPassword = defaultPassword; @@ -48,6 +60,24 @@ public class UserServiceImpl implements UserService { throw new BusinessException(ResultCode.USER_CODE_DUPLICATE, "用户号已存在"); } + if (dto.getEmployeeId() != null) { + Employee employee = employeeMapper.selectOne(new LambdaQueryWrapper() + .eq(Employee::getIIncrement, dto.getEmployeeId()) + .eq(Employee::getIIsDisabled, 0)); + if (employee == null) { + throw new BusinessException(ResultCode.EMPLOYEE_INVALID, "员工不存在或已作废"); + } + } + + if (dto.getPermissionIds() != null && !dto.getPermissionIds().isEmpty()) { + List found = permissionMapper.selectList(new LambdaQueryWrapper() + .in(Permission::getIIncrement, dto.getPermissionIds()) + .eq(Permission::getIIsDisabled, 0)); + if (found.size() != dto.getPermissionIds().size()) { + throw new BusinessException(ResultCode.PERMISSION_INVALID, "权限分类含非法项"); + } + } + User user = userConverter.toEntity(dto); user.setSBrandsId(current.getBrandsId()); user.setSSubsidiaryId(current.getSubsidiaryId()); diff --git a/backend/src/test/java/com/xly/test4/module/usr/service/impl/UserServiceImplTest.java b/backend/src/test/java/com/xly/test4/module/usr/service/impl/UserServiceImplTest.java index f3727cf..a1abef7 100644 --- a/backend/src/test/java/com/xly/test4/module/usr/service/impl/UserServiceImplTest.java +++ b/backend/src/test/java/com/xly/test4/module/usr/service/impl/UserServiceImplTest.java @@ -6,7 +6,11 @@ import com.xly.test4.common.security.CurrentUser; import com.xly.test4.common.security.CurrentUserContext; import com.xly.test4.module.usr.converter.UserConverter; import com.xly.test4.module.usr.dto.UserCreateDTO; +import com.xly.test4.module.usr.entity.Employee; +import com.xly.test4.module.usr.entity.Permission; import com.xly.test4.module.usr.entity.User; +import com.xly.test4.module.usr.mapper.EmployeeMapper; +import com.xly.test4.module.usr.mapper.PermissionMapper; import com.xly.test4.module.usr.mapper.UserMapper; import com.xly.test4.module.usr.vo.UserCreateVO; import org.junit.jupiter.api.AfterEach; @@ -31,6 +35,8 @@ import static org.mockito.Mockito.when; class UserServiceImplTest { private UserMapper userMapper; + private EmployeeMapper employeeMapper; + private PermissionMapper permissionMapper; private UserConverter userConverter; private PasswordEncoder passwordEncoder; private UserServiceImpl service; @@ -47,9 +53,12 @@ class UserServiceImplTest { @BeforeEach void setUp() { userMapper = mock(UserMapper.class); + employeeMapper = mock(EmployeeMapper.class); + permissionMapper = mock(PermissionMapper.class); userConverter = mock(UserConverter.class); passwordEncoder = new BCryptPasswordEncoder(); - service = new UserServiceImpl(userMapper, userConverter, passwordEncoder, "666666"); + service = new UserServiceImpl(userMapper, employeeMapper, permissionMapper, + userConverter, passwordEncoder, "666666"); ctxMock = mockStatic(CurrentUserContext.class); ctxMock.when(CurrentUserContext::current).thenReturn(ADMIN_CONTEXT); } @@ -150,4 +159,72 @@ class UserServiceImplTest { verify(userMapper, never()).insert(any(User.class)); } + + @Test + @SuppressWarnings("unchecked") + void createUser_invalidEmployeeId_throws40004() { + stubConverterReturnsEmptyUser(); + when(employeeMapper.selectOne(any(Wrapper.class))).thenReturn(null); + + UserCreateDTO dto = baseDTO(); + dto.setEmployeeId(99999); + + assertThatThrownBy(() -> service.createUser(dto)) + .isInstanceOf(BusinessException.class) + .matches(e -> ((BusinessException) e).getCode() == 40004); + + verify(userMapper, never()).insert(any(User.class)); + } + + @Test + @SuppressWarnings("unchecked") + void createUser_disabledEmployee_throws40004() { + stubConverterReturnsEmptyUser(); + // 模拟"员工存在但 iIsDisabled=1":Wrapper 含 eq(iIsDisabled,0) 时不返回任何记录 + when(employeeMapper.selectOne(any(Wrapper.class))).thenReturn(null); + + UserCreateDTO dto = baseDTO(); + dto.setEmployeeId(7); + + assertThatThrownBy(() -> service.createUser(dto)) + .isInstanceOf(BusinessException.class) + .matches(e -> ((BusinessException) e).getCode() == 40004); + } + + @Test + @SuppressWarnings("unchecked") + void createUser_invalidPermissionIds_throws40005() { + stubConverterReturnsEmptyUser(); + // 传 3 个 id,只查到 2 条 + when(permissionMapper.selectList(any(Wrapper.class))) + .thenReturn(List.of(new Permission(), new Permission())); + + UserCreateDTO dto = baseDTO(); + dto.setPermissionIds(List.of(1, 2, 3)); + + assertThatThrownBy(() -> service.createUser(dto)) + .isInstanceOf(BusinessException.class) + .matches(e -> ((BusinessException) e).getCode() == 40005); + + verify(userMapper, never()).insert(any(User.class)); + } + + @Test + @SuppressWarnings("unchecked") + void createUser_permissionIdsNullOrEmpty_skipsCheck() { + stubConverterReturnsEmptyUser(); + UserCreateDTO dto = baseDTO(); + dto.setPermissionIds(null); + + service.createUser(dto); + verify(permissionMapper, never()).selectList(any(Wrapper.class)); + + UserCreateDTO dto2 = baseDTO(); + dto2.setUserCode("U-NEW-002"); + dto2.setUserName("newuser2"); + dto2.setPermissionIds(List.of()); + + service.createUser(dto2); + verify(permissionMapper, never()).selectList(any(Wrapper.class)); + } }