mirror of
https://gitee.com/yudaocode/yudao-boot-mini.git
synced 2026-10-06 14:13:14 +08:00
Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/hrm
This commit is contained in:
+5
@@ -41,6 +41,11 @@ public class OAuth2TokenApiImpl implements OAuth2TokenCommonApi {
|
||||
return BeanUtils.toBean(accessTokenDO, OAuth2AccessTokenRespDTO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAccessToken(Long userId, Integer userType) {
|
||||
oauth2TokenService.removeAccessToken(userId, userType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessTokenRespDTO refreshAccessToken(String refreshToken, String clientId) {
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, clientId);
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ public class DictTypeController {
|
||||
@Operation(summary = "删除字典类型")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:dict:delete')")
|
||||
public CommonResult<Boolean> deleteDictType(Long id) {
|
||||
public CommonResult<Boolean> deleteDictType(@RequestParam("id") Long id) {
|
||||
dictTypeService.deleteDictType(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
+2
-1
@@ -19,6 +19,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -39,7 +40,7 @@ public class LoginLogController {
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得登录日志")
|
||||
@PreAuthorize("@ss.hasPermission('system:login-log:query')")
|
||||
public CommonResult<LoginLogRespVO> getLoginLog(Long id) {
|
||||
public CommonResult<LoginLogRespVO> getLoginLog(@RequestParam("id") Long id) {
|
||||
LoginLogDO loginLog = loginLogService.getLoginLog(id);
|
||||
return success(BeanUtils.toBean(loginLog, LoginLogRespVO.class));
|
||||
}
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ public class MenuController {
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获取菜单信息")
|
||||
@PreAuthorize("@ss.hasPermission('system:menu:query')")
|
||||
public CommonResult<MenuRespVO> getMenu(Long id) {
|
||||
public CommonResult<MenuRespVO> getMenu(@RequestParam("id") Long id) {
|
||||
MenuDO menu = menuService.getMenu(id);
|
||||
return success(BeanUtils.toBean(menu, MenuRespVO.class));
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ public class PermissionController {
|
||||
@Parameter(name = "roleId", description = "角色编号", required = true)
|
||||
@GetMapping("/list-role-menus")
|
||||
@PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
|
||||
public CommonResult<Set<Long>> getRoleMenuList(Long roleId) {
|
||||
public CommonResult<Set<Long>> getRoleMenuList(@RequestParam("roleId") Long roleId) {
|
||||
return success(permissionService.getRoleMenuListByRoleId(roleId));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ public class SocialUserController {
|
||||
List<SocialUserDO> list = socialUserService.getSocialUserList(getLoginUserId(), UserTypeEnum.ADMIN.getValue());
|
||||
return success(convertList(list, socialUser -> new SocialUserRespVO() // 返回精简信息
|
||||
.setId(socialUser.getId()).setType(socialUser.getType()).setOpenid(socialUser.getOpenid())
|
||||
.setNickname(socialUser.getNickname()).setAvatar(socialUser.getNickname())));
|
||||
.setNickname(socialUser.getNickname()).setAvatar(socialUser.getAvatar())));
|
||||
}
|
||||
|
||||
// ==================== 社交用户 CRUD ====================
|
||||
|
||||
+2
-7
@@ -134,13 +134,8 @@ public class UserController {
|
||||
@Operation(summary = "获取用户精简信息列表", description = "只包含被开启的用户,主要用于前端的下拉选项")
|
||||
public CommonResult<List<UserSimpleRespVO>> getSimpleUserList(
|
||||
@RequestParam(value = "deptId", required = false) Long deptId) {
|
||||
List<AdminUserDO> list;
|
||||
if (deptId != null) {
|
||||
List<Long> deptIds = Collections.singletonList(deptId);
|
||||
list = userService.getDeptUsers(deptIds);
|
||||
} else {
|
||||
list = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
}
|
||||
List<AdminUserDO> list = userService.getUserListByStatus(
|
||||
CommonStatusEnum.ENABLE.getStatus(), deptId);
|
||||
|
||||
// 拼接数据
|
||||
Map<Long, DeptDO> deptMap = deptService.getDeptMap(
|
||||
|
||||
+7
-1
@@ -41,7 +41,13 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
|
||||
}
|
||||
|
||||
default List<AdminUserDO> selectListByStatus(Integer status) {
|
||||
return selectList(AdminUserDO::getStatus, status);
|
||||
return selectListByStatusAndDeptId(status, null);
|
||||
}
|
||||
|
||||
default List<AdminUserDO> selectListByStatusAndDeptId(Integer status, Long deptId) {
|
||||
return selectList(new LambdaQueryWrapperX<AdminUserDO>()
|
||||
.eq(AdminUserDO::getStatus, status)
|
||||
.eqIfPresent(AdminUserDO::getDeptId, deptId));
|
||||
}
|
||||
|
||||
default List<AdminUserDO> selectListByDeptIds(Collection<Long> deptIds) {
|
||||
|
||||
+19
-12
@@ -91,10 +91,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
// 校验是否禁用
|
||||
if (CommonStatusEnum.isDisable(user.getStatus())) {
|
||||
createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED);
|
||||
throw exception(AUTH_LOGIN_USER_DISABLED);
|
||||
}
|
||||
validateUserStatus(user, username, logTypeEnum);
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -113,7 +110,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
|
||||
}
|
||||
// 创建 Token 令牌,记录登录日志
|
||||
return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
|
||||
return createTokenAfterLoginSuccess(user, reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -146,7 +143,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
}
|
||||
|
||||
// 创建 Token 令牌,记录登录日志
|
||||
return createTokenAfterLoginSuccess(user.getId(), reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE);
|
||||
return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE);
|
||||
}
|
||||
|
||||
private void createLoginLog(Long userId, String username,
|
||||
@@ -184,7 +181,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
}
|
||||
|
||||
// 创建 Token 令牌,记录登录日志
|
||||
return createTokenAfterLoginSuccess(user.getId(), user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
|
||||
return createTokenAfterLoginSuccess(user, user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -209,16 +206,26 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
return captchaService.verification(captchaVO);
|
||||
}
|
||||
|
||||
private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) {
|
||||
private AuthLoginRespVO createTokenAfterLoginSuccess(AdminUserDO user, String username, LoginLogTypeEnum logType) {
|
||||
// 统一校验用户状态,避免短信、社交等登录方式遗漏
|
||||
validateUserStatus(user, username, logType);
|
||||
|
||||
// 插入登陆日志
|
||||
createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
|
||||
createLoginLog(user.getId(), username, logType, LoginResultEnum.SUCCESS);
|
||||
// 创建访问令牌
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, getUserType().getValue(),
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(user.getId(), getUserType().getValue(),
|
||||
OAuth2ClientConstants.CLIENT_ID_DEFAULT, null);
|
||||
// 构建返回结果
|
||||
return BeanUtils.toBean(accessTokenDO, AuthLoginRespVO.class);
|
||||
}
|
||||
|
||||
private void validateUserStatus(AdminUserDO user, String username, LoginLogTypeEnum logType) {
|
||||
if (CommonStatusEnum.isDisable(user.getStatus())) {
|
||||
createLoginLog(user.getId(), username, logType, LoginResultEnum.USER_DISABLED);
|
||||
throw exception(AUTH_LOGIN_USER_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthLoginRespVO refreshToken(String refreshToken) {
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);
|
||||
@@ -271,10 +278,10 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
||||
validateCaptcha(registerReqVO);
|
||||
|
||||
// 2. 校验用户名是否已存在
|
||||
Long userId = userService.registerUser(registerReqVO);
|
||||
AdminUserDO user = userService.registerUser(registerReqVO);
|
||||
|
||||
// 3. 创建 Token 令牌,记录登录日志
|
||||
return createTokenAfterLoginSuccess(userId, registerReqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
|
||||
return createTokenAfterLoginSuccess(user, registerReqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
+9
-6
@@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqV
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -37,9 +38,9 @@ public interface AdminUserService {
|
||||
* 注册用户
|
||||
*
|
||||
* @param registerReqVO 用户信息
|
||||
* @return 用户编号
|
||||
* @return 用户信息
|
||||
*/
|
||||
Long registerUser(@Valid AuthRegisterReqVO registerReqVO);
|
||||
AdminUserDO registerUser(@Valid AuthRegisterReqVO registerReqVO);
|
||||
|
||||
/**
|
||||
* 修改用户
|
||||
@@ -214,11 +215,13 @@ public interface AdminUserService {
|
||||
List<AdminUserDO> getUserListByStatus(Integer status);
|
||||
|
||||
/**
|
||||
* 获得指定部门的用户
|
||||
* @param deptIds
|
||||
* @return
|
||||
* 获得指定状态和部门的用户们
|
||||
*
|
||||
* @param status 状态
|
||||
* @param deptId 部门编号,{@code null} 表示不筛选部门
|
||||
* @return 用户们
|
||||
*/
|
||||
List<AdminUserDO> getDeptUsers(Collection<Long> deptIds);
|
||||
List<AdminUserDO> getUserListByStatus(Integer status, @Nullable Long deptId);
|
||||
|
||||
/**
|
||||
* 判断密码是否匹配
|
||||
|
||||
+5
-5
@@ -124,7 +124,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long registerUser(AuthRegisterReqVO registerReqVO) {
|
||||
public AdminUserDO registerUser(AuthRegisterReqVO registerReqVO) {
|
||||
// 1.1 校验是否开启注册
|
||||
if (ObjUtil.notEqual(configApi.getConfigValueByKey(USER_REGISTER_ENABLED_KEY), "true")) {
|
||||
throw exception(USER_REGISTER_DISABLED);
|
||||
@@ -144,7 +144,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
|
||||
user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码
|
||||
userMapper.insert(user);
|
||||
return user.getId();
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -560,12 +560,12 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
|
||||
@Override
|
||||
public List<AdminUserDO> getUserListByStatus(Integer status) {
|
||||
return userMapper.selectListByStatus(status);
|
||||
return getUserListByStatus(status, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AdminUserDO> getDeptUsers(Collection<Long> deptIds) {
|
||||
return userMapper.selectListByDeptIds(deptIds);
|
||||
public List<AdminUserDO> getUserListByStatus(Integer status, Long deptId) {
|
||||
return userMapper.selectListByStatusAndDeptId(status, deptId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+60
-2
@@ -215,7 +215,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
|
||||
return true;
|
||||
})));
|
||||
// mock 方法(用户信息)
|
||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L));
|
||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L)
|
||||
.setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
||||
when(userService.getUserByMobile(eq(mobile))).thenReturn(user);
|
||||
// mock 缓存登录用户到 Redis
|
||||
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
|
||||
@@ -243,7 +244,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
|
||||
when(socialUserService.getSocialUserByCode(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()),
|
||||
eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(new SocialUserRespDTO(randomString(), randomString(), randomString(), userId));
|
||||
// mock(用户)
|
||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId));
|
||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId)
|
||||
.setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
||||
when(userService.getUser(eq(userId))).thenReturn(user);
|
||||
// mock 缓存登录用户到 Redis
|
||||
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
|
||||
@@ -262,6 +264,62 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmsLogin_userDisabled() {
|
||||
// 准备参数
|
||||
AuthSmsLoginReqVO reqVO = new AuthSmsLoginReqVO(randomString(), randomString());
|
||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
||||
when(userService.getUserByMobile(eq(reqVO.getMobile()))).thenReturn(user);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> authService.smsLogin(reqVO), AUTH_LOGIN_USER_DISABLED);
|
||||
verify(loginLogService).createLoginLog(argThat(o ->
|
||||
o.getLogType().equals(LoginLogTypeEnum.LOGIN_MOBILE.getType())
|
||||
&& o.getResult().equals(LoginResultEnum.USER_DISABLED.getResult())
|
||||
&& o.getUserId().equals(user.getId())));
|
||||
verify(oauth2TokenService, never()).createAccessToken(anyLong(), anyInt(), anyString(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSocialLogin_userDisabled() {
|
||||
// 准备参数
|
||||
AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class);
|
||||
Long userId = 1L;
|
||||
when(socialUserService.getSocialUserByCode(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()),
|
||||
eq(reqVO.getCode()), eq(reqVO.getState())))
|
||||
.thenReturn(new SocialUserRespDTO(randomString(), randomString(), randomString(), userId));
|
||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId)
|
||||
.setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
||||
when(userService.getUser(eq(userId))).thenReturn(user);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> authService.socialLogin(reqVO), AUTH_LOGIN_USER_DISABLED);
|
||||
verify(loginLogService).createLoginLog(argThat(o ->
|
||||
o.getLogType().equals(LoginLogTypeEnum.LOGIN_SOCIAL.getType())
|
||||
&& o.getResult().equals(LoginResultEnum.USER_DISABLED.getResult())
|
||||
&& o.getUserId().equals(user.getId())));
|
||||
verify(oauth2TokenService, never()).createAccessToken(anyLong(), anyInt(), anyString(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegister_success() {
|
||||
// 准备参数
|
||||
AuthRegisterReqVO reqVO = randomPojo(AuthRegisterReqVO.class);
|
||||
authService.setCaptchaEnable(false);
|
||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L)
|
||||
.setUsername(reqVO.getUsername()).setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
||||
when(userService.registerUser(reqVO)).thenReturn(user);
|
||||
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(user.getId())
|
||||
.setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||
when(oauth2TokenService.createAccessToken(eq(user.getId()), eq(UserTypeEnum.ADMIN.getValue()),
|
||||
eq("default"), isNull())).thenReturn(accessTokenDO);
|
||||
|
||||
// 调用,并断言
|
||||
AuthLoginRespVO loginRespVO = authService.register(reqVO);
|
||||
assertPojoEquals(accessTokenDO, loginRespVO);
|
||||
verify(userService, never()).getUser(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCaptcha_successWithEnable() {
|
||||
// 准备参数
|
||||
|
||||
+20
-1
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.user;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||
@@ -278,13 +279,14 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||
userMapper.insert(dbUser);
|
||||
// 准备参数
|
||||
Long userId = dbUser.getId();
|
||||
Integer status = randomCommonStatus();
|
||||
Integer status = CommonStatusEnum.DISABLE.getStatus();
|
||||
|
||||
// 调用
|
||||
userService.updateUserStatus(userId, status);
|
||||
// 断言
|
||||
AdminUserDO user = userMapper.selectById(userId);
|
||||
assertEquals(status, user.getStatus());
|
||||
verify(oauth2TokenService).removeAccessToken(userId, UserTypeEnum.ADMIN.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -721,6 +723,23 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||
assertEquals(user, result.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserListByStatusAndDeptId() {
|
||||
// mock 数据
|
||||
AdminUserDO user = randomAdminUserDO(o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()).setDeptId(1L));
|
||||
userMapper.insert(user);
|
||||
// 测试 status 不匹配
|
||||
userMapper.insert(cloneIgnoreId(user, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
||||
// 测试 deptId 不匹配
|
||||
userMapper.insert(cloneIgnoreId(user, o -> o.setDeptId(2L)));
|
||||
|
||||
// 调用
|
||||
List<AdminUserDO> result = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus(), 1L);
|
||||
// 断言
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(user, result.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateUserList_success() {
|
||||
// mock 数据
|
||||
|
||||
Reference in New Issue
Block a user