提交 | 用户 | 时间
|
e7c126
|
1 |
package com.iailab.module.system.service.permission; |
H |
2 |
|
|
3 |
import cn.hutool.core.collection.CollUtil; |
|
4 |
import cn.hutool.core.collection.CollectionUtil; |
|
5 |
import cn.hutool.core.util.ObjectUtil; |
|
6 |
import cn.hutool.extra.spring.SpringUtil; |
|
7 |
import com.iailab.framework.common.enums.CommonStatusEnum; |
|
8 |
import com.iailab.framework.common.pojo.PageResult; |
|
9 |
import com.iailab.framework.common.util.collection.CollectionUtils; |
|
10 |
import com.iailab.framework.common.util.object.BeanUtils; |
d9f9ba
|
11 |
import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX; |
e7c126
|
12 |
import com.iailab.module.system.controller.admin.permission.vo.role.RolePageReqVO; |
H |
13 |
import com.iailab.module.system.controller.admin.permission.vo.role.RoleSaveReqVO; |
|
14 |
import com.iailab.module.system.dal.dataobject.permission.RoleDO; |
|
15 |
import com.iailab.module.system.dal.mysql.permission.RoleMapper; |
|
16 |
import com.iailab.module.system.dal.redis.RedisKeyConstants; |
|
17 |
import com.iailab.module.system.enums.permission.DataScopeEnum; |
|
18 |
import com.iailab.module.system.enums.permission.RoleCodeEnum; |
|
19 |
import com.iailab.module.system.enums.permission.RoleTypeEnum; |
|
20 |
import com.google.common.annotations.VisibleForTesting; |
|
21 |
import com.mzt.logapi.context.LogRecordContext; |
|
22 |
import com.mzt.logapi.service.impl.DiffParseFunction; |
|
23 |
import com.mzt.logapi.starter.annotation.LogRecord; |
|
24 |
import lombok.extern.slf4j.Slf4j; |
|
25 |
import org.springframework.cache.annotation.CacheEvict; |
|
26 |
import org.springframework.cache.annotation.Cacheable; |
|
27 |
import org.springframework.stereotype.Service; |
|
28 |
import org.springframework.transaction.annotation.Transactional; |
|
29 |
import org.springframework.util.StringUtils; |
|
30 |
|
|
31 |
import javax.annotation.Resource; |
|
32 |
import java.util.*; |
|
33 |
|
|
34 |
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; |
|
35 |
import static com.iailab.framework.common.util.collection.CollectionUtils.convertMap; |
|
36 |
import static com.iailab.module.system.enums.ErrorCodeConstants.*; |
|
37 |
import static com.iailab.module.system.enums.LogRecordConstants.*; |
|
38 |
|
|
39 |
/** |
|
40 |
* 角色 Service 实现类 |
|
41 |
* |
|
42 |
* @author iailab |
|
43 |
*/ |
|
44 |
@Service |
|
45 |
@Slf4j |
|
46 |
public class RoleServiceImpl implements RoleService { |
|
47 |
|
|
48 |
@Resource |
|
49 |
private PermissionService permissionService; |
|
50 |
|
|
51 |
@Resource |
|
52 |
private RoleMapper roleMapper; |
|
53 |
|
|
54 |
@Override |
|
55 |
@Transactional(rollbackFor = Exception.class) |
|
56 |
@LogRecord(type = SYSTEM_ROLE_TYPE, subType = SYSTEM_ROLE_CREATE_SUB_TYPE, bizNo = "{{#role.id}}", |
|
57 |
success = SYSTEM_ROLE_CREATE_SUCCESS) |
|
58 |
public Long createRole(RoleSaveReqVO createReqVO, Integer type) { |
|
59 |
// 1. 校验角色 |
|
60 |
validateRoleDuplicate(createReqVO.getName(), createReqVO.getCode(), null); |
|
61 |
|
|
62 |
// 2. 插入到数据库 |
|
63 |
RoleDO role = BeanUtils.toBean(createReqVO, RoleDO.class) |
|
64 |
.setType(ObjectUtil.defaultIfNull(type, RoleTypeEnum.CUSTOM.getType())) |
|
65 |
.setStatus(CommonStatusEnum.ENABLE.getStatus()) |
|
66 |
.setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限 |
|
67 |
roleMapper.insert(role); |
|
68 |
|
|
69 |
// 3. 记录操作日志上下文 |
|
70 |
LogRecordContext.putVariable("role", role); |
|
71 |
return role.getId(); |
|
72 |
} |
|
73 |
|
|
74 |
@Override |
|
75 |
@CacheEvict(value = RedisKeyConstants.ROLE, key = "#updateReqVO.id") |
|
76 |
@LogRecord(type = SYSTEM_ROLE_TYPE, subType = SYSTEM_ROLE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", |
|
77 |
success = SYSTEM_ROLE_UPDATE_SUCCESS) |
|
78 |
public void updateRole(RoleSaveReqVO updateReqVO) { |
|
79 |
// 1.1 校验是否可以更新 |
|
80 |
RoleDO role = validateRoleForUpdate(updateReqVO.getId()); |
|
81 |
// 1.2 校验角色的唯一字段是否重复 |
|
82 |
validateRoleDuplicate(updateReqVO.getName(), updateReqVO.getCode(), updateReqVO.getId()); |
|
83 |
|
|
84 |
// 2. 更新到数据库 |
|
85 |
RoleDO updateObj = BeanUtils.toBean(updateReqVO, RoleDO.class); |
|
86 |
roleMapper.updateById(updateObj); |
|
87 |
|
|
88 |
// 3. 记录操作日志上下文 |
|
89 |
LogRecordContext.putVariable("role", role); |
|
90 |
} |
|
91 |
|
|
92 |
@Override |
|
93 |
@CacheEvict(value = RedisKeyConstants.ROLE, key = "#id") |
|
94 |
public void updateRoleDataScope(Long id, Integer dataScope, Set<Long> dataScopeDeptIds) { |
|
95 |
// 校验是否可以更新 |
|
96 |
validateRoleForUpdate(id); |
|
97 |
|
|
98 |
// 更新数据范围 |
|
99 |
RoleDO updateObject = new RoleDO(); |
|
100 |
updateObject.setId(id); |
|
101 |
updateObject.setDataScope(dataScope); |
|
102 |
updateObject.setDataScopeDeptIds(dataScopeDeptIds); |
|
103 |
roleMapper.updateById(updateObject); |
|
104 |
} |
|
105 |
|
|
106 |
@Override |
|
107 |
@Transactional(rollbackFor = Exception.class) |
|
108 |
@CacheEvict(value = RedisKeyConstants.ROLE, key = "#id") |
|
109 |
@LogRecord(type = SYSTEM_ROLE_TYPE, subType = SYSTEM_ROLE_DELETE_SUB_TYPE, bizNo = "{{#id}}", |
|
110 |
success = SYSTEM_ROLE_DELETE_SUCCESS) |
|
111 |
public void deleteRole(Long id) { |
|
112 |
// 1. 校验是否可以更新 |
|
113 |
RoleDO role = validateRoleForUpdate(id); |
|
114 |
|
|
115 |
// 2.1 标记删除 |
|
116 |
roleMapper.deleteById(id); |
|
117 |
// 2.2 删除相关数据 |
|
118 |
permissionService.processRoleDeleted(id); |
|
119 |
|
|
120 |
// 3. 记录操作日志上下文 |
|
121 |
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(role, RoleSaveReqVO.class)); |
|
122 |
LogRecordContext.putVariable("role", role); |
|
123 |
} |
|
124 |
|
|
125 |
/** |
|
126 |
* 校验角色的唯一字段是否重复 |
|
127 |
* |
|
128 |
* 1. 是否存在相同名字的角色 |
|
129 |
* 2. 是否存在相同编码的角色 |
|
130 |
* |
|
131 |
* @param name 角色名字 |
|
132 |
* @param code 角色额编码 |
|
133 |
* @param id 角色编号 |
|
134 |
*/ |
|
135 |
@VisibleForTesting |
|
136 |
void validateRoleDuplicate(String name, String code, Long id) { |
|
137 |
// 0. 超级管理员,不允许创建 |
|
138 |
if (RoleCodeEnum.isSuperAdmin(code)) { |
|
139 |
throw exception(ROLE_ADMIN_CODE_ERROR, code); |
|
140 |
} |
|
141 |
// 1. 该 name 名字被其它角色所使用 |
|
142 |
RoleDO role = roleMapper.selectByName(name); |
|
143 |
if (role != null && !role.getId().equals(id)) { |
|
144 |
throw exception(ROLE_NAME_DUPLICATE, name); |
|
145 |
} |
|
146 |
// 2. 是否存在相同编码的角色 |
|
147 |
if (!StringUtils.hasText(code)) { |
|
148 |
return; |
|
149 |
} |
|
150 |
// 该 code 编码被其它角色所使用 |
|
151 |
role = roleMapper.selectByCode(code); |
|
152 |
if (role != null && !role.getId().equals(id)) { |
|
153 |
throw exception(ROLE_CODE_DUPLICATE, code); |
|
154 |
} |
|
155 |
} |
|
156 |
|
|
157 |
/** |
|
158 |
* 校验角色是否可以被更新 |
|
159 |
* |
|
160 |
* @param id 角色编号 |
|
161 |
*/ |
|
162 |
@VisibleForTesting |
|
163 |
RoleDO validateRoleForUpdate(Long id) { |
|
164 |
RoleDO role = roleMapper.selectById(id); |
|
165 |
if (role == null) { |
|
166 |
throw exception(ROLE_NOT_EXISTS); |
|
167 |
} |
|
168 |
// 内置角色,不允许删除 |
|
169 |
if (RoleTypeEnum.SYSTEM.getType().equals(role.getType())) { |
|
170 |
throw exception(ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE); |
|
171 |
} |
|
172 |
return role; |
|
173 |
} |
|
174 |
|
|
175 |
@Override |
|
176 |
public RoleDO getRole(Long id) { |
|
177 |
return roleMapper.selectById(id); |
|
178 |
} |
|
179 |
|
|
180 |
@Override |
|
181 |
@Cacheable(value = RedisKeyConstants.ROLE, key = "#id", |
|
182 |
unless = "#result == null") |
|
183 |
public RoleDO getRoleFromCache(Long id) { |
|
184 |
return roleMapper.selectById(id); |
|
185 |
} |
|
186 |
|
|
187 |
|
|
188 |
@Override |
|
189 |
public List<RoleDO> getRoleListByStatus(Collection<Integer> statuses) { |
|
190 |
return roleMapper.selectListByStatus(statuses); |
|
191 |
} |
|
192 |
|
|
193 |
@Override |
|
194 |
public List<RoleDO> getRoleList() { |
|
195 |
return roleMapper.selectList(); |
|
196 |
} |
|
197 |
|
|
198 |
@Override |
|
199 |
public List<RoleDO> getRoleList(Collection<Long> ids) { |
|
200 |
if (CollectionUtil.isEmpty(ids)) { |
|
201 |
return Collections.emptyList(); |
|
202 |
} |
|
203 |
return roleMapper.selectBatchIds(ids); |
|
204 |
} |
|
205 |
|
|
206 |
@Override |
|
207 |
public List<RoleDO> getRoleListFromCache(Collection<Long> ids) { |
|
208 |
if (CollectionUtil.isEmpty(ids)) { |
|
209 |
return Collections.emptyList(); |
|
210 |
} |
|
211 |
// 这里采用 for 循环从缓存中获取,主要考虑 Spring CacheManager 无法批量操作的问题 |
|
212 |
RoleServiceImpl self = getSelf(); |
|
213 |
return CollectionUtils.convertList(ids, self::getRoleFromCache); |
|
214 |
} |
|
215 |
|
|
216 |
@Override |
|
217 |
public PageResult<RoleDO> getRolePage(RolePageReqVO reqVO) { |
|
218 |
return roleMapper.selectPage(reqVO); |
|
219 |
} |
|
220 |
|
|
221 |
@Override |
|
222 |
public boolean hasAnySuperAdmin(Collection<Long> ids) { |
|
223 |
if (CollectionUtil.isEmpty(ids)) { |
|
224 |
return false; |
|
225 |
} |
|
226 |
RoleServiceImpl self = getSelf(); |
|
227 |
return ids.stream().anyMatch(id -> { |
|
228 |
RoleDO role = self.getRoleFromCache(id); |
|
229 |
return role != null && RoleCodeEnum.isSuperAdmin(role.getCode()); |
|
230 |
}); |
|
231 |
} |
|
232 |
|
|
233 |
@Override |
|
234 |
public void validateRoleList(Collection<Long> ids) { |
|
235 |
if (CollUtil.isEmpty(ids)) { |
|
236 |
return; |
|
237 |
} |
|
238 |
// 获得角色信息 |
|
239 |
List<RoleDO> roles = roleMapper.selectBatchIds(ids); |
|
240 |
Map<Long, RoleDO> roleMap = convertMap(roles, RoleDO::getId); |
|
241 |
// 校验 |
|
242 |
ids.forEach(id -> { |
|
243 |
RoleDO role = roleMap.get(id); |
|
244 |
if (role == null) { |
|
245 |
throw exception(ROLE_NOT_EXISTS); |
|
246 |
} |
|
247 |
if (!CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())) { |
|
248 |
throw exception(ROLE_IS_DISABLE, role.getName()); |
|
249 |
} |
|
250 |
}); |
|
251 |
} |
|
252 |
|
d9f9ba
|
253 |
@Override |
H |
254 |
public RoleDO getRoleByName(String name) { |
|
255 |
return roleMapper.selectOne(new LambdaQueryWrapperX<RoleDO>().eq(RoleDO::getName, name)); |
|
256 |
} |
|
257 |
|
|
258 |
@Override |
|
259 |
public void insert(RoleDO role) { |
|
260 |
roleMapper.insert(role); |
|
261 |
} |
|
262 |
|
e7c126
|
263 |
/** |
H |
264 |
* 获得自身的代理对象,解决 AOP 生效问题 |
|
265 |
* |
|
266 |
* @return 自己 |
|
267 |
*/ |
|
268 |
private RoleServiceImpl getSelf() { |
|
269 |
return SpringUtil.getBean(getClass()); |
|
270 |
} |
|
271 |
|
|
272 |
} |