add store

This commit is contained in:
Timi
2026-08-07 11:37:54 +08:00
parent 7ffdd715ee
commit 7e40e0202e
60 changed files with 1657 additions and 446 deletions
@@ -10,7 +10,8 @@ import com.imyeyu.api.modules.user.entity.Permission;
import com.imyeyu.api.modules.user.entity.Role;
import com.imyeyu.api.modules.user.service.PermissionService;
import com.imyeyu.api.modules.user.service.RoleService;
import com.imyeyu.api.modules.user.vo.role.UserRoleAuthorizeReq;
import com.imyeyu.api.modules.user.service.UserRoleService;
import com.imyeyu.api.modules.user.vo.role.UserRoleAuthorizeRequest;
import com.imyeyu.spring.annotation.AOPLog;
import com.imyeyu.spring.bean.Page;
import com.imyeyu.spring.bean.PageResult;
@@ -37,6 +38,7 @@ import java.util.List;
public class RoleController {
private final RoleService service;
private final UserRoleService userRoleService;
private final PermissionService permissionService;
@RequireCoreRole(value = {CoreRoleCode.ADMIN, CoreRoleCode.USER_ROLE_ADMIN}, mode = RoleMatchMode.ANY)
@@ -86,26 +88,26 @@ public class RoleController {
@RequireCoreRole(value = {CoreRoleCode.ADMIN, CoreRoleCode.USER_ROLE_ADMIN}, mode = RoleMatchMode.ANY)
@RequireCorePermission(CorePermissionCode.USER_ROLE_READ)
@PostMapping("/authorized/list")
public List<Role> listUserRole(@RequestParam String userId, @RequestParam(required = false) ModuleCode moduleCode) {
public List<Role> listUserRole(@RequestParam(required = false) ModuleCode moduleCode, @RequestParam String userId) {
if (moduleCode != null) {
return service.listByUserId(userId, moduleCode);
return userRoleService.listRoleByUserId(moduleCode, userId);
}
return service.listByUserId(userId);
return userRoleService.listRoleByUserId(userId);
}
@AOPLog
@RequireCoreRole(value = {CoreRoleCode.ADMIN, CoreRoleCode.USER_ROLE_ADMIN}, mode = RoleMatchMode.ANY)
@RequireCorePermission(value = {CorePermissionCode.USER_ROLE_CREATE, CorePermissionCode.USER_ROLE_DELETE})
@PostMapping("/authorized/create")
public void authorizeUserRole(@RequestBody UserRoleAuthorizeReq req) {
service.authorizeUserRole(req);
public void authorizeUserRole(@RequestBody UserRoleAuthorizeRequest req) {
userRoleService.authorizeUserRole(req);
}
@RequireCoreRole(value = {CoreRoleCode.ADMIN, CoreRoleCode.USER_ROLE_ADMIN}, mode = RoleMatchMode.ANY)
@RequireCorePermission(CorePermissionCode.USER_ROLE_READ)
@PostMapping("/authorized/permission")
public List<Permission> listAuthorizedPermission(@RequestParam String userId) {
return service.listAllPermissionByUserId(userId);
return userRoleService.listAllPermissionByUserId(userId);
}
private void fillRoleDetail(Role role) {
@@ -8,6 +8,7 @@ import com.imyeyu.api.modules.user.bean.Gender;
import com.imyeyu.spring.annotation.table.Transient;
import com.imyeyu.spring.entity.UUIDEntity;
import com.imyeyu.spring.util.ResponseView;
import com.imyeyu.utils.Regex;
import com.imyeyu.utils.Time;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -123,6 +124,10 @@ public class User extends UUIDEntity {
@JsonView(ResponseView.Public.class)
protected List<String> permissionList;
@Transient
@JsonView(ResponseView.Public.class)
protected List<Role> roleEntityList;
@Transient
@JsonView(ResponseView.Public.class)
protected List<Attachment> attachmentList;
@@ -135,6 +140,10 @@ public class User extends UUIDEntity {
@JsonView(ResponseView.Public.class)
protected List<String> tempFileIdList;
public boolean isValidPhone() {
return Regex.isMatch(Regex.MOBILE_PHONE, phoneNo);
}
/** @return true 为禁言中 */
public boolean isMuting() {
return unmuteAt != null && Time.now() < unmuteAt;
@@ -3,8 +3,8 @@ package com.imyeyu.api.modules.user.mapper;
import com.imyeyu.api.bean.ModuleCode;
import com.imyeyu.api.modules.user.entity.Role;
import com.imyeyu.spring.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
/**
@@ -15,9 +15,7 @@ import java.util.List;
*/
public interface RoleMapper extends BaseMapper<Role, String> {
List<Role> selectByIdList(List<String> idList);
List<Role> selectByIdList(Collection<String> idList);
List<Role> selectByModuleCodeAndCodeList(@Param("moduleCode") ModuleCode moduleCode, @Param("codeList") List<String> codeList);
List<Role> selectByModuleCode(@Param("moduleCode") ModuleCode moduleCode);
List<Role> selectByModuleCode(ModuleCode moduleCode);
}
@@ -4,6 +4,7 @@ import com.imyeyu.api.modules.user.entity.User;
import com.imyeyu.spring.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
import java.util.Collection;
import java.util.List;
/**
@@ -32,5 +33,5 @@ public interface UserMapper extends BaseMapper<User, String> {
* @param idList 用户 ID 列表
* @return 用户列表
*/
List<User> listByIdList(List<String> idList);
List<User> listByIdList(Collection<String> idList);
}
@@ -2,7 +2,9 @@ package com.imyeyu.api.modules.user.mapper;
import com.imyeyu.api.modules.user.entity.UserRole;
import com.imyeyu.spring.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
/**
@@ -15,5 +17,7 @@ public interface UserRoleMapper extends BaseMapper<UserRole, String> {
void createBatch(List<UserRole> userRoleList);
List<UserRole> selectByUserIdList(@Param("userIdList") Collection<String> userIdList);
void deleteByRoleIdList(String userId, List<String> roleIdList);
}
@@ -3,9 +3,9 @@ package com.imyeyu.api.modules.user.service;
import com.imyeyu.api.bean.ModuleCode;
import com.imyeyu.api.modules.user.entity.Permission;
import com.imyeyu.api.modules.user.entity.Role;
import com.imyeyu.api.modules.user.vo.role.UserRoleAuthorizeReq;
import com.imyeyu.spring.service.BaseService;
import java.util.Collection;
import java.util.List;
/// 角色服务
@@ -14,60 +14,13 @@ import java.util.List;
/// @since 2026-05-13 14:46
public interface RoleService extends BaseService<Role, String> {
/// 给用户授权角色
///
/// @param req 用户角色授权请求
void authorizeUserRole(UserRoleAuthorizeReq req);
/// 查询用户直属角色
///
/// @param userId 用户 ID
/// @return 角色列表
List<Role> listByUserId(String userId);
/// 查询用户指定模块直属角色
///
/// @param userId 用户 ID
/// @param moduleCode 模块代码
/// @return 角色列表
List<Role> listByUserId(String userId, ModuleCode moduleCode);
/// 查询模块角色
///
/// @param moduleCode 模块代码
/// @return 角色列表
List<Role> listByModuleCode(ModuleCode moduleCode);
/// 查询用户直属角色编码
///
/// @param userId 用户 ID
/// @return 角色编码列表,格式为 MODULE:ROLE
default List<String> listCodeByUserId(String userId) {
return listByUserId(userId).stream().map(role -> "%s:%s".formatted(role.getModuleCode().name(), role.getCode())).toList();
}
/// 查询用户全部角色编码
///
/// @param userId 用户 ID
/// @return 包含子角色的角色编码列表,格式为 MODULE:ROLE
List<String> listAllCodeByUserId(String userId);
/// 查询用户全部权限
///
/// @param userId 用户 ID
/// @return 权限列表
List<Permission> listAllPermissionByUserId(String userId);
/// 查询用户全部权限编码
///
/// @param userId 用户 ID
/// @return 权限编码列表,格式为 MODULE:PERMISSION
default List<String> listAllPermissionCodeByUserId(String userId) {
return listAllPermissionByUserId(userId).stream()
.map(permission -> "%s:%s".formatted(permission.getModuleCode().name(), permission.getCode()))
.distinct()
.toList();
}
List<Role> listByIdList(Collection<String> idList);
/// 查询直属子角色
///
@@ -80,4 +33,10 @@ public interface RoleService extends BaseService<Role, String> {
/// @param roleId 角色 ID
/// @return 权限列表
List<Permission> listPermissionByRoleId(String roleId);
/// 递归获取角色及其所有子角色的 ID 列表
///
/// @param idList 角色 ID 列表
/// @return 包含所有子角色的 ID 列表
List<String> listAllRoleIdIncludingChildren(Collection<String> idList);
}
@@ -1,9 +1,15 @@
package com.imyeyu.api.modules.user.service;
import com.imyeyu.api.bean.ModuleCode;
import com.imyeyu.api.modules.user.entity.Permission;
import com.imyeyu.api.modules.user.entity.Role;
import com.imyeyu.api.modules.user.entity.UserRole;
import com.imyeyu.api.modules.user.vo.role.UserRoleAuthorizeRequest;
import com.imyeyu.spring.service.BaseService;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/// 用户角色绑定服务
///
@@ -16,11 +22,62 @@ public interface UserRoleService extends BaseService<UserRole, String> {
/// @param list 用户角色绑定列表
void createBatch(List<UserRole> list);
/// 查询用户角色绑定
/// 给用户授权角色
///
/// @param req 用户角色授权请求
void authorizeUserRole(UserRoleAuthorizeRequest req);
List<UserRole> listByUserId(String userId);
/// 查询多个用户角色绑定
///
/// @param userIdList 用户 ID 列表
/// @return 用户角色绑定列表
List<UserRole> listByUserIdList(Collection<String> userIdList);
/// 查询用户直属角色
///
/// @param userId 用户 ID
/// @return 用户角色绑定列表
List<UserRole> listByUserId(String userId);
/// @return 角色列表
List<Role> listRoleByUserId(String userId);
/// 查询用户指定模块直属角色
///
/// @param moduleCode 模块代码
/// @param userId 用户 ID
/// @return 角色列表
List<Role> listRoleByUserId(ModuleCode moduleCode, String userId);
/// 查询用户直属角色编码
///
/// @param userId 用户 ID
/// @return 角色编码列表,格式为 MODULE:ROLE
default List<String> listRoleCodeByUserId(String userId) {
return listRoleByUserId(userId).stream().map(role -> "%s:%s".formatted(role.getModuleCode().name(), role.getCode())).toList();
}
/// 查询用户全部角色编码
///
/// @param userId 用户 ID
/// @return 包含子角色的角色编码列表,格式为 MODULE:ROLE
List<String> listAllRoleCodeByUserId(String userId);
/// 查询用户全部权限
///
/// @param userId 用户 ID
/// @return 权限列表
List<Permission> listAllPermissionByUserId(String userId);
/// 查询用户全部权限编码
///
/// @param userId 用户 ID
/// @return 权限编码列表,格式为 MODULE:PERMISSION
default List<String> listAllPermissionCodeByUserId(String userId) {
return listAllPermissionByUserId(userId).stream()
.map(permission -> "%s:%s".formatted(permission.getModuleCode().name(), permission.getCode()))
.distinct()
.toList();
}
/// 查询用户直属角色 ID
///
@@ -31,6 +88,12 @@ public interface UserRoleService extends BaseService<UserRole, String> {
return bindingList.stream().map(UserRole::getRoleId).toList();
}
/// 按用户 ID 分组查询直属角色
///
/// @param idList 用户 ID 列表
/// @return 用户角色映射
Map<String, List<Role>> mapRoleListByUserIdList(Collection<String> idList);
/// 删除用户指定角色绑定
///
/// @param userId 用户 ID
@@ -3,6 +3,9 @@ package com.imyeyu.api.modules.user.service;
import com.imyeyu.api.modules.user.entity.User;
import com.imyeyu.spring.service.BaseService;
import java.util.Collection;
import java.util.Map;
/**
* 用户管理服务
*
@@ -20,4 +23,10 @@ public interface UserService extends BaseService<User, String> {
User getByPhoneNo(String phoneNo);
User getByVerifiedPhoneNo(String phoneNo);
void verifyEmail(String id);
void verifyPhoneNo(String id);
Map<String, User> mapByIdList(Collection<String> idList);
}
@@ -4,6 +4,7 @@ import com.imyeyu.api.bean.ModuleCode;
import com.imyeyu.api.modules.user.service.PermissionChecker;
import com.imyeyu.api.modules.user.service.RoleService;
import com.imyeyu.api.modules.user.service.UserLoginService;
import com.imyeyu.api.modules.user.service.UserRoleService;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import lombok.RequiredArgsConstructor;
@@ -25,7 +26,7 @@ import java.util.Set;
@RequiredArgsConstructor
public class PermissionCheckerImplement implements PermissionChecker {
private final RoleService roleService;
private final UserRoleService userRoleService;
private final UserLoginService userLoginService;
public Set<String> codeSet() {
@@ -34,7 +35,7 @@ public class PermissionCheckerImplement implements PermissionChecker {
@Override
public Set<String> codeSet(String userId) {
return new HashSet<>(roleService.listAllPermissionCodeByUserId(userId));
return new HashSet<>(userRoleService.listAllPermissionCodeByUserId(userId));
}
@Override
@@ -2,8 +2,8 @@ package com.imyeyu.api.modules.user.service.implement;
import com.imyeyu.api.bean.ModuleCode;
import com.imyeyu.api.modules.user.service.RoleChecker;
import com.imyeyu.api.modules.user.service.RoleService;
import com.imyeyu.api.modules.user.service.UserLoginService;
import com.imyeyu.api.modules.user.service.UserRoleService;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import lombok.RequiredArgsConstructor;
@@ -24,12 +24,12 @@ import java.util.Set;
@RequiredArgsConstructor
public class RoleCheckerImplement implements RoleChecker {
private final RoleService roleService;
private final UserRoleService userRoleService;
private final UserLoginService userLoginService;
@Override
public Set<String> codeSet() {
return new HashSet<>(roleService.listAllCodeByUserId(userLoginService.getRequireLoginUserId()));
return new HashSet<>(userRoleService.listAllRoleCodeByUserId(userLoginService.getRequireLoginUserId()));
}
@Override
@@ -2,23 +2,17 @@ package com.imyeyu.api.modules.user.service.implement;
import com.imyeyu.api.bean.ModuleCode;
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
import com.imyeyu.api.modules.common.entity.Multilingual;
import com.imyeyu.api.modules.common.mapper.MultilingualMapper;
import com.imyeyu.api.modules.common.service.MultilingualService;
import com.imyeyu.api.modules.user.entity.Permission;
import com.imyeyu.api.modules.user.entity.Role;
import com.imyeyu.api.modules.user.entity.RolePermission;
import com.imyeyu.api.modules.user.entity.RoleRelation;
import com.imyeyu.api.modules.user.entity.UserRole;
import com.imyeyu.api.modules.user.mapper.RoleMapper;
import com.imyeyu.api.modules.user.mapper.RolePermissionMapper;
import com.imyeyu.api.modules.user.mapper.RoleRelationMapper;
import com.imyeyu.api.modules.user.service.PermissionService;
import com.imyeyu.api.modules.user.service.RoleService;
import com.imyeyu.api.modules.user.service.UserRoleService;
import com.imyeyu.api.modules.user.vo.role.UserRoleAuthorizeReq;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.mapper.BaseMapper;
import com.imyeyu.spring.service.AbstractEntityService;
@@ -28,6 +22,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -42,9 +37,7 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class RoleServiceImplement extends AbstractEntityService<Role, String> implements RoleService {
private final UserRoleService userRoleService;
private final PermissionService permissionService;
private final MultilingualMapper multilingualMapper;
private final MultilingualService multilingualService;
private final RoleMapper mapper;
@@ -153,67 +146,6 @@ public class RoleServiceImplement extends AbstractEntityService<Role, String> im
}
}
@Transactional(TimiServerDBConfig.ROLLBACKER)
@Override
public void authorizeUserRole(UserRoleAuthorizeReq req) {
TimiException.required(req, "not found req");
TimiException.required(req.getUserId(), "not found req.userId");
if (req.getModuleCode() == null) {
throw new TimiException(TimiCode.ARG_MISS, "moduleCode");
}
List<UserRole> bindingList = userRoleService.listByUserId(req.getUserId());
List<String> bindingRoleIdList = bindingList.stream().map(UserRole::getRoleId).toList();
Set<String> dbIdSet = mapper.selectByIdList(bindingRoleIdList).stream()
.filter(role -> req.getModuleCode() == role.getModuleCode())
.map(Role::getId)
.collect(Collectors.toSet());
Set<String> newIdSet = new HashSet<>();
if (TimiJava.isNotEmpty(req.getRoleIdList())) {
newIdSet.addAll(mapper.selectByIdList(req.getRoleIdList()).stream()
.filter(role -> req.getModuleCode() == role.getModuleCode())
.map(Role::getId)
.toList());
}
if (TimiJava.isNotEmpty(req.getRoleCodeList())) {
newIdSet.addAll(mapper.selectByModuleCodeAndCodeList(req.getModuleCode(), req.getRoleCodeList()).stream().map(Role::getId).toList());
}
Set<String> deleteIdList = new HashSet<>(dbIdSet);
deleteIdList.removeAll(newIdSet);
Set<String> addIdList = new HashSet<>(newIdSet);
addIdList.removeAll(dbIdSet);
if (TimiJava.isNotEmpty(deleteIdList)) {
userRoleService.deleteByRoleIdList(req.getUserId(), new ArrayList<>(deleteIdList));
}
if (TimiJava.isNotEmpty(addIdList)) {
List<UserRole> roleBindingList = new ArrayList<>();
long now = Time.now();
for (String roleId : addIdList) {
UserRole roleBinding = new UserRole();
roleBinding.setId(UUID.randomUUID().toString());
roleBinding.setUserId(req.getUserId());
roleBinding.setRoleId(roleId);
roleBinding.setCreatedAt(now);
roleBindingList.add(roleBinding);
}
userRoleService.createBatch(roleBindingList);
}
}
@Override
public List<Role> listByUserId(String userId) {
return mapper.selectByIdList(userRoleService.listRoleIdByUserId(userId));
}
@Override
public List<Role> listByUserId(String userId, ModuleCode moduleCode) {
TimiException.required(moduleCode, "not found moduleCode");
return listByUserId(userId).stream()
.filter(role -> moduleCode == role.getModuleCode())
.toList();
}
@Override
public List<Role> listByModuleCode(ModuleCode moduleCode) {
TimiException.required(moduleCode, "not found moduleCode");
@@ -221,20 +153,8 @@ public class RoleServiceImplement extends AbstractEntityService<Role, String> im
}
@Override
public List<String> listAllCodeByUserId(String userId) {
List<String> roleIdList = listByUserId(userId).stream().map(Role::getId).toList();
List<String> allRoleIdList = getAllRoleIdsIncludingChildren(roleIdList);
if (TimiJava.isEmpty(allRoleIdList)) {
return List.of();
}
return mapper.selectByIdList(allRoleIdList).stream().map(role -> "%s:%s".formatted(role.getModuleCode().name(), role.getCode())).distinct().toList();
}
@Override
public List<Permission> listAllPermissionByUserId(String userId) {
List<String> roleIdList = listByUserId(userId).stream().map(Role::getId).toList();
List<String> allRoleIdList = getAllRoleIdsIncludingChildren(roleIdList);
return permissionService.listByRoleId(allRoleIdList);
public List<Role> listByIdList(Collection<String> idList) {
return mapper.selectByIdList(new HashSet<>(idList));
}
@Override
@@ -248,20 +168,13 @@ public class RoleServiceImplement extends AbstractEntityService<Role, String> im
@Override
public List<Permission> listPermissionByRoleId(String roleId) {
List<String> allRoleIdList = getAllRoleIdsIncludingChildren(List.of(roleId));
List<String> allRoleIdList = listAllRoleIdIncludingChildren(List.of(roleId));
return permissionService.listByRoleId(allRoleIdList);
}
/// 递归获取角色及其所有子角色的 ID 列表
///
/// @param roleIdList 角色 ID 列表
/// @return 包含所有子角色的 ID 列表
private List<String> getAllRoleIdsIncludingChildren(List<String> roleIdList) {
if (TimiJava.isEmpty(roleIdList)) {
return new ArrayList<>();
}
Set<String> allRoleIdSet = new HashSet<>(roleIdList);
List<String> currentLevelRoleIdList = new ArrayList<>(roleIdList);
public List<String> listAllRoleIdIncludingChildren(Collection<String> idList) {
Set<String> allRoleIdSet = new HashSet<>(idList);
List<String> currentLevelRoleIdList = new ArrayList<>(idList);
while (TimiJava.isNotEmpty(currentLevelRoleIdList)) {
List<String> childRoleIdList = roleRelationMapper.selectChildRoleIdListByParentRoleIdList(currentLevelRoleIdList);
@@ -277,18 +190,4 @@ public class RoleServiceImplement extends AbstractEntityService<Role, String> im
}
return new ArrayList<>(allRoleIdSet);
}
private String saveNameMultilingual(String langId, String name) {
if (TimiJava.isEmpty(name)) {
return langId;
}
if (TimiJava.isEmpty(langId)) {
return multilingualService.create(name);
}
Multilingual multilingual = new Multilingual();
multilingual.setId(langId);
multilingual.setZhCN(name);
multilingualMapper.updateSelective(multilingual);
return langId;
}
}
@@ -9,6 +9,7 @@ import com.imyeyu.api.modules.user.bean.BootstrapData;
import com.imyeyu.api.modules.user.entity.User;
import com.imyeyu.api.modules.user.service.RoleService;
import com.imyeyu.api.modules.user.service.UserLoginService;
import com.imyeyu.api.modules.user.service.UserRoleService;
import com.imyeyu.api.modules.user.service.UserService;
import com.imyeyu.api.modules.user.vo.LoginRequest;
import com.imyeyu.api.modules.user.vo.LoginResponse;
@@ -45,6 +46,7 @@ public class UserLoginServiceImplement implements UserLoginService, TimiJava {
private final UserService userService;
private final RoleService roleService;
private final SettingService settingService;
private final UserRoleService userRoleService;
private final AttachmentService attachmentService;
private final Redis<String, String> redisUserToken;
@@ -86,8 +88,8 @@ public class UserLoginServiceImplement implements UserLoginService, TimiJava {
result.setUser(userService.get(userId));
User user = result.getUser();
user.setPermissionList(roleService.listAllPermissionCodeByUserId(user.getId()));
user.setRoleList(roleService.listAllCodeByUserId(user.getId()));
user.setPermissionList(userRoleService.listAllPermissionCodeByUserId(user.getId()));
user.setRoleList(userRoleService.listAllRoleCodeByUserId(user.getId()));
user.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.USER, user.getId()));
return result;
}
@@ -1,14 +1,34 @@
package com.imyeyu.api.modules.user.service.implement;
import com.imyeyu.api.bean.ModuleCode;
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
import com.imyeyu.api.modules.user.entity.Permission;
import com.imyeyu.api.modules.user.entity.Role;
import com.imyeyu.api.modules.user.entity.UserRole;
import com.imyeyu.api.modules.user.mapper.UserRoleMapper;
import com.imyeyu.api.modules.user.service.PermissionService;
import com.imyeyu.api.modules.user.service.RoleService;
import com.imyeyu.api.modules.user.service.UserRoleService;
import com.imyeyu.api.modules.user.vo.role.UserRoleAuthorizeRequest;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.mapper.BaseMapper;
import com.imyeyu.spring.service.AbstractEntityService;
import com.imyeyu.utils.Time;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
/// 用户角色服务实现
///
@@ -18,6 +38,9 @@ import java.util.List;
@RequiredArgsConstructor
public class UserRoleServiceImplement extends AbstractEntityService<UserRole, String> implements UserRoleService {
private final RoleService roleService;
private final PermissionService permissionService;
private final UserRoleMapper mapper;
@Override
@@ -30,6 +53,49 @@ public class UserRoleServiceImplement extends AbstractEntityService<UserRole, St
mapper.createBatch(list);
}
@Transactional(TimiServerDBConfig.ROLLBACKER)
@Override
public void authorizeUserRole(UserRoleAuthorizeRequest req) {
TimiException.required(req, "not found req");
TimiException.required(req.getUserId(), "not found req.userId");
if (req.getModuleCode() == null) {
throw new TimiException(TimiCode.ARG_MISS, "moduleCode");
}
List<UserRole> bindingList = listByUserId(req.getUserId());
List<String> bindingRoleIdList = bindingList.stream().map(UserRole::getRoleId).toList();
Set<String> dbIdSet = roleService.listByIdList(bindingRoleIdList)
.stream()
.filter(role -> req.getModuleCode() == role.getModuleCode())
.map(Role::getId)
.collect(Collectors.toSet());
Set<String> newIdSet = new HashSet<>();
if (TimiJava.isNotEmpty(req.getRoleIdList())) {
newIdSet.addAll(roleService.listByIdList(req.getRoleIdList()).stream().filter(role -> req.getModuleCode() == role.getModuleCode()).map(Role::getId).toList());
}
Set<String> deleteIdList = new HashSet<>(dbIdSet);
deleteIdList.removeAll(newIdSet);
Set<String> addIdList = new HashSet<>(newIdSet);
addIdList.removeAll(dbIdSet);
if (TimiJava.isNotEmpty(deleteIdList)) {
deleteByRoleIdList(req.getUserId(), new ArrayList<>(deleteIdList));
}
if (TimiJava.isNotEmpty(addIdList)) {
List<UserRole> roleBindingList = new ArrayList<>();
long now = Time.now();
for (String roleId : addIdList) {
UserRole roleBinding = new UserRole();
roleBinding.setId(UUID.randomUUID().toString());
roleBinding.setUserId(req.getUserId());
roleBinding.setRoleId(roleId);
roleBinding.setCreatedAt(now);
roleBindingList.add(roleBinding);
}
createBatch(roleBindingList);
}
}
@Override
public List<UserRole> listByUserId(String userId) {
UserRole example = new UserRole();
@@ -37,6 +103,57 @@ public class UserRoleServiceImplement extends AbstractEntityService<UserRole, St
return mapper.selectAllByExample(example);
}
@Override
public List<UserRole> listByUserIdList(Collection<String> userIdList) {
return mapper.selectByUserIdList(userIdList);
}
@Override
public List<Role> listRoleByUserId(String userId) {
List<UserRole> userRoleList = listByUserId(userId);
return roleService.listByIdList(userRoleList.stream().map(UserRole::getRoleId).toList());
}
@Override
public List<Role> listRoleByUserId(ModuleCode moduleCode, String userId) {
TimiException.required(moduleCode, "not found moduleCode");
return listRoleByUserId(userId).stream().filter(role -> moduleCode == role.getModuleCode()).toList();
}
@Override
public List<String> listAllRoleCodeByUserId(String userId) {
List<String> roleIdList = listRoleByUserId(userId).stream().map(Role::getId).toList();
List<String> allRoleIdList = roleService.listAllRoleIdIncludingChildren(roleIdList);
if (TimiJava.isEmpty(allRoleIdList)) {
return List.of();
}
return roleService.listByIdList(allRoleIdList).stream().map(role -> "%s:%s".formatted(role.getModuleCode().name(), role.getCode())).distinct().toList();
}
@Override
public List<Permission> listAllPermissionByUserId(String userId) {
List<String> roleIdList = listRoleByUserId(userId).stream().map(Role::getId).toList();
List<String> allRoleIdList = roleService.listAllRoleIdIncludingChildren(roleIdList);
return permissionService.listByRoleId(allRoleIdList);
}
@Override
public Map<String, List<Role>> mapRoleListByUserIdList(Collection<String> idList) {
if (TimiJava.isEmpty(idList)) {
return Map.of();
}
List<UserRole> userRoleList = listByUserIdList(idList);
if (TimiJava.isEmpty(userRoleList)) {
return Map.of();
}
Map<String, Role> roleMap = roleService.listByIdList(userRoleList.stream().map(UserRole::getRoleId).distinct().toList())
.stream()
.collect(Collectors.toMap(Role::getId, Function.identity()));
return userRoleList.stream()
.filter(userRole -> roleMap.containsKey(userRole.getRoleId()))
.collect(Collectors.groupingBy(UserRole::getUserId, Collectors.mapping(userRole -> roleMap.get(userRole.getRoleId()), Collectors.toList())));
}
@Override
public void deleteByRoleIdList(String userId, List<String> roleIdList) {
mapper.deleteByRoleIdList(userId, roleIdList);
@@ -11,11 +11,18 @@ import com.imyeyu.spring.mapper.BaseMapper;
import com.imyeyu.spring.service.AbstractEntityService;
import com.imyeyu.utils.Digest;
import com.imyeyu.utils.Regex;
import com.imyeyu.utils.Time;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 用户管理服务实现
*
@@ -27,8 +34,6 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class UserServiceImplement extends AbstractEntityService<User, String> implements UserService, TimiJava {
private static final String REGEX_PHONE_NO = "^1\\d{10}$";
private final UserMapper mapper;
@Override
@@ -51,7 +56,7 @@ public class UserServiceImplement extends AbstractEntityService<User, String> im
}
{
if (TimiJava.isNotEmpty(user.getPhoneNo())) {
validatePhoneNo(user.getPhoneNo());
TimiException.requiredTrue(user.isValidPhone(), "invalid phone");
User byPhoneNo = getByVerifiedPhoneNo(user.getPhoneNo());
TimiException.requiredNull(byPhoneNo, "existed phone number");
}
@@ -65,7 +70,6 @@ public class UserServiceImplement extends AbstractEntityService<User, String> im
dbUser.setPassword(Digest.argon2id(user.getPassword()));
dbUser.setEmail(user.getEmail());
dbUser.setPhoneNo(user.getPhoneNo());
dbUser.setPhoneNoVerifyAt(user.getPhoneNoVerifyAt());
dbUser.setExp(TimiJava.defaultIfNull(user.getExp(), 0));
super.create(dbUser);
user.setId(dbUser.getId());
@@ -88,7 +92,7 @@ public class UserServiceImplement extends AbstractEntityService<User, String> im
TimiException.requiredTrue(byEmail == null || byEmail.getId().equals(dbUser.getId()), "existed email");
}
if (TimiJava.isNotEmpty(phoneNo)) {
validatePhoneNo(phoneNo);
TimiException.requiredTrue(user.isValidPhone(), "invalid phone");
if (!phoneNo.equals(dbUser.getPhoneNo())) {
User byPhoneNo = getByVerifiedPhoneNo(phoneNo);
TimiException.requiredTrue(byPhoneNo == null || byPhoneNo.getId().equals(dbUser.getId()), "existed phone number");
@@ -138,7 +142,22 @@ public class UserServiceImplement extends AbstractEntityService<User, String> im
return mapper.selectByVerifiedPhoneNo(phoneNo);
}
private void validatePhoneNo(String phoneNo) {
TimiException.requiredTrue(Regex.isMatch(REGEX_PHONE_NO, phoneNo), "invalid phone number");
@Override
public void verifyEmail(String id) {
User user = get(id);
user.setEmailVerifyAt(Time.now());
update(user);
}
@Override
public void verifyPhoneNo(String id) {
User user = get(id);
user.setPhoneNoVerifyAt(Time.now());
update(user);
}
@Override
public Map<String, User> mapByIdList(Collection<String> idList) {
return mapper.listByIdList(new HashSet<>(idList)).stream().collect(Collectors.toMap(User::getId, Function.identity()));
}
}
@@ -10,13 +10,11 @@ import java.util.List;
/// @author 夜雨
/// @since 2026-07-17 14:16
@Data
public class UserRoleAuthorizeReq {
public class UserRoleAuthorizeRequest {
private String userId;
private ModuleCode moduleCode;
private List<String> roleIdList;
private List<String> roleCodeList;
}