支持单位授权与客户端限制
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.xspaceagi.system.application.dto.permission;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
@@ -20,6 +21,15 @@ public class SysGroupAddDto implements Serializable {
|
||||
@Schema(description = "最大用户数")
|
||||
private Integer maxUserCount;
|
||||
|
||||
@Schema(description = "最大客户端数,-1表示不限制")
|
||||
private Integer maxClientCount;
|
||||
|
||||
@Schema(description = "授权开关:1-已授权,0-未授权")
|
||||
private Integer authEnabled;
|
||||
|
||||
@Schema(description = "授权到期时间,空表示不过期")
|
||||
private Date expireTime;
|
||||
|
||||
@Schema(description = "来源,1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
|
||||
@@ -31,6 +31,15 @@ public class SysGroupDto implements Serializable {
|
||||
@Schema(description = "最大用户数")
|
||||
private Integer maxUserCount;
|
||||
|
||||
@Schema(description = "最大客户端数,-1表示不限制")
|
||||
private Integer maxClientCount;
|
||||
|
||||
@Schema(description = "授权开关:1-已授权,0-未授权")
|
||||
private Integer authEnabled;
|
||||
|
||||
@Schema(description = "授权到期时间,空表示不过期")
|
||||
private Date expireTime;
|
||||
|
||||
@Schema(description = "来源,1:系统内置 2:用户自定义")
|
||||
private Integer source;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class SysGroupUpdateDto implements Serializable {
|
||||
@@ -23,6 +24,15 @@ public class SysGroupUpdateDto implements Serializable {
|
||||
@Schema(description = "最大用户数")
|
||||
private Integer maxUserCount;
|
||||
|
||||
@Schema(description = "最大客户端数,-1表示不限制")
|
||||
private Integer maxClientCount;
|
||||
|
||||
@Schema(description = "授权开关:1-已授权,0-未授权")
|
||||
private Integer authEnabled;
|
||||
|
||||
@Schema(description = "授权到期时间,空表示不过期")
|
||||
private Date expireTime;
|
||||
|
||||
@Schema(description = "来源,1:系统内置 2:用户自定义", hidden = true)
|
||||
private Integer source;
|
||||
|
||||
|
||||
@@ -76,6 +76,16 @@ public interface SysGroupApplicationService {
|
||||
*/
|
||||
List<SysGroup> getEffectiveGroupListByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 查询用户可用于系统登录的已授权用户组(启用、授权开启、未过期)
|
||||
*/
|
||||
List<SysGroup> getAuthorizedGroupListForLogin(Long userId);
|
||||
|
||||
/**
|
||||
* 为用户选择一个可注册客户端的已授权用户组(同时满足客户端数量限制)
|
||||
*/
|
||||
SysGroup selectAuthorizedGroupForClient(Long userId, java.util.Map<Long, Long> clientCountByGroupId);
|
||||
|
||||
/**
|
||||
* 用户组绑定用户(全量覆盖)
|
||||
*/
|
||||
|
||||
@@ -3,13 +3,16 @@ package com.xspaceagi.system.application.service.impl;
|
||||
import com.xspaceagi.system.application.dto.TenantConfigDto;
|
||||
import com.xspaceagi.system.application.dto.UserDto;
|
||||
import com.xspaceagi.system.application.service.AuthService;
|
||||
import com.xspaceagi.system.application.service.SysGroupApplicationService;
|
||||
import com.xspaceagi.system.application.service.UserApplicationService;
|
||||
import com.xspaceagi.system.infra.dao.entity.User;
|
||||
import com.xspaceagi.system.infra.rpc.WeChatMpService;
|
||||
import com.xspaceagi.system.infra.verify.VerifyCodeSendAndCheckService;
|
||||
import com.xspaceagi.system.spec.common.RequestContext;
|
||||
import com.xspaceagi.system.spec.enums.CodeTypeEnum;
|
||||
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
|
||||
import com.xspaceagi.system.spec.exception.BizException;
|
||||
import com.xspaceagi.system.spec.exception.BizExceptionCodeEnum;
|
||||
import com.xspaceagi.system.spec.utils.I18nUtil;
|
||||
import com.xspaceagi.system.spec.utils.JwtUtils;
|
||||
import com.xspaceagi.system.spec.utils.RedisUtil;
|
||||
@@ -28,6 +31,9 @@ public class AuthServiceImpl implements AuthService {
|
||||
@Resource
|
||||
private UserApplicationService userApplicationService;
|
||||
|
||||
@Resource
|
||||
private SysGroupApplicationService sysGroupApplicationService;
|
||||
|
||||
@Resource
|
||||
private VerifyCodeSendAndCheckService verifyCodeSendAndCheckService;
|
||||
|
||||
@@ -66,9 +72,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
userDto.setEmail(email);
|
||||
userApplicationService.add(userDto);
|
||||
}
|
||||
if (userDto.getStatus() == User.Status.Disabled || userDto.getStatus() == User.Status.Deleted) {
|
||||
throw new BizException(I18nUtil.systemMessage("Backend.Auth.Login.AccountDisabled"));
|
||||
}
|
||||
validateLoginUser(userDto);
|
||||
updateLastLoginTime(userDto);
|
||||
return createToken(userDto, UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
@@ -87,13 +91,23 @@ public class AuthServiceImpl implements AuthService {
|
||||
userDto.setPhone(phone);
|
||||
userApplicationService.add(userDto);
|
||||
}
|
||||
if (userDto.getStatus() == User.Status.Disabled) {
|
||||
throw new BizException(I18nUtil.systemMessage("Backend.Auth.Login.AccountDisabled"));
|
||||
}
|
||||
validateLoginUser(userDto);
|
||||
updateLastLoginTime(userDto);
|
||||
return createToken(userDto, UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
|
||||
private void validateLoginUser(UserDto userDto) {
|
||||
if (userDto.getStatus() == User.Status.Disabled || userDto.getStatus() == User.Status.Deleted) {
|
||||
throw new BizException(I18nUtil.systemMessage("Backend.Auth.Login.AccountDisabled"));
|
||||
}
|
||||
if (userDto.getRole() == User.Role.Admin) {
|
||||
return;
|
||||
}
|
||||
if (sysGroupApplicationService.getAuthorizedGroupListForLogin(userDto.getId()).isEmpty()) {
|
||||
throw BizException.of(ErrorCodeEnum.PERMISSION_DENIED, BizExceptionCodeEnum.systemGroupAuthorizationUnavailable);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLastLoginTime(UserDto userDto) {
|
||||
UserDto update = new UserDto();
|
||||
update.setId(userDto.getId());
|
||||
@@ -105,6 +119,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
}
|
||||
|
||||
public String createToken(UserDto userDto, String clientId) {
|
||||
validateLoginUser(userDto);
|
||||
//过期token检查
|
||||
Map<String, Object> map = redisUtil.hashGetAll("user-token:" + userDto.getId());
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
@@ -127,6 +142,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
Assert.notNull(emailOrPhone, "emailOrPhone must be non-null");
|
||||
UserDto userDto = userApplicationService.queryUserByPhoneOrEmailWithPassword(emailOrPhone, password);
|
||||
if (userDto != null) {
|
||||
validateLoginUser(userDto);
|
||||
updateLastLoginTime(userDto);
|
||||
return createToken(userDto, UUID.randomUUID().toString().replace("-", ""));
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package com.xspaceagi.system.application.service.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -23,6 +25,7 @@ import com.xspaceagi.system.domain.model.GroupBindMenuModel;
|
||||
import com.xspaceagi.system.domain.model.MenuNode;
|
||||
import com.xspaceagi.system.domain.model.SortIndex;
|
||||
import com.xspaceagi.system.domain.service.SysGroupDomainService;
|
||||
import com.xspaceagi.system.domain.service.impl.GroupAuthorizationPolicy;
|
||||
import com.xspaceagi.system.infra.dao.entity.SysDataPermission;
|
||||
import com.xspaceagi.system.infra.dao.entity.SysGroup;
|
||||
import com.xspaceagi.system.infra.dao.entity.User;
|
||||
@@ -141,6 +144,39 @@ public class SysGroupApplicationServiceImpl implements SysGroupApplicationServic
|
||||
: groupList.stream().filter(g -> StatusEnum.isEnabled(g.getStatus())).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysGroup> getAuthorizedGroupListForLogin(Long userId) {
|
||||
return filterAuthorizedGroupsForLogin(getEffectiveGroupListByUserId(userId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysGroup selectAuthorizedGroupForClient(Long userId, Map<Long, Long> clientCountByGroupId) {
|
||||
return selectAuthorizedGroupForClient(getEffectiveGroupListByUserId(userId), clientCountByGroupId);
|
||||
}
|
||||
|
||||
List<SysGroup> filterAuthorizedGroupsForLogin(List<SysGroup> groups) {
|
||||
if (CollectionUtils.isEmpty(groups)) {
|
||||
return List.of();
|
||||
}
|
||||
Date now = new Date();
|
||||
return groups.stream()
|
||||
.filter(group -> GroupAuthorizationPolicy.evaluate(group, -1, now).allowed())
|
||||
.toList();
|
||||
}
|
||||
|
||||
SysGroup selectAuthorizedGroupForClient(List<SysGroup> groups, Map<Long, Long> clientCountByGroupId) {
|
||||
if (CollectionUtils.isEmpty(groups)) {
|
||||
return null;
|
||||
}
|
||||
Date now = new Date();
|
||||
Map<Long, Long> counts = clientCountByGroupId == null ? Map.of() : clientCountByGroupId;
|
||||
return groups.stream()
|
||||
.filter(group -> group.getId() != null)
|
||||
.filter(group -> GroupAuthorizationPolicy.evaluate(group, counts.getOrDefault(group.getId(), 0L), now).allowed())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private List<Long> getSubscriptionPlanGroupIds(Long userId) {
|
||||
try {
|
||||
UserSubscriptionDTO subscription = subscriptionRpcService.getUserCurrentSystemSubscription(userId);
|
||||
|
||||
Reference in New Issue
Block a user