diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index c595ae174..4dd6f2e9c 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -12,8 +12,6 @@ ruoyi: profile: D:/ruoyi/uploadPath # 获取ip地址开关 addressEnabled: false - # 验证码类型 math 数组计算 char 字符验证 - captchaType: math # 开发环境配置 server: @@ -42,7 +40,7 @@ spring: messages: # 国际化资源文件路径 basename: i18n/messages - profiles: + profiles: active: druid # 文件上传 servlet: @@ -59,13 +57,13 @@ spring: # redis 配置 redis: # 地址 - host: localhost + host: 127.0.0.1 # 端口,默认为6379 port: 6379 # 数据库索引 database: 0 # 密码 - password: + password: # 连接超时时间 timeout: 10s lettuce: @@ -79,15 +77,6 @@ spring: # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms -# token配置 -token: - # 令牌自定义标识 - header: Authorization - # 令牌密钥 - secret: abcdefghijklmnopqrstuvwxyz - # 令牌有效期(默认30分钟) - expireTime: 30 - # MyBatis配置 mybatis: # 搜索指定包别名 @@ -98,11 +87,11 @@ mybatis: configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 -pagehelper: +pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true - params: count=countSql + params: count=countSql # Swagger配置 swagger: @@ -112,7 +101,7 @@ swagger: pathMapping: /dev-api # 防止XSS攻击 -xss: +xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) diff --git a/ruoyi-ui/src/store/modules/user.js b/ruoyi-ui/src/store/modules/user.js index 91f825307..ae3931f2f 100644 --- a/ruoyi-ui/src/store/modules/user.js +++ b/ruoyi-ui/src/store/modules/user.js @@ -51,7 +51,7 @@ const user = { return new Promise((resolve, reject) => { getInfo(state.token).then(res => { const user = res.user - const avatar = user.avatar == "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; + const avatar = user.avatar === "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 commit('SET_ROLES', res.roles) commit('SET_PERMISSIONS', res.permissions) @@ -66,7 +66,7 @@ const user = { }) }) }, - + // 退出系统 LogOut({ commit, state }) { return new Promise((resolve, reject) => { diff --git a/src/main/java/cn/iocoder/dashboard/common/core/IntArrayValuable.java b/src/main/java/cn/iocoder/dashboard/common/core/IntArrayValuable.java new file mode 100644 index 000000000..d9494d4cd --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/common/core/IntArrayValuable.java @@ -0,0 +1,15 @@ +package cn.iocoder.dashboard.common.core; + +/** + * 可生成 Int 数组的接口 + * + * @author 芋道源码 + */ +public interface IntArrayValuable { + + /** + * @return int 数组 + */ + int[] array(); + +} diff --git a/src/main/java/cn/iocoder/dashboard/common/enums/CommonStatusEnum.java b/src/main/java/cn/iocoder/dashboard/common/enums/CommonStatusEnum.java new file mode 100644 index 000000000..35fad09f2 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/common/enums/CommonStatusEnum.java @@ -0,0 +1,27 @@ +package cn.iocoder.dashboard.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 通用状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum CommonStatusEnum { + + ENABLE("0", "开启"), + DISABLE("1", "关闭"); + + /** + * 状态值 + */ + private final String status; + /** + * 状态名 + */ + private final String name; + +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/datasource/DataSourceConfiguration.java b/src/main/java/cn/iocoder/dashboard/framework/datasource/DataSourceConfiguration.java new file mode 100644 index 000000000..8c7f2a4c4 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/datasource/DataSourceConfiguration.java @@ -0,0 +1,12 @@ +package cn.iocoder.dashboard.framework.datasource; + +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * 数据库匹配类 + */ +@Configuration +@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理 +public class DataSourceConfiguration { +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/mybatis/config/MybatisConfiguration.java b/src/main/java/cn/iocoder/dashboard/framework/mybatis/config/MybatisConfiguration.java new file mode 100644 index 000000000..ed1a51313 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/mybatis/config/MybatisConfiguration.java @@ -0,0 +1,15 @@ +package cn.iocoder.dashboard.framework.mybatis.config; + +import org.apache.ibatis.annotations.Mapper; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Configuration; + +/** + * MyBaits 配置类 + * + * @author 芋道源码 + */ +@Configuration +@MapperScan(value = "cn.iocoder.dashboard", annotationClass = Mapper.class) +public class MybatisConfiguration { +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/SysAuthGetInfoRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/SysAuthGetInfoRespVO.java index c80f4f3aa..c6fbcd8bc 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/SysAuthGetInfoRespVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/SysAuthGetInfoRespVO.java @@ -2,18 +2,42 @@ package cn.iocoder.dashboard.modules.system.controller.auth.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.Set; @ApiModel("获得用户信息 Resp VO") @Data +@NoArgsConstructor +@AllArgsConstructor +@Builder public class SysAuthGetInfoRespVO { + @ApiModelProperty(value = "用户信息", required = true) + private UserVO user; + @ApiModelProperty(value = "角色权限数组", required = true) private Set roles; @ApiModelProperty(value = "菜单权限数组", required = true) private Set permissions; + @ApiModel("用户信息 VO") + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class UserVO { + + @ApiModelProperty(value = "用户昵称", required = true, example = "芋道源码") + private String nickname; + + @ApiModelProperty(value = "用户头像", required = true, example = "http://www.iocoder.cn/xx.jpg") + private String avatar; + + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java index d44856102..0f3af8e02 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java @@ -22,10 +22,11 @@ public interface SysAuthConvert { LoginUser convert(SysUserDO bean); default SysAuthGetInfoRespVO convert(SysUserDO user, List roleList, List menuList) { - SysAuthGetInfoRespVO respVO = new SysAuthGetInfoRespVO(); - respVO.setRoles(CollectionUtils.convertSet(roleList, SysRoleDO::getRoleKey)); - respVO.setPermissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPerms)); - return respVO; + return SysAuthGetInfoRespVO.builder() + .user(SysAuthGetInfoRespVO.UserVO.builder().nickname(user.getNickname()).avatar(user.getAvatar()).build()) + .roles(CollectionUtils.convertSet(roleList, SysRoleDO::getRoleKey)) + .permissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPerms)) + .build(); } SysAuthGetRouterRespVO convertTreeNode(SysMenuDO menu); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/permission/MenuTypeEnum.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/permission/MenuTypeEnum.java new file mode 100644 index 000000000..9a5e0a09c --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/permission/MenuTypeEnum.java @@ -0,0 +1,25 @@ +package cn.iocoder.dashboard.modules.system.enums.permission; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 菜单类型枚举类 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MenuTypeEnum { + + DIR("M"), // 目录 + MENU("C"), // 菜单 + BUTTON("F") // 按钮 + ; + + /** + * 类型 + */ + private final String type; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java index 868c67798..1189a66d8 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.service.auth.impl; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.framework.security.config.SecurityProperties; import cn.iocoder.dashboard.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO; @@ -12,6 +13,7 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRo import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO; import cn.iocoder.dashboard.modules.system.enums.permission.MenuIdEnum; +import cn.iocoder.dashboard.modules.system.enums.permission.MenuTypeEnum; import cn.iocoder.dashboard.modules.system.enums.user.UserStatus; import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService; @@ -19,6 +21,7 @@ import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionServi import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; import cn.iocoder.dashboard.util.collection.CollectionUtils; +import cn.iocoder.dashboard.util.collection.SetUtils; import cn.iocoder.dashboard.util.date.DateUtils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtException; @@ -231,22 +234,24 @@ public class SysAuthServiceImpl implements SysAuthService { // 获得角色列表 List roleList = roleService.listRolesFromCache(roleIds); // 获得菜单列表 - List menuList = permissionService.listRoleMenusFromCache(roleIds); + List menuList = permissionService.listRoleMenusFromCache(roleIds, + SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()), + SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 拼接结果返回 return SysAuthConvert.INSTANCE.convert(user, roleList, menuList); } @Override public List getRouters(Long userId, Set roleIds) { - // TODO 芋艿:去除 F 的类型,去除 禁用 的 - List menuList = permissionService.listRoleMenusFromCache(roleIds); + List menuList = permissionService.listRoleMenusFromCache(roleIds, + SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), + SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 转换成 Tree 结构返回 return buildRouterTree(menuList); } private static List buildRouterTree(List menuList) { // 排序,保证菜单的有序性 - menuList = new ArrayList<>(menuList); // 使用 ArrayList 套一下,因为 menuList 是不可修改的 List menuList.sort(Comparator.comparing(SysMenuDO::getOrderNum)); // 构建菜单树 // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuService.java index 09898e124..b574fe8be 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuService.java @@ -18,16 +18,25 @@ public interface SysMenuService { /** * 获得所有菜单,从缓存中 * + * 任一参数为空时,则返回为空 + * + * @param menuTypes 菜单类型数组 + * @param menusStatuses 菜单状态数组 * @return 菜单列表 */ - List listMenusFromCache(); + List listMenusFromCache(Collection menuTypes, Collection menusStatuses); /** * 获得指定编号的菜单数组,从缓存中 * + * 任一参数为空时,则返回为空 + * * @param menuIds 菜单编号数组 + * @param menuTypes 菜单类型数组 + * @param menusStatuses 菜单状态数组 * @return 菜单数组 */ - List listMenusFromCache(Collection menuIds); + List listMenusFromCache(Collection menuIds, Collection menuTypes, + Collection menusStatuses); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java index 51be3c7ac..7c94f7ee3 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java @@ -22,10 +22,15 @@ public interface SysPermissionService { /** * 获得角色们拥有的菜单列表,从缓存中获取 * - * @param roleIds 角色编号素组 + * 任一参数为空时,则返回为空 + * + * @param roleIds 角色编号数组 + * @param menuTypes 菜单类型数组 + * @param menusStatuses 菜单状态数组 * @return 菜单列表 */ - List listRoleMenusFromCache(Collection roleIds); + List listRoleMenusFromCache(Collection roleIds, Collection menuTypes, + Collection menusStatuses); /** * 获得用户拥有的角色编号数组 diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java index 5f536ac61..605ed6439 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java @@ -1,10 +1,9 @@ package cn.iocoder.dashboard.modules.system.service.permission.impl; -import cn.hutool.core.collection.CollectionUtil; import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysMenuMapper; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO; import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService; -import com.google.common.collect.ImmutableList; +import cn.iocoder.dashboard.util.collection.CollectionUtils; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; @@ -13,10 +12,7 @@ import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.Resource; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -64,18 +60,27 @@ public class SysMenuServiceImpl implements SysMenuService { } @Override - public List listMenusFromCache() { - // Guava ImmutableMap 对应的 value 类型为 ImmutableCollection - // 而 ImmutableList 在 copyof 时,如果入参类型为 ImmutableCollection 时,会进行包装,而不会进行复制。 - return ImmutableList.copyOf(menuCache.values()); + public List listMenusFromCache(Collection menuTypes, Collection menusStatuses) { + // 任一一个参数为空,则返回空 + if (CollectionUtils.isAnyEmpty(menuTypes, menusStatuses)) { + return Collections.emptyList(); + } + // 创建新数组,避免缓存被修改 + return menuCache.values().stream().filter(menu -> menuTypes.contains(menu.getMenuType()) + && menusStatuses.contains(menu.getStatus())) + .collect(Collectors.toList()); } @Override - public List listMenusFromCache(Collection menuIds) { - if (CollectionUtil.isEmpty(menuIds)) { + public List listMenusFromCache(Collection menuIds, Collection menuTypes, + Collection menusStatuses) { + // 任一一个参数为空,则返回空 + if (CollectionUtils.isAnyEmpty(menuIds, menuTypes, menusStatuses)) { return Collections.emptyList(); } - return menuCache.values().stream().filter(menuDO -> menuIds.contains(menuDO.getMenuId())) + return menuCache.values().stream().filter(menu -> menuIds.contains(menu.getMenuId()) + && menuTypes.contains(menu.getMenuType()) + && menusStatuses.contains(menu.getStatus())) .collect(Collectors.toList()); } } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java index 815a6f26b..304dc8f23 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java @@ -17,6 +17,7 @@ import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -77,16 +78,21 @@ public class SysPermissionServiceImpl implements SysPermissionService { } @Override - public List listRoleMenusFromCache(Collection roleIds) { + public List listRoleMenusFromCache(Collection roleIds, Collection menuTypes, + Collection menusStatuses) { + // 任一一个参数为空时,不返回任何菜单 + if (CollectionUtils.isAnyEmpty(roleIds, menusStatuses, menusStatuses)) { + return Collections.emptyList(); + } // 判断角色是否包含管理员 List roleList = roleService.listRolesFromCache(roleIds); boolean hasAdmin = roleService.hasAnyAdmin(roleList); // 获得角色拥有的菜单关联 if (hasAdmin) { // 管理员,获取到全部 - return menuService.listMenusFromCache(); + return menuService.listMenusFromCache(menuTypes, menusStatuses); } List menuIds = MapUtils.getList(roleMenuCache, roleIds); - return menuService.listMenusFromCache(menuIds); + return menuService.listMenusFromCache(menuIds, menuTypes, menusStatuses); } @Override diff --git a/src/main/java/cn/iocoder/dashboard/util/collection/CollectionUtils.java b/src/main/java/cn/iocoder/dashboard/util/collection/CollectionUtils.java index 433ae3a74..afb67fb3e 100644 --- a/src/main/java/cn/iocoder/dashboard/util/collection/CollectionUtils.java +++ b/src/main/java/cn/iocoder/dashboard/util/collection/CollectionUtils.java @@ -14,8 +14,8 @@ import java.util.stream.Collectors; */ public class CollectionUtils { - public static Set asSet(T... objs) { - return new HashSet<>(Arrays.asList(objs)); + public static boolean isAnyEmpty(Collection... collections) { + return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); } public static List filterList(Collection from, Predicate predicate) { diff --git a/src/main/java/cn/iocoder/dashboard/util/collection/SetUtils.java b/src/main/java/cn/iocoder/dashboard/util/collection/SetUtils.java new file mode 100644 index 000000000..d6fafcff0 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/util/collection/SetUtils.java @@ -0,0 +1,18 @@ +package cn.iocoder.dashboard.util.collection; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * Set 工具类 + * + * @author 芋道源码 + */ +public class SetUtils { + + public static Set asSet(T... objs) { + return new HashSet<>(Arrays.asList(objs)); + } + +}