Merge remote-tracking branch 'base-version/main' into dev
This commit is contained in:
@@ -31,6 +31,11 @@
|
||||
<artifactId>zt-spring-boot-starter-biz-data-permission</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
<artifactId>zt-spring-boot-starter-biz-tenant</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>com.zt.plat</groupId>
|
||||
|
||||
@@ -4,11 +4,15 @@ import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.zt.plat.framework.common.pojo.CompanyDeptInfo;
|
||||
import com.zt.plat.framework.security.core.LoginUser;
|
||||
import com.zt.plat.framework.tenant.core.context.CompanyContextHolder;
|
||||
import com.zt.plat.framework.web.core.util.WebFrameworkUtils;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -22,43 +26,85 @@ import static com.zt.plat.framework.security.core.util.SecurityFrameworkUtils.ge
|
||||
public class BusinessDeptHandleUtil {
|
||||
public static Set<CompanyDeptInfo> getBelongCompanyAndDept(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
String companyId = request.getHeader("visit-company-id");
|
||||
String deptId = request.getHeader("visit-dept-id");
|
||||
LoginUser loginUser = Optional.ofNullable(getLoginUser()).orElse(new LoginUser().setInfo(new HashMap<>()));
|
||||
Set<CompanyDeptInfo> companyDeptSet = JSONUtil.parseArray(loginUser.getInfo().getOrDefault(LoginUser.INFO_KEY_COMPANY_DEPT_SET, "[]")).stream()
|
||||
String companyIdHeader = request.getHeader(WebFrameworkUtils.HEADER_VISIT_COMPANY_ID);
|
||||
String deptIdHeader = request.getHeader(WebFrameworkUtils.HEADER_VISIT_DEPT_ID);
|
||||
|
||||
LoginUser currentLoginUser = getLoginUser();
|
||||
Map<String, String> extraInfo = Optional.ofNullable(currentLoginUser)
|
||||
.map(LoginUser::getInfo)
|
||||
.orElseGet(HashMap::new);
|
||||
if (currentLoginUser != null && currentLoginUser.getInfo() == null) {
|
||||
currentLoginUser.setInfo(extraInfo);
|
||||
}
|
||||
|
||||
Set<CompanyDeptInfo> companyDeptSet = JSONUtil.parseArray(extraInfo.getOrDefault(LoginUser.INFO_KEY_COMPANY_DEPT_SET, "[]")).stream()
|
||||
.map(obj -> JSONUtil.toBean((JSONObject) obj, CompanyDeptInfo.class))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 1. 有 companyId
|
||||
if (companyId != null && !companyId.isBlank()) {
|
||||
if (companyIdHeader != null && !companyIdHeader.isBlank()) {
|
||||
// 根据请求头中的公司 ID 过滤出当前用户的公司部门信息
|
||||
Set<CompanyDeptInfo> companyDeptSetByCompanyId = companyDeptSet.stream().filter(companyDeptInfo -> companyDeptInfo.getCompanyId().toString().equals(companyId)).collect(Collectors.toSet());
|
||||
Set<CompanyDeptInfo> companyDeptSetByCompanyId = companyDeptSet.stream()
|
||||
.filter(companyDeptInfo -> companyDeptInfo.getCompanyId().toString().equals(companyIdHeader))
|
||||
.collect(Collectors.toSet());
|
||||
if (companyDeptSetByCompanyId.isEmpty()) {
|
||||
// 当前公司下没有部门
|
||||
CompanyDeptInfo data = new CompanyDeptInfo();
|
||||
data.setCompanyId(Long.valueOf(companyId));
|
||||
data.setCompanyId(Long.valueOf(companyIdHeader));
|
||||
data.setDeptId(0L);
|
||||
return new HashSet<>(singleton(data));
|
||||
}
|
||||
// 如果有 deptId,校验其是否属于该 companyId
|
||||
if (deptId != null) {
|
||||
boolean valid = companyDeptSetByCompanyId.stream().anyMatch(info -> String.valueOf(info.getDeptId()).equals(deptId));
|
||||
if (deptIdHeader != null) {
|
||||
boolean valid = companyDeptSetByCompanyId.stream().anyMatch(info -> String.valueOf(info.getDeptId()).equals(deptIdHeader));
|
||||
if (!valid) {
|
||||
return null;
|
||||
}else{
|
||||
} else {
|
||||
// 部门存在,放行
|
||||
return new HashSet<>();
|
||||
}
|
||||
}
|
||||
if (companyDeptSetByCompanyId.size() == 1) {
|
||||
CompanyDeptInfo singleCompanyDept = companyDeptSetByCompanyId.iterator().next();
|
||||
if (applyAutoSelection(currentLoginUser, request, singleCompanyDept)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
return companyDeptSetByCompanyId;
|
||||
}
|
||||
// 2. 没有公司信息,尝试唯一性自动推断
|
||||
// 如果当前用户下只有一个公司和部门的对于关系
|
||||
if (companyDeptSet.size() == 1) {
|
||||
CompanyDeptInfo companyDeptInfo = companyDeptSet.iterator().next();
|
||||
if (applyAutoSelection(currentLoginUser, request, companyDeptInfo)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return new HashSet<>(singleton(companyDeptInfo));
|
||||
} else {
|
||||
return companyDeptSet;
|
||||
}
|
||||
return companyDeptSet;
|
||||
}
|
||||
|
||||
private static boolean applyAutoSelection(LoginUser loginUser, HttpServletRequest request, CompanyDeptInfo info) {
|
||||
if (info == null || info.getCompanyId() == null || info.getCompanyId() <= 0
|
||||
|| info.getDeptId() == null || info.getDeptId() <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (loginUser != null) {
|
||||
loginUser.setVisitCompanyId(info.getCompanyId());
|
||||
loginUser.setVisitCompanyName(info.getCompanyName());
|
||||
loginUser.setVisitDeptId(info.getDeptId());
|
||||
loginUser.setVisitDeptName(info.getDeptName());
|
||||
}
|
||||
request.setAttribute(WebFrameworkUtils.HEADER_VISIT_COMPANY_ID, info.getCompanyId());
|
||||
if (info.getCompanyName() != null) {
|
||||
request.setAttribute(WebFrameworkUtils.HEADER_VISIT_COMPANY_NAME, info.getCompanyName());
|
||||
}
|
||||
request.setAttribute(WebFrameworkUtils.HEADER_VISIT_DEPT_ID, info.getDeptId());
|
||||
if (info.getDeptName() != null) {
|
||||
request.setAttribute(WebFrameworkUtils.HEADER_VISIT_DEPT_NAME, info.getDeptName());
|
||||
}
|
||||
CompanyContextHolder.setIgnore(false);
|
||||
CompanyContextHolder.setCompanyId(info.getCompanyId());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,30 +20,68 @@ public class CompanyVisitContextInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
// 解析 header 并设置 visitCompanyId
|
||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||
|
||||
Long companyId = WebFrameworkUtils.getCompanyId(request);
|
||||
// 优先使用请求头上的公司信息,若缺失则回退到请求属性或当前登录用户已缓存的访问公司
|
||||
if (companyId == null || companyId <= 0L) {
|
||||
Long attrCompanyId = resolveLong(request.getAttribute(WebFrameworkUtils.HEADER_VISIT_COMPANY_ID));
|
||||
if (attrCompanyId != null && attrCompanyId > 0L) {
|
||||
companyId = attrCompanyId;
|
||||
} else if (loginUser != null && loginUser.getVisitCompanyId() != null && loginUser.getVisitCompanyId() > 0L) {
|
||||
companyId = loginUser.getVisitCompanyId();
|
||||
}
|
||||
}
|
||||
|
||||
String companyName = WebFrameworkUtils.getCompanyName(request);
|
||||
if (companyId <= 0L) {
|
||||
// 如果没有设置 companyId,则忽略
|
||||
if (companyName == null || companyName.isEmpty()) {
|
||||
Object attrCompanyName = request.getAttribute(WebFrameworkUtils.HEADER_VISIT_COMPANY_NAME);
|
||||
if (attrCompanyName instanceof String) {
|
||||
companyName = (String) attrCompanyName;
|
||||
} else if (loginUser != null) {
|
||||
companyName = loginUser.getVisitCompanyName();
|
||||
}
|
||||
}
|
||||
|
||||
Long deptId = WebFrameworkUtils.getDeptId(request);
|
||||
// 部门信息同样遵循“请求头 -> 请求属性 -> 登录缓存”的回退顺序
|
||||
if (deptId == null || deptId <= 0L) {
|
||||
Long attrDeptId = resolveLong(request.getAttribute(WebFrameworkUtils.HEADER_VISIT_DEPT_ID));
|
||||
if (attrDeptId != null && attrDeptId > 0L) {
|
||||
deptId = attrDeptId;
|
||||
} else if (loginUser != null && loginUser.getVisitDeptId() != null && loginUser.getVisitDeptId() > 0L) {
|
||||
deptId = loginUser.getVisitDeptId();
|
||||
}
|
||||
}
|
||||
|
||||
String deptName = WebFrameworkUtils.getDeptName(request);
|
||||
if (deptName == null || deptName.isEmpty()) {
|
||||
Object attrDeptName = request.getAttribute(WebFrameworkUtils.HEADER_VISIT_DEPT_NAME);
|
||||
if (attrDeptName instanceof String) {
|
||||
deptName = (String) attrDeptName;
|
||||
} else if (loginUser != null) {
|
||||
deptName = loginUser.getVisitDeptName();
|
||||
}
|
||||
}
|
||||
|
||||
if (companyId == null || companyId <= 0L) {
|
||||
CompanyContextHolder.setIgnore(true);
|
||||
return true;
|
||||
}
|
||||
Long deptId = WebFrameworkUtils.getDeptId(request);
|
||||
String deptName = WebFrameworkUtils.getDeptName(request);
|
||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||
|
||||
CompanyContextHolder.setIgnore(false);
|
||||
CompanyContextHolder.setCompanyId(companyId);
|
||||
if (loginUser == null) {
|
||||
return true;
|
||||
}
|
||||
if (deptId > 0L) {
|
||||
|
||||
// 同步最新的访问公司/部门到登录用户对象,供后续数据权限及上下文读取
|
||||
loginUser.setVisitCompanyId(companyId);
|
||||
loginUser.setVisitCompanyName(companyName);
|
||||
if (deptId != null && deptId > 0L) {
|
||||
loginUser.setVisitDeptId(deptId);
|
||||
loginUser.setVisitDeptName(deptName);
|
||||
}
|
||||
// if (!securityFrameworkService.hasAnyPermissions(PERMISSION)) {
|
||||
// throw exception0(GlobalErrorCodeConstants.FORBIDDEN.getCode(), "您无权切换部门");
|
||||
// }
|
||||
loginUser.setVisitCompanyId(companyId);
|
||||
loginUser.setVisitCompanyName(companyName);
|
||||
CompanyContextHolder.setCompanyId(companyId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -55,4 +93,18 @@ public class CompanyVisitContextInterceptor implements HandlerInterceptor {
|
||||
loginUser.setVisitCompanyId(0L);
|
||||
}
|
||||
}
|
||||
|
||||
private Long resolveLong(Object value) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).longValue();
|
||||
}
|
||||
if (value instanceof String) {
|
||||
try {
|
||||
return Long.parseLong(((String) value).trim());
|
||||
} catch (NumberFormatException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user