xiejun
2024-01-23 f09e05514d9a9e2623cfa73c4de1ffa98bb30bf8
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
package com.vci.ubcs.system.service.impl;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vci.ubcs.code.feign.ICodeClassifyClient;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import com.vci.ubcs.system.entity.ClassifyAuth;
import com.vci.ubcs.system.entity.Menu;
import com.vci.ubcs.system.mapper.ClassifyAuthMapper;
import com.vci.ubcs.system.service.IClassifyAuthService;
import com.vci.ubcs.system.service.IMenuService;
import com.vci.ubcs.system.vo.ClassifyAuthVO;
import com.vci.ubcs.system.vo.MenuVO;
import com.vci.ubcs.system.wrapper.ClassifyAuthWrapper;
import lombok.AllArgsConstructor;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * 分类授权,数据授权
 * @author ludc
 * @date 2023/12/25 15:35
 */
@Service
@AllArgsConstructor
public class ClassifyAuthServiceImpl extends ServiceImpl<ClassifyAuthMapper,ClassifyAuth> implements IClassifyAuthService {
 
    private final ClassifyAuthMapper classifyAuthMapper;
 
    private final IMenuService menuService;
 
    private final ICodeClassifyClient codeClassifyClient;
 
    /**
     * 分类授权保存接口
     * @param classifyAuthList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R submit(List<ClassifyAuth> classifyAuthList) {
        if(classifyAuthList.isEmpty()){
            R.fail("授权列表不能为空!");
        }
        // 判重,查看是否存在同一个classid下配置了相同的角色
        Map<String, Long> roleidCounts = classifyAuthList.stream()
            .collect(Collectors.groupingBy(ClassifyAuth::getRoleId, Collectors.counting()));
 
        // 检查是否有roleid出现次数大于1的情况
        boolean hasDuplicateRoleid = roleidCounts.values().stream()
            .anyMatch(count -> count > 1);
        if(hasDuplicateRoleid){
            R.fail("角色和分类已经存在,请重新配置!");
        }
 
        // 如果传过来的集合中该分类id下删除了部分角色的授权,就需要将该库中classifyId下不存在的数据删掉
        List<String> roleIds = classifyAuthList.stream().map(ClassifyAuth::getRoleId).collect(Collectors.toList());
        // 删除
        LambdaUpdateWrapper<ClassifyAuth> updateWrapper = Wrappers.<ClassifyAuth>update()
            .lambda().eq(ClassifyAuth::getClassifyId, classifyAuthList.get(0).getClassifyId())
            .notIn(ClassifyAuth::getRoleId, roleIds);
        try {
            this.classifyAuthMapper.delete(updateWrapper);
        }catch (Exception e){
            throw new ServiceException("分类授权过程中出现错误,错误原因:"+e.getMessage());
        }
        return R.status(saveOrUpdateBatch(classifyAuthList));
    }
 
    /**
     * 获取分类授权集合
     * @param classifyAuthVO
     * @return
     */
    @Override
    public List<ClassifyAuthVO> getClassifyAuthList(ClassifyAuthVO classifyAuthVO) {
        if(Func.isBlank(classifyAuthVO.getClassifyId())){
            throw new ServiceException("缺少必传参数分类id");
        }
        LambdaQueryWrapper<ClassifyAuth> wrapper = Wrappers.<ClassifyAuth>query()
            .lambda().eq(ClassifyAuth::getClassifyId,classifyAuthVO.getClassifyId())
            .eq(ClassifyAuth::getAuthType,classifyAuthVO.getAuthType());
        List<ClassifyAuth> classifyAuths = this.classifyAuthMapper.selectList(wrapper);
        if(classifyAuths.isEmpty()){
            return new ArrayList<ClassifyAuthVO>();
        }
        return ClassifyAuthWrapper.build().listVO(classifyAuths);
    }
 
