AuthzService.java
5.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package com.xly.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* xlyAi 侧授权层 —— 表单级白名单(架构 §7)。
*
* <p>后端逐用户表单权限被关(只验登录 + 租户 + 行级),所以在 agent 侧按用户实际授权把可碰的
* 表单/菜单限制住。数据源与后端一致(`sysjurisdiction`,即 `getsAuthsIdNew` 的逻辑)——不新造。
*
* <p>管理员(sysadmin/admin) = 全部权限(返回 null);否则 = 该用户有权的 id 集合(菜单/表单/按钮,
* 由 `sysjurisdiction.sKey` 按 '-' 拆出)。当前本地 dev-login 以 admin 身份运行,因此实际全通;
* 生产透传用户 token 时即按各用户真实授权收紧。Read / Query / Write 共用此边界。
*/
@Service
public class AuthzService {
private final JdbcTemplate jdbc;
@Value("${erp.dev-login.username:admin}")
private String devUserNo;
@Value("${erp.dev-login.brand:1111111111}")
private String devBrand;
@Value("${erp.dev-login.subsidiary:1111111111}")
private String devSub;
@Value("${erp.dev-login.usertype:sysadmin}")
private String devUserType;
@Value("${erp.dev-login.userid:}")
private String devUserIdOverride;
public AuthzService(JdbcTemplate jdbc) {
this.jdbc = jdbc;
}
/**
* 构造 dev-login(本地开发)身份:token 为空 → ErpClient 回退 dev-login;权限集按 dev 账号解析
* (admin → null = 全部)。
*/
public com.xly.agent.AgentIdentity devIdentity() {
String uid = devUserIdOverride != null && !devUserIdOverride.isBlank() ? devUserIdOverride : resolveDevUserId();
Set<String> granted = grantedIds(uid, devUserType, devBrand, devSub);
return new com.xly.agent.AgentIdentity(null, uid, devBrand, granted);
}
/**
* 构造透传的真实用户身份:token = 用户浏览器里的 ERP 登录 token(转发给 ERP),权限集按该用户
* 真实授权({@code sAuthsId})解析。用于生产环境按各用户真实权限收紧。
*/
public com.xly.agent.AgentIdentity userIdentity(String token, String userId,
String brandsId, String subsidiaryId, String userType) {
Set<String> granted = grantedIds(userId, userType, brandsId, subsidiaryId);
return new com.xly.agent.AgentIdentity(token, userId, brandsId, granted);
}
/** null = 全部(管理员);否则 = 有权的 id 集合。 */
private Set<String> grantedIds(String userId, String userType, String brandsId, String subsidiaryId) {
if (isAdmin(userType)) {
return null; // 超管全部权限
}
Set<String> ids = new HashSet<>();
if (userId == null) {
return ids;
}
List<Map<String, Object>> rows;
Integer direct = safeCount(
"SELECT COUNT(*) FROM sysjurisdiction WHERE sBrandsId=? AND sSubsidiaryId=? AND sUserId=?",
brandsId, subsidiaryId, userId);
if (direct != null && direct > 0) {
rows = jdbc.queryForList(
"SELECT J.sKey AS sKey FROM sysjurisdiction J WHERE J.sBrandsId=? AND J.sSubsidiaryId=? AND J.sUserId=?",
brandsId, subsidiaryId, userId);
} else {
String groups = queryStr(
"SELECT GROUP_CONCAT(sJurisdictionClassifyId) FROM sftlogininfojurisdictiongroup " +
"WHERE sBrandsId=? AND sSubsidiaryId=? AND sParentId=? " +
"AND sJurisdictionClassifyId IN (SELECT sId FROM sisjurisdictionclassify WHERE bLogininfoShow=0)",
brandsId, subsidiaryId, userId);
if (groups == null || groups.isBlank()) {
return ids;
}
List<String> gl = Arrays.asList(groups.split(","));
String in = gl.stream().map(g -> "?").collect(Collectors.joining(","));
List<Object> args = new ArrayList<>();
args.add(brandsId);
args.add(subsidiaryId);
args.addAll(gl);
rows = jdbc.queryForList(
"SELECT J.sKey AS sKey FROM sysjurisdiction J WHERE J.sBrandsId=? AND J.sSubsidiaryId=? " +
"AND J.sJurisdictionClassifyId IN (" + in + ")", args.toArray());
}
for (Map<String, Object> r : rows) {
Object k = r.get("sKey");
if (k != null) {
for (String part : k.toString().split("-")) {
if (!part.isBlank()) {
ids.add(part);
}
}
}
}
return ids;
}
private String resolveDevUserId() {
return queryStr("SELECT sId FROM gdslogininfo WHERE sUserNo=? AND sBrandsId=? LIMIT 1", devUserNo, devBrand);
}
private boolean isAdmin(String userType) {
return userType != null && (userType.equalsIgnoreCase("sysadmin") || userType.equalsIgnoreCase("admin"));
}
private Integer safeCount(String sql, Object... args) {
try {
return jdbc.queryForObject(sql, Integer.class, args);
} catch (Exception e) {
return 0;
}
}
private String queryStr(String sql, Object... args) {
try {
List<Map<String, Object>> r = jdbc.queryForList(sql, args);
if (!r.isEmpty()) {
Object v = r.get(0).values().iterator().next();
return v == null ? null : v.toString();
}
} catch (Exception ignore) {
}
return null;
}
}