/* * Copyright 2019-2020 Zheng Jie * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package admin.modules.system.service.impl; import admin.base.PageInfo; import admin.base.QueryHelpMybatisPlus; import admin.base.impl.CommonServiceImpl; import admin.exception.BadRequestException; import admin.exception.EntityExistException; import admin.modules.security.service.UserCacheClean; import admin.modules.system.domain.*; import admin.modules.system.service.RoleService; import admin.modules.system.service.SysRolesDeptsService; import admin.modules.system.service.SysRolesMenusService; import admin.modules.system.service.dto.RoleDto; import admin.modules.system.service.dto.RoleQueryCriteria; import admin.modules.system.service.dto.RoleSmallDto; import admin.modules.system.service.dto.UserDto; import admin.modules.system.service.mapper.*; import admin.utils.*; import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Pageable; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * @date 2018-12-03 */ @Service @RequiredArgsConstructor @CacheConfig(cacheNames = "role") public class RoleServiceImpl extends CommonServiceImpl<RoleMapper, Role> implements RoleService { private final RoleMapper roleMapper; private final MenuMapper menuMapper; private final DeptMapper deptMapper; private final RedisUtils redisUtils; private final UserMapper userMapper; private final SysRolesDeptsService sysRolesDeptsService; private final SysRolesDeptsMapper sysRolesDeptsMapper; private final SysRolesMenusService sysRolesMenusService; private final SysRolesMenusMapper sysRolesMenusMapper; private final UserCacheClean userCacheClean; @Override public List<RoleDto> queryAll() { Object object = redisUtils.get(CacheKey.ROLE_ALL); List<RoleDto> roleDtos = null; if(object==null){ QueryWrapper<Role> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByAsc("level"); List<Role> roles = roleMapper.selectList(queryWrapper); roles.forEach(role -> { role.setMenus(menuMapper.findMenuByRoleId(role.getId())); role.setDepts(deptMapper.findByRoleId(role.getId())); }); roleDtos = ConvertUtil.convertList(roles, RoleDto.class); redisUtils.set(CacheKey.ROLE_ALL,roleDtos,2, TimeUnit.HOURS); }else{ roleDtos = (List<RoleDto>) object; } return roleDtos; } @Override public List<RoleDto> queryAll(RoleQueryCriteria criteria) { List<Role> roles = roleMapper.selectList(QueryHelpMybatisPlus.getPredicate(criteria)); roles.forEach(role -> { role.setMenus(menuMapper.findMenuByRoleId(role.getId())); role.setDepts(deptMapper.findByRoleId(role.getId())); }); return ConvertUtil.convertList(roles, RoleDto.class); } @Override public PageInfo<RoleDto> queryAll(RoleQueryCriteria criteria, Pageable pageable) { IPage<Role> page = PageUtil.toMybatisPage(pageable, false); IPage<Role> pageList = roleMapper.selectPage(page, QueryHelpMybatisPlus.getPredicate(criteria)); pageList.getRecords().forEach(role -> { role.setMenus(menuMapper.findMenuByRoleId(role.getId())); role.setDepts(deptMapper.findByRoleId(role.getId())); }); return ConvertUtil.convertPage(pageList, RoleDto.class); } @Override @Cacheable(key = "'id:' + #p0") @Transactional(rollbackFor = Exception.class) public RoleDto findById(long id) { Role role = roleMapper.selectById(id); ValidationUtil.isNull(role.getId(), "Role", "id", id); role.setMenus(menuMapper.findMenuByRoleId(role.getId())); role.setDepts(deptMapper.findByRoleId(role.getId())); RoleDto convert = ConvertUtil.convert(role, RoleDto.class); return convert; } @Override @Transactional(rollbackFor = Exception.class) public void create(Role resources) { if (roleMapper.findByName(resources.getName()) != null) { throw new EntityExistException(Role.class, "username", resources.getName()); } roleMapper.insert(resources); if (resources.getDepts() != null) { resources.getDepts().forEach(dept -> { SysRolesDepts rd = new SysRolesDepts(); rd.setRoleId(resources.getId()); rd.setDeptId(dept.getId()); sysRolesDeptsMapper.insert(rd); }); } delAllRoleCaches(); } @Override @Transactional(rollbackFor = Exception.class) public void update(Role resources) { Role role = roleMapper.selectById(resources.getId()); ValidationUtil.isNull(role.getId(), "Role", "id", resources.getId()); Role role1 = roleMapper.findByName(resources.getName()); if (role1 != null && !role1.getId().equals(role.getId())) { throw new EntityExistException(Role.class, "username", resources.getName()); } role.setName(resources.getName()); role.setDescription(resources.getDescription()); role.setDataScope(resources.getDataScope()); role.setDepts(resources.getDepts()); role.setLevel(resources.getLevel()); roleMapper.updateById(role); sysRolesDeptsService.removeByRoleId(resources.getId()); if (resources.getDepts() != null) { resources.getDepts().forEach(dept -> { SysRolesDepts rd = new SysRolesDepts(); rd.setRoleId(resources.getId()); rd.setDeptId(dept.getId()); sysRolesDeptsMapper.insert(rd); }); } // 更新相关缓存 delCaches(role.getId(), null); delAllRoleCaches(); } @Override public void updateMenu(Role resources, RoleDto roleDTO) { Role role = ConvertUtil.convert(roleDTO, Role.class); List<User> users = userMapper.findByRoleId(role.getId()); // 更新菜单 role.setMenus(resources.getMenus()); SysRolesMenus rm = new SysRolesMenus(); List<Long> oldMenuIds = sysRolesMenusService.queryMenuIdByRoleId(resources.getId()); List<Long> menuIds = resources.getMenus().stream().map(Menu::getId).collect(Collectors.toList()); List<Long> deleteList = oldMenuIds.stream().filter(item -> !menuIds.contains(item)) .collect(Collectors.toList()); List<Long> addList = menuIds.stream().filter(item -> !oldMenuIds.contains(item)).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(deleteList)) { sysRolesMenusService.lambdaUpdate() .eq(SysRolesMenus::getRoleId, resources.getId()) .in(SysRolesMenus::getMenuId, deleteList).remove(); } addList.forEach(item -> { rm.setMenuId(item); rm.setRoleId(resources.getId()); sysRolesMenusMapper.insert(rm); }); delCaches(resources.getId(), users); delAllRoleCaches(); roleMapper.updateById(role); } @Override @Transactional(rollbackFor = Exception.class) public void untiedMenu(Long menuId) { // 更新菜单 roleMapper.untiedMenu(menuId); } @Override @Transactional(rollbackFor = Exception.class) public void delete(Set<Long> ids) { for (Long id : ids) { // 更新相关缓存 delCaches(id, null); } delAllRoleCaches(); roleMapper.deleteAllByIdIn(ids); } @Override public List<RoleSmallDto> findByUsersId(Long id) { return ConvertUtil.convertList(new ArrayList<>(roleMapper.findByUserId(id)), RoleSmallDto.class); } @Override public Integer findByRoles(Set<Role> roles) { Set<RoleDto> roleDtos = new HashSet<>(); for (Role role : roles) { roleDtos.add(findById(role.getId())); } return Collections.min(roleDtos.stream().map(RoleDto::getLevel).collect(Collectors.toList())); } @Override @Cacheable(key = "'auth:' + #p0.id") public List<GrantedAuthority> mapToGrantedAuthorities(UserDto user) { Set<String> permissions = new HashSet<>(); // 如果是管理员直接返回 if (user.getIsAdmin()) { permissions.add("admin"); return permissions.stream().map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); } Set<Role> roles = roleMapper.findByUserId(user.getId()); permissions = roles.stream().flatMap(role -> role.getMenus().stream()) .filter(menu -> StringUtils.isNotBlank(menu.getPermission())) .map(Menu::getPermission).collect(Collectors.toSet()); return permissions.stream().map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); } @Override public void download(List<RoleDto> roles, HttpServletResponse response) throws IOException { List<Map<String, Object>> list = new ArrayList<>(); for (RoleDto role : roles) { Map<String, Object> map = new LinkedHashMap<>(); map.put("角色名称", role.getName()); map.put("角色级别", role.getLevel()); map.put("描述", role.getDescription()); map.put("创建日期", role.getCreateTime()); list.add(map); } FileUtil.downloadExcel(list, response); } @Override public void verification(Set<Long> ids) { if (userMapper.countByRoles(ids) > 0) { throw new BadRequestException("所选角色存在用户关联,请解除关联再试!"); } } @Override public List<Role> findInMenuId(List<Long> menuIds) { return roleMapper.findInMenuId(menuIds); } /** * 清理缓存 * @param id / */ public void delCaches(Long id, List<User> users) { users = CollectionUtil.isEmpty(users) ? userMapper.findByRoleId(id) : users; if (CollectionUtil.isNotEmpty(users)) { users.forEach(item -> userCacheClean.cleanUserCache(item.getUsername())); Set<Long> userIds = users.stream().map(User::getId).collect(Collectors.toSet()); redisUtils.delByKeys(CacheKey.DATE_USER, userIds); redisUtils.delByKeys(CacheKey.MENU_USER, userIds); redisUtils.delByKeys(CacheKey.ROLE_AUTH, userIds); redisUtils.del(CacheKey.ROLE_ID + id); } } /** * 清理所有角色信息缓存 */ public void delAllRoleCaches(){ redisUtils.del(CacheKey.ROLE_ALL); } }