    /**
     * 查询该分类下,当前登录的角色有哪些按钮权限
     * @param classifyId
     * @param menuCode
     * @param authType
     * @return
     */
    public Map<String,Boolean> getAuthButtonList(String classifyId,String menuCode,String authType){
        List<Menu> menuList = this.getButtonList(classifyId, menuCode, authType);
        if(menuList.isEmpty()){
            return new HashMap<>();
        }
        Map<String, Boolean> buttonMaps = menuList.stream()
            .collect(Collectors.toMap(Menu::getCode, menu -> true));
        return buttonMaps;
    }
 
    /**
     * 查询该主数据下,当前登录的角色有哪些按钮菜单权限
     * @param classifyId
     * @param menuCode
     * @param authType
     * @return
     */
    public List<Menu> getAuthMenuButtonList(String classifyId,String menuCode,String authType){
        List<Menu> buttonList = getButtonList(classifyId, menuCode, authType);
        return buttonList;
    }
 
    private List<Menu> getButtonList(String classifyId,String menuCode,String authType){
        if(Func.isBlank(classifyId)){
            throw new ServiceException("必传参数分类oid不能为空!");
        }
        //查询分类节点的所有父级节点
        R<List<String>> listR = codeClassifyClient.selectAllParentOid(classifyId);
        if (!listR.isSuccess() && !listR.getData().isEmpty()) {
            throw new ServiceException("获取分类信息失败!");
        }
        // 返回的分类oid是当前节点为第一个,后面依次是他的上层节点
        List<String> classifyOidList = listR.getData();
        final String roleIds = AuthUtil.getUser().getRoleId();
        // 先查询按钮id列表
        LambdaQueryWrapper<ClassifyAuth> wrapper = Wrappers.<ClassifyAuth>query()
            .lambda().eq(ClassifyAuth::getClassifyId, classifyId)
            .eq(ClassifyAuth::getAuthType,authType)
            .in(ClassifyAuth::getRoleId, roleIds);
        List<ClassifyAuth> classifyAuths = this.classifyAuthMapper.selectList(wrapper);
        //如果当前分类没有找到授权配置,就依次从当前节点往上层节点找授权配置,找到了就停止,没找到就一直找到最后
        if(classifyAuths.isEmpty()){
            // 下标从1开始因为当前节点0已经查询过
            for (int i = 1; i < classifyOidList.size(); i++) {
                classifyAuths = this.classifyAuthMapper.selectList(
                    Wrappers.<ClassifyAuth>query()
                        .lambda().eq(ClassifyAuth::getClassifyId, classifyOidList.get(i))
                        .in(ClassifyAuth::getRoleId, roleIds)
                );
                if(!classifyAuths.isEmpty()){
                    break;
                }
            }
        }
        //出现了错误数据,同一个角色和同一个分类id存在多条授权记录
        if(classifyAuths.size()>1){
            throw new ServiceException("角色和分类配置存在多条记录,请联系管理人员清理错误配置!");
        }
        // 是否为超管
        Boolean isAdmin = VciBaseUtil.checkAdminTenant();
        // 未配置按钮权限
        if(!isAdmin && (classifyAuths.isEmpty() || Func.isBlank(classifyAuths.get(0).getButtonIds()))){
            return new ArrayList<>();
        }
        List<String> ids = new ArrayList<>();
        // 如果不是超管用户
        if(!isAdmin){
            ids.addAll(Arrays.asList(classifyAuths.get(0).getButtonIds().split(",")));
        }
        return menuService.getMenuListByCode(ids,menuCode,roleIds);
    }
 
    /**
     * 根据角色id查看有哪些分类具备查看权限
     * @param roleIds
     * @return
     */
    @Override
    public List<String> getViewClassByRoleIds(List<String> roleIds,String authType,String buttonCode,String menuCode) {
        if(roleIds.isEmpty()){
            return new ArrayList<>();
        }
        return this.classifyAuthMapper.getViewClassByRoleIds(roleIds, authType,buttonCode,menuCode);
    }
 
}