fix user group permission scope
This commit is contained in:
@@ -216,13 +216,6 @@ public class AuthInterceptor implements HandlerInterceptor {
|
||||
requestContext.setLangMap(userDto.getLangMap());
|
||||
requestContext.setLang(userDto.getLang());
|
||||
log.debug("JWT token OK, userId: {} ", userDto.getId());
|
||||
if (originalRequestUri.startsWith("/api/system/")) {
|
||||
//判断是不是管理员
|
||||
if (userDto.getRole() != User.Role.Admin) {
|
||||
throw BizException.of(ErrorCodeEnum.PERMISSION_DENIED, BizExceptionCodeEnum.permissionDenied);
|
||||
}
|
||||
}
|
||||
|
||||
String header = request.getHeader("X-Client-Type");
|
||||
if (header != null || token.startsWith("ticket")) {
|
||||
authService.renewToken(token);
|
||||
@@ -358,4 +351,4 @@ public class AuthInterceptor implements HandlerInterceptor {
|
||||
throw BizException.of(HttpStatusEnum.UNAUTHORIZED, ErrorCodeEnum.UNAUTHORIZED,
|
||||
BizExceptionCodeEnum.systemUnauthorizedOrSessionExpired);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class UserQueryDto implements Serializable {
|
||||
@@ -29,4 +30,7 @@ public class UserQueryDto implements Serializable {
|
||||
|
||||
@Schema(description = "角色")
|
||||
private User.Role role;
|
||||
|
||||
@Schema(description = "用户ID范围,后端数据权限过滤使用")
|
||||
private List<Long> userIds;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.xspaceagi.system.application.dto.permission;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -28,6 +29,7 @@ public class SysGroupAddDto implements Serializable {
|
||||
private Integer authEnabled;
|
||||
|
||||
@Schema(description = "授权到期时间,空表示不过期")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date expireTime;
|
||||
|
||||
@Schema(description = "来源,1:系统内置 2:用户自定义", hidden = true)
|
||||
@@ -38,4 +40,4 @@ public class SysGroupAddDto implements Serializable {
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -31,6 +32,7 @@ public class SysGroupUpdateDto implements Serializable {
|
||||
private Integer authEnabled;
|
||||
|
||||
@Schema(description = "授权到期时间,空表示不过期")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date expireTime;
|
||||
|
||||
@Schema(description = "来源,1:系统内置 2:用户自定义", hidden = true)
|
||||
@@ -41,4 +43,4 @@ public class SysGroupUpdateDto implements Serializable {
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,6 +247,12 @@ public class UserApplicationServiceImpl implements UserApplicationService {
|
||||
UserQueryDto userQueryDto = pageQueryVo.getQueryFilter();
|
||||
if (userQueryDto != null) {
|
||||
BeanUtils.copyProperties(userQueryDto, user);
|
||||
if (userQueryDto.getUserIds() != null) {
|
||||
if (userQueryDto.getUserIds().isEmpty()) {
|
||||
return new Page<>(pageQueryVo.getPageNo(), pageQueryVo.getPageSize(), 0);
|
||||
}
|
||||
queryWrapper.in(User::getId, userQueryDto.getUserIds());
|
||||
}
|
||||
}
|
||||
if ("".equals(user.getUserName())) {
|
||||
user.setUserName(null);
|
||||
|
||||
@@ -5,15 +5,20 @@ import com.xspaceagi.system.application.dto.SendNotifyMessageDto;
|
||||
import com.xspaceagi.system.application.dto.UserDto;
|
||||
import com.xspaceagi.system.application.dto.UserQueryDto;
|
||||
import com.xspaceagi.system.application.service.NotifyMessageApplicationService;
|
||||
import com.xspaceagi.system.application.service.SysGroupApplicationService;
|
||||
import com.xspaceagi.system.application.service.UserApplicationService;
|
||||
import com.xspaceagi.system.infra.dao.entity.SysGroup;
|
||||
import com.xspaceagi.system.infra.dao.entity.NotifyMessage;
|
||||
import com.xspaceagi.system.infra.dao.entity.User;
|
||||
import com.xspaceagi.system.infra.dao.mapper.UserMapper;
|
||||
import com.xspaceagi.system.infra.dao.service.UserService;
|
||||
import com.xspaceagi.system.spec.annotation.RequireResource;
|
||||
import com.xspaceagi.system.spec.common.RequestContext;
|
||||
import com.xspaceagi.system.spec.common.UserContext;
|
||||
import com.xspaceagi.system.spec.dto.PageQueryVo;
|
||||
import com.xspaceagi.system.spec.dto.ReqResult;
|
||||
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
|
||||
import com.xspaceagi.system.spec.enums.GroupEnum;
|
||||
import com.xspaceagi.system.spec.exception.BizException;
|
||||
import com.xspaceagi.system.spec.exception.BizExceptionCodeEnum;
|
||||
import com.xspaceagi.system.web.dto.UserAddDto;
|
||||
@@ -28,6 +33,7 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.xspaceagi.system.spec.enums.ResourceEnum.*;
|
||||
@@ -40,17 +46,32 @@ public class UserManageController {
|
||||
@Resource
|
||||
private UserApplicationService userApplicationService;
|
||||
|
||||
@Resource
|
||||
private SysGroupApplicationService sysGroupApplicationService;
|
||||
|
||||
@Resource
|
||||
private NotifyMessageApplicationService notifyMessageApplicationService;
|
||||
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@RequireResource(USER_MANAGE_QUERY)
|
||||
@Operation(summary = "查询用户列表")
|
||||
@RequestMapping(path = "/list", method = RequestMethod.POST)
|
||||
public ReqResult<IPage<UserDto>> listQuery(@RequestBody PageQueryVo<UserQueryDto> pageQueryVo) {
|
||||
checkAdmin();
|
||||
if (pageQueryVo == null) {
|
||||
pageQueryVo = new PageQueryVo<>();
|
||||
}
|
||||
if (pageQueryVo.getPageNo() == null) {
|
||||
pageQueryVo.setPageNo(1L);
|
||||
}
|
||||
if (pageQueryVo.getPageSize() == null) {
|
||||
pageQueryVo.setPageSize(10L);
|
||||
}
|
||||
applyUserManageScope(pageQueryVo);
|
||||
return ReqResult.success(userApplicationService.listQuery(pageQueryVo));
|
||||
}
|
||||
|
||||
@@ -58,8 +79,6 @@ public class UserManageController {
|
||||
@Operation(summary = "获取用户统计")
|
||||
@RequestMapping(path = "/stats", method = RequestMethod.GET)
|
||||
public ReqResult<UserStatsDto> getUserStats() {
|
||||
checkAdmin();
|
||||
|
||||
Long totalUserCount = userMapper.countTotalUsers();
|
||||
Long todayNewUserCount = userMapper.countTodayNewUsers();
|
||||
|
||||
@@ -90,13 +109,17 @@ public class UserManageController {
|
||||
@Operation(summary = "添加用户")
|
||||
@RequestMapping(path = "/add", method = RequestMethod.POST)
|
||||
public ReqResult<Void> addUser(@RequestBody UserAddDto userAddDto) {
|
||||
checkAdmin();
|
||||
UserDto userDto = new UserDto();
|
||||
BeanUtils.copyProperties(userAddDto, userDto);
|
||||
if (StringUtils.isNotBlank(userAddDto.getPassword())) {
|
||||
userDto.setResetPass(1);
|
||||
}
|
||||
userDto.setRole(User.Role.User);
|
||||
userApplicationService.add(userDto);
|
||||
List<Long> groupIds = currentUserGroupIds().stream().toList();
|
||||
if (CollectionUtils.isNotEmpty(groupIds)) {
|
||||
groupIds.forEach(groupId -> sysGroupApplicationService.groupAddUser(groupId, userDto.getId(), getCurrentUserContext()));
|
||||
}
|
||||
return ReqResult.success();
|
||||
}
|
||||
|
||||
@@ -104,7 +127,7 @@ public class UserManageController {
|
||||
@Operation(summary = "更新用户信息")
|
||||
@RequestMapping(path = "/updateById/{id}", method = RequestMethod.POST)
|
||||
public ReqResult<Void> updateUserById(@PathVariable Long id, @RequestBody UserUpdateDto userUpdateDto) {
|
||||
checkAdmin();
|
||||
checkCurrentTenantUser(id);
|
||||
UserDto userUpdate = new UserDto();
|
||||
userUpdate.setId(id);
|
||||
userUpdate.setAvatar(userUpdateDto.getAvatar());
|
||||
@@ -122,7 +145,7 @@ public class UserManageController {
|
||||
@Operation(summary = "禁用用户")
|
||||
@RequestMapping(path = "/disable/{id}", method = RequestMethod.POST)
|
||||
public ReqResult<Void> disableUserById(@PathVariable Long id) {
|
||||
checkAdmin();
|
||||
checkCurrentTenantUser(id);
|
||||
UserDto userUpdate = new UserDto();
|
||||
userUpdate.setId(id);
|
||||
userUpdate.setStatus(User.Status.Disabled);
|
||||
@@ -134,7 +157,7 @@ public class UserManageController {
|
||||
@Operation(summary = "启用用户")
|
||||
@RequestMapping(path = "/enable/{id}", method = RequestMethod.POST)
|
||||
public ReqResult<Void> enableUserById(@PathVariable Long id) {
|
||||
checkAdmin();
|
||||
checkCurrentTenantUser(id);
|
||||
UserDto userUpdate = new UserDto();
|
||||
userUpdate.setId(id);
|
||||
userUpdate.setStatus(User.Status.Enabled);
|
||||
@@ -146,7 +169,7 @@ public class UserManageController {
|
||||
@Operation(summary = "删除用户")
|
||||
@RequestMapping(path = "/delete/{id}", method = RequestMethod.POST)
|
||||
public ReqResult<Void> deleteUserById(@PathVariable Long id) {
|
||||
checkAdmin();
|
||||
checkCurrentTenantUser(id);
|
||||
userApplicationService.logicDelete(id);
|
||||
return ReqResult.success();
|
||||
}
|
||||
@@ -165,12 +188,53 @@ public class UserManageController {
|
||||
return ReqResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前简单的在商家范围支持普通用户和管理员两种角色;后续再迭代完整的权限角色
|
||||
*/
|
||||
private void checkAdmin() {
|
||||
if (((UserDto) RequestContext.get().getUser()).getRole() != User.Role.Admin) {
|
||||
private void checkCurrentTenantUser(Long userId) {
|
||||
if (userId == null || userService.getById(userId) == null || !visibleUserIds().contains(userId)) {
|
||||
throw BizException.of(ErrorCodeEnum.PERMISSION_DENIED, BizExceptionCodeEnum.permissionDenied);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void applyUserManageScope(PageQueryVo<UserQueryDto> pageQueryVo) {
|
||||
if (pageQueryVo.getQueryFilter() == null) {
|
||||
pageQueryVo.setQueryFilter(new UserQueryDto());
|
||||
}
|
||||
pageQueryVo.getQueryFilter().setUserIds(visibleUserIds().stream().toList());
|
||||
}
|
||||
|
||||
private Set<Long> visibleUserIds() {
|
||||
return currentUserGroupIds().stream()
|
||||
.flatMap(groupId -> sysGroupApplicationService.getUserListByGroupId(groupId).stream())
|
||||
.map(User::getId)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private Set<Long> currentUserGroupIds() {
|
||||
return sysGroupApplicationService.getGroupListByUserId(getCurrentUserDto().getId()).stream()
|
||||
.filter(group -> !GroupEnum.DEFAULT_GROUP.getCode().equals(group.getCode()))
|
||||
.map(SysGroup::getId)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private UserDto getCurrentUserDto() {
|
||||
UserDto userDto = (UserDto) RequestContext.get().getUser();
|
||||
if (userDto == null) {
|
||||
throw BizException.of(ErrorCodeEnum.UNAUTHORIZED, BizExceptionCodeEnum.systemUserNotLoggedInWeb);
|
||||
}
|
||||
return userDto;
|
||||
}
|
||||
|
||||
private UserContext getCurrentUserContext() {
|
||||
UserDto userDto = getCurrentUserDto();
|
||||
return UserContext.builder()
|
||||
.userId(userDto.getId())
|
||||
.userName(userDto.getUserName())
|
||||
.nickName(userDto.getNickName())
|
||||
.avatar(userDto.getAvatar())
|
||||
.email(userDto.getEmail())
|
||||
.phone(userDto.getPhone())
|
||||
.status(userDto.getStatus() == User.Status.Enabled ? 1 : -1)
|
||||
.tenantId(userDto.getTenantId())
|
||||
.roleType(userDto.getRole() == User.Role.Admin ? 1 : 2)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,8 +344,8 @@ public class SysGroupController extends BaseController {
|
||||
return ReqResult.error("参数不能为空");
|
||||
}
|
||||
checkGroupManageScope(dto.getGroupId());
|
||||
// 用户组不允许绑定 生态市场/系统管理
|
||||
checkForbiddenMenuCodes(dto.getMenuTree());
|
||||
// 用户组不允许绑定生态市场和系统管理整棵子树。
|
||||
checkForbiddenMenuCodes(dto.getMenuTree(), false);
|
||||
|
||||
GroupBindMenuModel model = GroupBindMenuModelConverter.convertToModel(dto);
|
||||
sysGroupApplicationService.bindMenu(model, getUser());
|
||||
@@ -370,29 +370,31 @@ public class SysGroupController extends BaseController {
|
||||
return ReqResult.success(menuDtoList);
|
||||
}
|
||||
|
||||
private void checkForbiddenMenuCodes(List<MenuNodeDto> nodes) {
|
||||
private void checkForbiddenMenuCodes(List<MenuNodeDto> nodes, boolean underForbiddenMenu) {
|
||||
if (CollectionUtils.isEmpty(nodes)) {
|
||||
return;
|
||||
}
|
||||
for (MenuNodeDto node : nodes) {
|
||||
boolean currentForbidden = underForbiddenMenu;
|
||||
if (StringUtils.isNotBlank(node.getCode())) {
|
||||
if (node.getCode().equals(MenuEnum.ECO_MARKET.getCode()) && node.getMenuBindType() > 0) {
|
||||
throw BizException.of(ErrorCodeEnum.INVALID_PARAM, BizExceptionCodeEnum.systemGroupCannotBindForbiddenMenu,
|
||||
MenuEnum.ECO_MARKET.getName());
|
||||
}
|
||||
if (node.getCode().equals(MenuEnum.SYSTEM_MANAGE.getCode()) && node.getMenuBindType() > 0) {
|
||||
currentForbidden = currentForbidden || node.getCode().equals(MenuEnum.SYSTEM_MANAGE.getCode());
|
||||
if (currentForbidden && node.getMenuBindType() > 0) {
|
||||
throw BizException.of(ErrorCodeEnum.INVALID_PARAM, BizExceptionCodeEnum.systemGroupCannotBindForbiddenMenu,
|
||||
MenuEnum.SYSTEM_MANAGE.getName());
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(node.getChildren())) {
|
||||
checkForbiddenMenuCodes(node.getChildren());
|
||||
checkForbiddenMenuCodes(node.getChildren(), currentForbidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<SysGroup> filterGroupManageScope(List<SysGroup> groupList) {
|
||||
if (isPlatformAdmin() || CollectionUtils.isEmpty(groupList)) {
|
||||
if (CollectionUtils.isEmpty(groupList)) {
|
||||
return groupList;
|
||||
}
|
||||
Set<Long> allowedGroupIds = currentUserGroupIds();
|
||||
@@ -402,24 +404,18 @@ public class SysGroupController extends BaseController {
|
||||
}
|
||||
|
||||
private void checkGroupManageScope(Long groupId) {
|
||||
if (isPlatformAdmin()) {
|
||||
return;
|
||||
}
|
||||
if (groupId == null || !currentUserGroupIds().contains(groupId)) {
|
||||
throw BizException.of(ErrorCodeEnum.PERMISSION_DENIED, BizExceptionCodeEnum.permissionDenied);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Long> currentUserGroupIds() {
|
||||
return sysGroupApplicationService.getEffectiveGroupListByUserId(getCurrentUserDto().getId()).stream()
|
||||
return sysGroupApplicationService.getGroupListByUserId(getCurrentUserDto().getId()).stream()
|
||||
.filter(group -> !GroupEnum.DEFAULT_GROUP.getCode().equals(group.getCode()))
|
||||
.map(SysGroup::getId)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private boolean isPlatformAdmin() {
|
||||
return getCurrentUserDto().getRole() == User.Role.Admin;
|
||||
}
|
||||
|
||||
private UserDto getCurrentUserDto() {
|
||||
UserDto userDto = (UserDto) RequestContext.get().getUser();
|
||||
if (userDto == null) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.xspaceagi.system.application.dto.permission.*;
|
||||
import com.xspaceagi.system.application.service.SysDataPermissionApplicationService;
|
||||
import com.xspaceagi.system.application.service.SysGroupApplicationService;
|
||||
import com.xspaceagi.system.application.service.SysRoleApplicationService;
|
||||
import com.xspaceagi.system.application.service.UserApplicationService;
|
||||
import com.xspaceagi.system.application.service.impl.SysUserPermissionCacheServiceImpl;
|
||||
import com.xspaceagi.system.infra.dao.entity.SysGroup;
|
||||
import com.xspaceagi.system.infra.dao.entity.SysRole;
|
||||
@@ -15,6 +16,7 @@ import com.xspaceagi.system.spec.annotation.SaasAdmin;
|
||||
import com.xspaceagi.system.spec.common.RequestContext;
|
||||
import com.xspaceagi.system.spec.dto.ReqResult;
|
||||
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
|
||||
import com.xspaceagi.system.spec.enums.GroupEnum;
|
||||
import com.xspaceagi.system.spec.exception.BizException;
|
||||
import com.xspaceagi.system.spec.exception.BizExceptionCodeEnum;
|
||||
import com.xspaceagi.system.spec.utils.I18nUtil;
|
||||
@@ -28,6 +30,7 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -47,6 +50,8 @@ public class SysUserController extends BaseController {
|
||||
private SysDataPermissionApplicationService sysDataPermissionApplicationService;
|
||||
@Resource
|
||||
private SysUserPermissionCacheServiceImpl sysUserPermissionCacheService;
|
||||
@Resource
|
||||
private UserApplicationService userApplicationService;
|
||||
|
||||
@RequireResource(USER_MANAGE_BIND_ROLE)
|
||||
@Operation(summary = "查询用户绑定的角色列表")
|
||||
@@ -56,6 +61,7 @@ public class SysUserController extends BaseController {
|
||||
return ReqResult.error("参数不能为空");
|
||||
}
|
||||
checkUserManageScope(userId);
|
||||
checkRoleAuthorizationTarget(userId);
|
||||
|
||||
List<SysRole> roleList = sysRoleApplicationService.getRoleListByUserId(userId);
|
||||
if (CollectionUtils.isEmpty(roleList)) {
|
||||
@@ -79,6 +85,7 @@ public class SysUserController extends BaseController {
|
||||
return ReqResult.error("参数不能为空");
|
||||
}
|
||||
checkUserManageScope(dto.getUserId());
|
||||
checkRoleAuthorizationTarget(dto.getUserId());
|
||||
checkRoleBindScope(dto.getRoleIds());
|
||||
sysRoleApplicationService.userBindRole(dto.getUserId(), dto.getRoleIds(), getUser());
|
||||
return ReqResult.success();
|
||||
@@ -146,11 +153,13 @@ public class SysUserController extends BaseController {
|
||||
}
|
||||
|
||||
private void checkUserManageScope(Long userId) {
|
||||
if (isPlatformAdmin()) {
|
||||
return;
|
||||
UserDto targetUser = userApplicationService.queryById(userId);
|
||||
if (targetUser == null || !Objects.equals(targetUser.getTenantId(), RequestContext.get().getTenantId())) {
|
||||
throw BizException.of(ErrorCodeEnum.PERMISSION_DENIED, BizExceptionCodeEnum.permissionDenied);
|
||||
}
|
||||
|
||||
Set<Long> allowedGroupIds = currentUserGroupIds();
|
||||
boolean inScope = sysGroupApplicationService.getEffectiveGroupListByUserId(userId).stream()
|
||||
boolean inScope = sysGroupApplicationService.getGroupListByUserId(userId).stream()
|
||||
.map(SysGroup::getId)
|
||||
.anyMatch(allowedGroupIds::contains);
|
||||
if (!inScope) {
|
||||
@@ -159,7 +168,7 @@ public class SysUserController extends BaseController {
|
||||
}
|
||||
|
||||
private void checkGroupBindScope(List<Long> groupIds) {
|
||||
if (isPlatformAdmin() || CollectionUtils.isEmpty(groupIds)) {
|
||||
if (CollectionUtils.isEmpty(groupIds)) {
|
||||
return;
|
||||
}
|
||||
Set<Long> allowedGroupIds = currentUserGroupIds();
|
||||
@@ -170,7 +179,7 @@ public class SysUserController extends BaseController {
|
||||
}
|
||||
|
||||
private void checkRoleBindScope(List<Long> roleIds) {
|
||||
if (isPlatformAdmin() || CollectionUtils.isEmpty(roleIds)) {
|
||||
if (CollectionUtils.isEmpty(roleIds)) {
|
||||
return;
|
||||
}
|
||||
Set<Long> allowedRoleIds = sysRoleApplicationService.getRoleListByUserId(getCurrentUserDto().getId()).stream()
|
||||
@@ -182,14 +191,18 @@ public class SysUserController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Long> currentUserGroupIds() {
|
||||
return sysGroupApplicationService.getEffectiveGroupListByUserId(getCurrentUserDto().getId()).stream()
|
||||
.map(SysGroup::getId)
|
||||
.collect(Collectors.toSet());
|
||||
private void checkRoleAuthorizationTarget(Long userId) {
|
||||
UserDto targetUser = userApplicationService.queryById(userId);
|
||||
if (targetUser == null || targetUser.getRole() != User.Role.Admin) {
|
||||
throw BizException.of(ErrorCodeEnum.PERMISSION_DENIED, BizExceptionCodeEnum.permissionDenied);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPlatformAdmin() {
|
||||
return getCurrentUserDto().getRole() == User.Role.Admin;
|
||||
private Set<Long> currentUserGroupIds() {
|
||||
return sysGroupApplicationService.getGroupListByUserId(getCurrentUserDto().getId()).stream()
|
||||
.filter(group -> !GroupEnum.DEFAULT_GROUP.getCode().equals(group.getCode()))
|
||||
.map(SysGroup::getId)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private UserDto getCurrentUserDto() {
|
||||
|
||||
@@ -22,6 +22,7 @@ const CustomFormModal: React.FC<PropsWithChildren<CustomFormModalProps>> = ({
|
||||
onCancel,
|
||||
onConfirm,
|
||||
okDisabled,
|
||||
skipFormValidation,
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
@@ -45,6 +46,7 @@ const CustomFormModal: React.FC<PropsWithChildren<CustomFormModalProps>> = ({
|
||||
form={form}
|
||||
okText={okText}
|
||||
disabled={okDisabled}
|
||||
skipFormValidation={skipFormValidation}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -14,18 +14,24 @@ const SubmitButton: React.FC<SubmitButtonProps> = ({
|
||||
okText,
|
||||
onConfirm,
|
||||
disabled,
|
||||
skipFormValidation = false,
|
||||
}) => {
|
||||
const [submittable, setSubmittable] = useState<boolean>(false);
|
||||
const [submittable, setSubmittable] = useState<boolean>(skipFormValidation);
|
||||
|
||||
// Watch all values
|
||||
const values = Form.useWatch([], { form, preserve: true });
|
||||
|
||||
useEffect(() => {
|
||||
if (skipFormValidation) {
|
||||
setSubmittable(true);
|
||||
return;
|
||||
}
|
||||
|
||||
form
|
||||
.validateFields({ validateOnly: true })
|
||||
.then(() => setSubmittable(true))
|
||||
.catch(() => setSubmittable(false));
|
||||
}, [form, values]);
|
||||
}, [form, values, skipFormValidation]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
|
||||
@@ -46,6 +46,8 @@ const UserAuthModal: React.FC<UserAuthModalProps> = ({
|
||||
onCancel,
|
||||
}) => {
|
||||
const { hasPermission } = useModel('menuModel');
|
||||
const canBindRole = hasPermission('user_manage_bind_role');
|
||||
const canBindGroup = hasPermission('user_manage_bind_group');
|
||||
// 如果是普通用户,默认显示用户组 tab;否则显示角色 tab
|
||||
const [activeTab, setActiveTab] = useState<TabKey>('role');
|
||||
// 创建一个空的 Form 实例,用于 CustomFormModal(不使用表单功能)
|
||||
@@ -114,9 +116,13 @@ const UserAuthModal: React.FC<UserAuthModalProps> = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setActiveTab(role === UserRoleEnum.User ? 'group' : 'role');
|
||||
setActiveTab(
|
||||
role === UserRoleEnum.User || !hasPermission('user_manage_bind_role')
|
||||
? 'group'
|
||||
: 'role',
|
||||
);
|
||||
// 如果不是普通用户,才查询角色列表
|
||||
if (role !== UserRoleEnum.User) {
|
||||
if (role !== UserRoleEnum.User && canBindRole) {
|
||||
// 查询角色列表
|
||||
runGetRoleList();
|
||||
// 查询用户绑定的角色列表
|
||||
@@ -136,7 +142,7 @@ const UserAuthModal: React.FC<UserAuthModalProps> = ({
|
||||
setGroupLoading(false);
|
||||
setRoleLoading(false);
|
||||
}
|
||||
}, [open, targetId, role]);
|
||||
}, [open, targetId, role, canBindRole, hasPermission]);
|
||||
|
||||
// 处理角色选择变化
|
||||
const handleRoleChange = (checkedValues: number[]) => {
|
||||
@@ -151,7 +157,7 @@ const UserAuthModal: React.FC<UserAuthModalProps> = ({
|
||||
// 提交数据
|
||||
const handlerSubmit = async () => {
|
||||
// 如果不是普通用户,需要同时提交角色和用户组
|
||||
if (role !== UserRoleEnum.User) {
|
||||
if (role !== UserRoleEnum.User && canBindRole) {
|
||||
setRoleLoading(true);
|
||||
await runBindRole({
|
||||
userId: targetId,
|
||||
@@ -161,12 +167,14 @@ const UserAuthModal: React.FC<UserAuthModalProps> = ({
|
||||
}
|
||||
|
||||
// 用户组总是需要提交
|
||||
setGroupLoading(true);
|
||||
await runBindGroup({
|
||||
userId: targetId,
|
||||
groupIds: selectedGroupIds,
|
||||
});
|
||||
setGroupLoading(false);
|
||||
if (canBindGroup) {
|
||||
setGroupLoading(true);
|
||||
await runBindGroup({
|
||||
userId: targetId,
|
||||
groupIds: selectedGroupIds,
|
||||
});
|
||||
setGroupLoading(false);
|
||||
}
|
||||
onCancel();
|
||||
};
|
||||
|
||||
@@ -298,6 +306,7 @@ const UserAuthModal: React.FC<UserAuthModalProps> = ({
|
||||
loading={loading}
|
||||
onCancel={onCancel}
|
||||
onConfirm={handlerSubmit}
|
||||
skipFormValidation
|
||||
okDisabled={
|
||||
activeTab === 'role'
|
||||
? !hasPermission('user_manage_bind_role')
|
||||
|
||||
@@ -34,6 +34,7 @@ const UserFormModal: React.FC<UserFormModalProps> = ({
|
||||
form.setFieldsValue(record);
|
||||
} else {
|
||||
form.resetFields();
|
||||
form.setFieldsValue({ role: UserRoleEnum.User });
|
||||
}
|
||||
}
|
||||
}, [open, isEdit, record, form]);
|
||||
@@ -50,6 +51,7 @@ const UserFormModal: React.FC<UserFormModalProps> = ({
|
||||
} else {
|
||||
await apiAddSystemUser({
|
||||
...values,
|
||||
role: UserRoleEnum.User,
|
||||
});
|
||||
}
|
||||
onSuccess(isEdit);
|
||||
@@ -195,12 +197,14 @@ const UserFormModal: React.FC<UserFormModalProps> = ({
|
||||
<Form.Item
|
||||
label={dict('PC.Pages.UserManage.UserFormModal.userType')}
|
||||
name="role"
|
||||
initialValue={UserRoleEnum.Admin}
|
||||
initialValue={UserRoleEnum.User}
|
||||
>
|
||||
<Radio.Group>
|
||||
<Radio value={UserRoleEnum.Admin}>
|
||||
{dict('PC.Pages.UserManage.UserFormModal.admin')}
|
||||
</Radio>
|
||||
{isEdit && (
|
||||
<Radio value={UserRoleEnum.Admin}>
|
||||
{dict('PC.Pages.UserManage.UserFormModal.admin')}
|
||||
</Radio>
|
||||
)}
|
||||
<Radio value={UserRoleEnum.User}>
|
||||
{dict('PC.Pages.UserManage.UserFormModal.normalUser')}
|
||||
</Radio>
|
||||
|
||||
@@ -161,8 +161,10 @@ const UserManage: React.FC = () => {
|
||||
key: 'auth',
|
||||
label: dict('PC.Pages.UserManage.Index.auth'),
|
||||
disabled:
|
||||
!hasPermissionByMenuCode('user_manage', 'user_manage_bind_role') &&
|
||||
!hasPermissionByMenuCode('user_manage', 'user_manage_bind_group'),
|
||||
record.role === UserRoleEnum.Admin
|
||||
? !hasPermissionByMenuCode('user_manage', 'user_manage_bind_role') &&
|
||||
!hasPermissionByMenuCode('user_manage', 'user_manage_bind_group')
|
||||
: !hasPermissionByMenuCode('user_manage', 'user_manage_bind_group'),
|
||||
onClick: handleAuth,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -188,6 +188,8 @@ export interface CustomFormModalProps {
|
||||
onConfirm: () => void;
|
||||
// 确定按钮是否禁用
|
||||
okDisabled?: boolean;
|
||||
// 非表单场景跳过 Form 校验,仅由 okDisabled 控制按钮状态
|
||||
skipFormValidation?: boolean;
|
||||
}
|
||||
|
||||
// Form.Item 验证rule
|
||||
@@ -456,6 +458,8 @@ export interface SubmitButtonProps {
|
||||
onConfirm: () => void;
|
||||
// 确定按钮是否禁用
|
||||
disabled?: boolean;
|
||||
// 非表单场景跳过 Form 校验,仅由 disabled 控制按钮状态
|
||||
skipFormValidation?: boolean;
|
||||
}
|
||||
|
||||
// 上传文件信息
|
||||
|
||||
Reference in New Issue
Block a user