| | |
| | | package com.iailab.module.system.controller.admin.auth; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.date.LocalDateTimeUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.iailab.framework.common.enums.CommonStatusEnum; |
| | | import com.iailab.framework.common.enums.UserTypeEnum; |
| | | import com.iailab.framework.common.pojo.CommonResult; |
| | | import com.iailab.framework.common.util.object.BeanUtils; |
| | | import com.iailab.framework.security.config.SecurityProperties; |
| | | import com.iailab.framework.security.core.LoginUser; |
| | | import com.iailab.framework.security.core.util.SecurityFrameworkUtils; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppMenuRespVO; |
| | | import com.iailab.module.system.controller.admin.app.vo.AppRespVO; |
| | | import com.iailab.module.system.controller.admin.auth.vo.*; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO; |
| | | import com.iailab.module.system.controller.admin.permission.vo.menu.MenuRespVO; |
| | | import com.iailab.module.system.convert.auth.AuthConvert; |
| | | import com.iailab.module.system.dal.dataobject.app.AppDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.MenuDO; |
| | | import com.iailab.module.system.dal.dataobject.permission.RoleDO; |
| | | import com.iailab.module.system.dal.dataobject.user.AdminUserDO; |
| | | import com.iailab.module.system.enums.logger.LoginLogTypeEnum; |
| | | import com.iailab.module.system.enums.permission.MenuTypeEnum; |
| | | import com.iailab.module.system.service.app.AppService; |
| | | import com.iailab.module.system.service.auth.AdminAuthService; |
| | | import com.iailab.module.system.service.permission.MenuService; |
| | | import com.iailab.module.system.service.permission.PermissionService; |
| | |
| | | import io.swagger.v3.oas.annotations.Parameters; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.security.core.Authentication; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | import javax.annotation.security.PermitAll; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.validation.Valid; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import static com.iailab.framework.common.pojo.CommonResult.success; |
| | | import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet; |
| | | import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| | | import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.*; |
| | | import static com.iailab.framework.tenant.core.context.TenantContextHolder.getTenantId; |
| | | |
| | | |
| | | @Tag(name = "管理后台 - 认证") |
| | | @RestController |
| | |
| | | private PermissionService permissionService; |
| | | @Resource |
| | | private SocialClientService socialClientService; |
| | | |
| | | @Resource |
| | | private SecurityProperties securityProperties; |
| | | @Resource |
| | | private AppService appService; |
| | | |
| | | @PostMapping("/login") |
| | | @PermitAll |
| | |
| | | return success(authService.refreshToken(refreshToken)); |
| | | } |
| | | |
| | | @PostMapping("/client-refresh-token") |
| | | @PermitAll |
| | | @Operation(summary = "刷新令牌") |
| | | @Parameter(name = "refreshToken", description = "刷新令牌", required = true) |
| | | public Map<String, Object> refreshToken(@RequestParam("refreshToken") String refreshToken, @RequestParam("clientId") String clientId) { |
| | | AuthLoginRespVO authLoginRespVO = authService.refreshToken(refreshToken, clientId); |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("access_token", authLoginRespVO.getAccessToken()); |
| | | map.put("refresh_token", authLoginRespVO.getRefreshToken()); |
| | | map.put("expires_time", LocalDateTimeUtil.toEpochMilli(authLoginRespVO.getExpiresTime()) / 1000L); |
| | | return map; |
| | | } |
| | | |
| | | @GetMapping("/get-permission-info") |
| | | @Operation(summary = "获取登录用户的权限信息") |
| | | public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() { |
| | |
| | | // 1.3 获得菜单列表 |
| | | Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); |
| | | List<MenuDO> menuList = menuService.getMenuList(menuIds); |
| | | menuList.removeIf(menu -> !CommonStatusEnum.ENABLE.getStatus().equals(menu.getStatus())); // 移除禁用的菜单 |
| | | menuList = menuService.filterDisableMenus(menuList); |
| | | // menuList = menuService.filterMenus(menuList, "system"); |
| | | |
| | | // 2. 拼接结果返回 |
| | | return success(AuthConvert.INSTANCE.convert(user, roles, menuList)); |
| | | } |
| | | |
| | | @GetMapping("/get-app-permission-info") |
| | | @Operation(summary = "脚手架获取登录用户的权限信息") |
| | | public CommonResult<AuthPermissionInfoRespVO> getAppPermissionInfo() { |
| | | // 1.1 获得用户信息 |
| | | AdminUserDO user = userService.getUser(getLoginUserId()); |
| | | if (user == null) { |
| | | return success(null); |
| | | } |
| | | |
| | | // 1.2 获得角色列表 |
| | | Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); |
| | | if (CollUtil.isEmpty(roleIds)) { |
| | | return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList())); |
| | | } |
| | | List<RoleDO> roles = roleService.getRoleList(roleIds); |
| | | roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 |
| | | |
| | | // 1.3 获得菜单列表 |
| | | Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); |
| | | List<MenuDO> menuList = menuService.getMenuList(menuIds); |
| | | menuList = menuService.filterDisableMenus(menuList); |
| | | menuList = menuService.filterMenus(menuList, "app"); |
| | | |
| | | // 2. 拼接结果返回 |
| | | return success(AuthConvert.INSTANCE.convert(user, roles, menuList)); |
| | | } |
| | | |
| | | @GetMapping("/get-app-permission") |
| | | @Operation(summary = "获取登录用户的app权限信息") |
| | | public CommonResult<List<AppRespVO>> getAppPermission() { |
| | | List<AppRespVO> appList = new ArrayList<>(); |
| | | // 1.1 获得用户信息 |
| | | AdminUserDO user = userService.getUser(getLoginUserId()); |
| | | if (user == null) { |
| | | return success(null); |
| | | } |
| | | // 1.2 获得角色列表 |
| | | Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); |
| | | if (CollUtil.isEmpty(roleIds)) { |
| | | return success(appList); |
| | | } |
| | | List<RoleDO> roles = roleService.getRoleList(roleIds); |
| | | roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 |
| | | |
| | | // 1.3 获得应用菜单列表 |
| | | Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); |
| | | List<MenuDO> menuList = menuService.getMenuList(menuIds); |
| | | //只要一级菜单,一级菜单即是应用 |
| | | menuList = menuList.stream().filter(menu -> menu.getParentId() == 0l).collect(Collectors.toList()); |
| | | menuList = menuService.filterDisableMenus(menuList); |
| | | List<Long> ids = menuList.stream().map(MenuDO::getAppId).collect(Collectors.toList()); |
| | | List<AppDO> appDOS = appService.selectBatchIds(ids); |
| | | //排序 |
| | | Collections.sort(appDOS, Comparator.comparing(AppDO::getOrderNum)); |
| | | // 2. 拼接结果返回 |
| | | return success(BeanUtils.toBean(appDOS, AppRespVO.class)); |
| | | } |
| | | |
| | | @GetMapping("/get-app-menu-permission") |
| | | @Operation(summary = "获取登录用户的app权限信息") |
| | | public CommonResult<List<AuthPermissionInfoRespVO.MenuVO>> getAppMenuPermission(@RequestParam("id") Long id) { |
| | | List<AuthPermissionInfoRespVO.MenuVO> menuVOS = new ArrayList<>(); |
| | | // 1.1 获得用户信息 |
| | | AdminUserDO user = userService.getUser(getLoginUserId()); |
| | | if (user == null) { |
| | | return success(null); |
| | | } |
| | | // 1.2 获得角色列表 |
| | | Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); |
| | | if (CollUtil.isEmpty(roleIds)) { |
| | | return success(menuVOS); |
| | | } |
| | | List<RoleDO> roles = roleService.getRoleList(roleIds); |
| | | roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 |
| | | |
| | | // 1.3 获得应用菜单列表 |
| | | Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId)); |
| | | List<MenuDO> menuList = menuService.getMenuList(menuIds); |
| | | menuList = menuService.filterDisableMenus(menuList); |
| | | MenuDO menuDO = menuService.getMenuByAppId(id); |
| | | AppDO info = appService.getInfo(id); |
| | | List<MenuDO> children = new LinkedList<>(); |
| | | // 遍历每一层 |
| | | Collection<Long> parentIds = Collections.singleton(menuDO.getId()); |
| | | for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下,存在死循环 |
| | | // 查询当前层,所有的子应用菜单 |
| | | List<MenuDO> menus = menuService.selectListByParentId(parentIds); |
| | | // 1. 如果没有子菜单,则结束遍历 |
| | | if (CollUtil.isEmpty(menus)) { |
| | | break; |
| | | } |
| | | // 2. 如果有子应用菜单,继续遍历 |
| | | children.addAll(menus); |
| | | parentIds = convertSet(menus, MenuDO::getId); |
| | | } |
| | | children.retainAll(menuList); |
| | | List<MenuDO> tempChildren = new LinkedList<>(); |
| | | //为每一个二级菜单增加一个隐藏父级目录 |
| | | children.stream().forEach(menu -> { |
| | | if (menu.getParentId().equals(menuDO.getId())) { |
| | | if(menu.getType().equals(MenuTypeEnum.MENU.getType())) { |
| | | MenuDO parentMenu = BeanUtils.toBean(menu, MenuDO.class); |
| | | parentMenu.setId(System.currentTimeMillis() + (int) (Math.random() * (99999 - 10000 + 1)) + 10000); |
| | | parentMenu.setType(MenuTypeEnum.DIR.getType()); |
| | | parentMenu.setVisible(true); |
| | | parentMenu.setAlwaysShow(false); |
| | | parentMenu.setParentId(menuDO.getId()); |
| | | parentMenu.setPath("/"); |
| | | menu.setParentId(parentMenu.getId()); |
| | | tempChildren.add(parentMenu); |
| | | } else if(menu.getType().equals(MenuTypeEnum.DIR.getType())) { |
| | | // 为应用菜单二级目录前增加“/” |
| | | menu.setPath("/" + menu.getPath()); |
| | | } |
| | | } |
| | | tempChildren.add(menu); |
| | | }); |
| | | menuVOS = AuthConvert.INSTANCE.buildMenuTree(tempChildren, menuDO.getId(), menuDO.getPath(), info.getType()); |
| | | // 2. 拼接结果返回 |
| | | return success(menuVOS); |
| | | } |
| | | |
| | | // ========== 短信登录相关 ========== |
| | | |
| | | @PostMapping("/sms-login") |