diff --git a/README.md b/README.md index eee75a30..9707e752 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ ```bash # clone -git clone https://github.com/dromara/orion-visor +git clone --depth=1 https://github.com/dromara/orion-visor cd orion-visor # 启动 docker compose up -d diff --git a/docker-compose-testing.yml b/docker-compose-testing.yml index d60b162c..c45299ce 100644 --- a/docker-compose-testing.yml +++ b/docker-compose-testing.yml @@ -1,7 +1,7 @@ version: '3.3' services: service: - image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.3 + image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.4 privileged: true ports: - 1081:80 @@ -32,7 +32,7 @@ services: - mysql - redis mysql: - image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.3 + image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.4 privileged: true ports: - 3307:3306 @@ -52,7 +52,7 @@ services: retries: 10 start_period: 3s redis: - image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.3 + image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.4 privileged: true ports: - 6380:6379 diff --git a/docker-compose.yml b/docker-compose.yml index 0deb56f9..e28141fe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '3.3' services: service: - image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.3 + image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.4 privileged: true ports: - ${SERVICE_PORT:-1081}:80 @@ -19,9 +19,9 @@ services: - ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/service/root-orion:/root/orion healthcheck: test: [ "CMD", "curl", "http://127.0.0.1:9200/orion-visor/api/server/bootstrap/health" ] - interval: 3s + interval: 15s timeout: 300s - retries: 200 + retries: 15 start_period: 3s depends_on: mysql: @@ -32,7 +32,7 @@ services: - mysql - redis mysql: - image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.3 + image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.4 privileged: true ports: - 3307:3306 @@ -47,12 +47,12 @@ services: - ${VOLUME_BASE:-/data/orion-visor-space/docker-volumes}/mysql/etc-mysql:/etc/mysql healthcheck: test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/3306" ] - interval: 3s + interval: 15s timeout: 60s - retries: 10 + retries: 15 start_period: 3s redis: - image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.3 + image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.4 privileged: true ports: - 6380:6379 @@ -63,12 +63,12 @@ services: command: sh -c "redis-server /usr/local/redis.conf --requirepass $${REDIS_PASSWORD}" healthcheck: test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ] - interval: 3s + interval: 15s timeout: 60s - retries: 10 + retries: 15 start_period: 3s adminer: - image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-adminer:2.1.3 + image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-adminer:2.1.4 ports: - 8081:8080 depends_on: diff --git a/docker/adminer/build.sh b/docker/adminer/build.sh index f03a0a99..e55f97de 100644 --- a/docker/adminer/build.sh +++ b/docker/adminer/build.sh @@ -1,4 +1,4 @@ #/bin/bash -version=2.1.3 +version=2.1.4 docker build -t orion-visor-adminer:${version} . docker tag orion-visor-adminer:${version} registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-adminer:${version} diff --git a/docker/mysql/build.sh b/docker/mysql/build.sh index 614c250f..a6cc7f61 100644 --- a/docker/mysql/build.sh +++ b/docker/mysql/build.sh @@ -1,5 +1,5 @@ #/bin/bash -version=2.1.3 +version=2.1.4 cp -r ../../sql ./sql docker build -t orion-visor-mysql:${version} . rm -rf ./sql diff --git a/docker/push.sh b/docker/push.sh index 736746e7..d60a754d 100644 --- a/docker/push.sh +++ b/docker/push.sh @@ -1,5 +1,5 @@ #/bin/bash -version=2.1.3 +version=2.1.4 docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-adminer:${version} docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:${version} docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version} diff --git a/docker/redis/build.sh b/docker/redis/build.sh index 16e44b07..e4ce685d 100644 --- a/docker/redis/build.sh +++ b/docker/redis/build.sh @@ -1,4 +1,4 @@ #/bin/bash -version=2.1.3 +version=2.1.4 docker build -t orion-visor-redis:${version} . docker tag orion-visor-redis:${version} registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version} diff --git a/docker/service/build.sh b/docker/service/build.sh index 52b69d10..26fee918 100644 --- a/docker/service/build.sh +++ b/docker/service/build.sh @@ -1,5 +1,5 @@ #/bin/bash -version=2.1.3 +version=2.1.4 mv ../../orion-visor-launch/target/orion-visor-launch.jar ./orion-visor-launch.jar mv ../../orion-visor-ui/dist ./dist docker build -t orion-visor-service:${version} . diff --git a/docker/service/nginx.conf b/docker/service/nginx.conf index 86a73f21..c8ef796f 100644 --- a/docker/service/nginx.conf +++ b/docker/service/nginx.conf @@ -29,7 +29,7 @@ server { location /orion-visor/api { proxy_pass http://localhost:9200/orion-visor/api; proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } diff --git a/orion-visor-dependencies/pom.xml b/orion-visor-dependencies/pom.xml index 75eef8cf..33c03316 100644 --- a/orion-visor-dependencies/pom.xml +++ b/orion-visor-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/dromara/orion-visor - 2.1.3 + 2.1.4 2.7.17 2.7.15 1.5.0 diff --git a/orion-visor-framework/orion-visor-framework-common/src/main/java/com/orion/visor/framework/common/constant/AppConst.java b/orion-visor-framework/orion-visor-framework-common/src/main/java/com/orion/visor/framework/common/constant/AppConst.java index 1d03be4f..041dc000 100644 --- a/orion-visor-framework/orion-visor-framework-common/src/main/java/com/orion/visor/framework/common/constant/AppConst.java +++ b/orion-visor-framework/orion-visor-framework-common/src/main/java/com/orion/visor/framework/common/constant/AppConst.java @@ -14,7 +14,7 @@ public interface AppConst extends OrionConst { /** * 同 ${orion.version} 迭代时候需要手动更改 */ - String VERSION = "2.1.3"; + String VERSION = "2.1.4"; /** * 同 ${spring.application.name} diff --git a/orion-visor-framework/orion-visor-framework-common/src/main/java/com/orion/visor/framework/common/meta/TraceIdHolder.java b/orion-visor-framework/orion-visor-framework-common/src/main/java/com/orion/visor/framework/common/meta/TraceIdHolder.java index 03213d5a..dae1375b 100644 --- a/orion-visor-framework/orion-visor-framework-common/src/main/java/com/orion/visor/framework/common/meta/TraceIdHolder.java +++ b/orion-visor-framework/orion-visor-framework-common/src/main/java/com/orion/visor/framework/common/meta/TraceIdHolder.java @@ -1,6 +1,8 @@ package com.orion.visor.framework.common.meta; import com.alibaba.ttl.TransmittableThreadLocal; +import com.orion.lang.id.UUIds; +import org.slf4j.MDC; /** * traceId 持有者 @@ -23,16 +25,74 @@ private TraceIdHolder() { */ private static final ThreadLocal HOLDER = new TransmittableThreadLocal<>(); + /** + * 获取 traceId + * + * @return traceId + */ public static String get() { return HOLDER.get(); } + /** + * 设置 traceId + */ + public static void set() { + set(createTraceId()); + } + + /** + * 设置 traceId + * + * @param traceId traceId + */ public static void set(String traceId) { + // 设置应用上下文 HOLDER.set(traceId); + // 设置日志上下文 + setMdc(traceId); } + /** + * 删除 traceId + */ public static void remove() { + // 移除应用上下文 HOLDER.remove(); + // 移除日志上下文 + removeMdc(); + } + + /** + * 从应用上下文 设置到日志上下文 + */ + public static void setMdc() { + setMdc(HOLDER.get()); + } + + /** + * 设置到日志上下文 + * + * @param traceId traceId + */ + public static void setMdc(String traceId) { + MDC.put(TRACE_ID_MDC, traceId); + } + + /** + * 移除日志上下文 + */ + public static void removeMdc() { + MDC.remove(TRACE_ID_MDC); + } + + /** + * 创建 traceId + * + * @return traceId + */ + public static String createTraceId() { + return UUIds.random32(); } } diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/com/orion/visor/framework/mybatis/core/generator/core/DictParser.java b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/com/orion/visor/framework/mybatis/core/generator/core/DictParser.java index 35a07b9c..4fa573a3 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/com/orion/visor/framework/mybatis/core/generator/core/DictParser.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/com/orion/visor/framework/mybatis/core/generator/core/DictParser.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.generator.config.po.TableField; import com.baomidou.mybatisplus.generator.config.po.TableInfo; +import com.orion.lang.utils.Exceptions; import com.orion.lang.utils.Strings; import com.orion.visor.framework.common.constant.Const; import com.orion.visor.framework.common.constant.FieldConst; @@ -47,7 +48,7 @@ public Map parse() { .stream() .filter(s -> variable.equals(s.getName()) || variable.equals(s.getPropertyName())) .findFirst() - .orElseThrow(() -> new RuntimeException("未查询到字典映射字段 " + variable)); + .orElseThrow(() -> Exceptions.runtime("未查询到字典映射字段 " + variable)); // 设置字段名称 if (meta.getField() == null) { meta.setField(Strings.firstUpper(tableField.getPropertyName())); diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-security/src/main/java/com/orion/visor/framework/security/core/utils/SecurityUtils.java b/orion-visor-framework/orion-visor-spring-boot-starter-security/src/main/java/com/orion/visor/framework/security/core/utils/SecurityUtils.java index dbe6d252..0e46d405 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-security/src/main/java/com/orion/visor/framework/security/core/utils/SecurityUtils.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-security/src/main/java/com/orion/visor/framework/security/core/utils/SecurityUtils.java @@ -98,6 +98,13 @@ public static Long getLoginTimestamp() { return loginUser != null ? loginUser.getTimestamp() : null; } + /** + * 清空用户上下文 + */ + public static void clearAuthentication() { + SecurityContextHolder.getContext().setAuthentication(null); + } + /** * 设置当前用户 * @@ -107,7 +114,9 @@ public static Long getLoginTimestamp() { public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) { // 创建 authentication UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginUser, null, Collections.emptyList()); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + if (request != null) { + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + } // 设置上下文 SecurityContextHolder.getContext().setAuthentication(authentication); } diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/com/orion/visor/framework/web/core/filter/TraceIdFilter.java b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/com/orion/visor/framework/web/core/filter/TraceIdFilter.java index 0ae69b79..f2b73503 100644 --- a/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/com/orion/visor/framework/web/core/filter/TraceIdFilter.java +++ b/orion-visor-framework/orion-visor-spring-boot-starter-web/src/main/java/com/orion/visor/framework/web/core/filter/TraceIdFilter.java @@ -1,8 +1,6 @@ package com.orion.visor.framework.web.core.filter; -import com.orion.lang.id.UUIds; import com.orion.visor.framework.common.meta.TraceIdHolder; -import org.slf4j.MDC; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; @@ -23,21 +21,17 @@ public class TraceIdFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { try { - // 获 traceId - String traceId = UUIds.random32(); - // 设置应用上下文 + // 获取 traceId + String traceId = TraceIdHolder.createTraceId(); + // 设置 traceId 上下文 TraceIdHolder.set(traceId); - // 设置日志上下文 - MDC.put(TraceIdHolder.TRACE_ID_MDC, traceId); // 设置响应头 response.setHeader(TraceIdHolder.TRACE_ID_HEADER, traceId); // 执行请求 filterChain.doFilter(request, response); } finally { - // 清理应用上下文 + // 清空 traceId 上下文 TraceIdHolder.remove(); - // 清理日志上下文 - MDC.clear(); } } diff --git a/orion-visor-launch/src/main/resources/application.yaml b/orion-visor-launch/src/main/resources/application.yaml index 3edfe856..f6a3008b 100644 --- a/orion-visor-launch/src/main/resources/application.yaml +++ b/orion-visor-launch/src/main/resources/application.yaml @@ -167,6 +167,8 @@ app: allow-refresh: true # 凭证续签最大次数 max-refresh-count: 3 + # 登录失败发送站内信阈值 + login-failed-send-threshold: 3 # 登录失败锁定次数 login-failed-lock-count: 5 # 登录失败锁定时间 (分) diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/controller/ExecJobController.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/controller/ExecJobController.java index 64f2a808..ffe3b010 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/controller/ExecJobController.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/controller/ExecJobController.java @@ -5,6 +5,7 @@ import com.orion.visor.framework.common.validator.group.Page; import com.orion.visor.framework.log.core.annotation.IgnoreLog; import com.orion.visor.framework.log.core.enums.IgnoreLogMode; +import com.orion.visor.framework.web.core.annotation.DemoDisableApi; import com.orion.visor.framework.web.core.annotation.RestWrapper; import com.orion.visor.module.asset.define.operator.ExecJobOperatorType; import com.orion.visor.module.asset.entity.request.exec.*; @@ -39,6 +40,7 @@ public class ExecJobController { @Resource private ExecJobService execJobService; + @DemoDisableApi @OperatorLog(ExecJobOperatorType.CREATE) @PostMapping("/create") @Operation(summary = "创建计划任务") @@ -47,6 +49,7 @@ public Long createExecJob(@Validated @RequestBody ExecJobCreateRequest request) return execJobService.createExecJob(request); } + @DemoDisableApi @OperatorLog(ExecJobOperatorType.UPDATE) @PutMapping("/update") @Operation(summary = "更新计划任务") @@ -55,6 +58,7 @@ public Integer updateExecJob(@Validated @RequestBody ExecJobUpdateRequest reques return execJobService.updateExecJobById(request); } + @DemoDisableApi @OperatorLog(ExecJobOperatorType.UPDATE_STATUS) @PutMapping("/update-status") @Operation(summary = "更新计划任务状态") @@ -88,6 +92,7 @@ public DataGrid getExecJobPage(@Validated(Page.class) @RequestBody Ex return execJobService.getExecJobPage(request); } + @DemoDisableApi @OperatorLog(ExecJobOperatorType.DELETE) @DeleteMapping("/delete") @Operation(summary = "删除计划任务") @@ -97,6 +102,7 @@ public Integer deleteExecJob(@RequestParam("id") Long id) { return execJobService.deleteExecJobById(id); } + @DemoDisableApi @OperatorLog(ExecJobOperatorType.DELETE) @DeleteMapping("/batch-delete") @Operation(summary = "批量删除计划任务") diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/jsch/SessionStores.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/jsch/SessionStores.java index 08879f71..7284f1aa 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/jsch/SessionStores.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/jsch/SessionStores.java @@ -7,6 +7,7 @@ import com.orion.net.host.SessionHolder; import com.orion.net.host.SessionLogger; import com.orion.net.host.SessionStore; +import com.orion.visor.framework.common.constant.AppConst; import com.orion.visor.framework.common.constant.Const; import com.orion.visor.framework.common.utils.CryptoUtils; import com.orion.visor.module.asset.entity.dto.HostTerminalConnectDTO; @@ -43,6 +44,8 @@ public static SessionStore openSessionStore(HostTerminalConnectDTO conn) { SessionHolder sessionHolder = SessionHolder.create(); sessionHolder.setLogger(SessionLogger.INFO); SessionStore session = createSessionStore(conn, sessionHolder); + // 设置版本 + session.getSession().setClientVersion("SSH-2.0-ORION_VISOR_V" + AppConst.VERSION); // 连接 session.connect(); log.info("SessionStores-open-success hostId: {}, address: {}, username: {}", hostId, address, username); diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/handler/TerminalConnectHandler.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/handler/TerminalConnectHandler.java index 0ceb98fa..3bff8f69 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/handler/TerminalConnectHandler.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/handler/TerminalConnectHandler.java @@ -65,13 +65,15 @@ public void handle(WebSocketSession channel, TerminalConnectRequest payload) { // 移除会话连接信息 channel.getAttributes().remove(sessionId); Exception ex = null; + ITerminalSession session = null; try { // 连接主机 - ITerminalSession session = this.connect(sessionId, connect, channel, payload); + session = this.connect(sessionId, connect, channel, payload); // 添加会话到 manager hostTerminalManager.addSession(session); } catch (Exception e) { ex = e; + Streams.close(session); // 修改连接状态为失败 Map extra = Maps.newMap(4); extra.put(ExtraFieldConst.ERROR_MESSAGE, this.getConnectErrorMessage(e)); diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/impl/HostTerminalServiceImpl.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/impl/HostTerminalServiceImpl.java index 7e4a3618..b8c8cee6 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/impl/HostTerminalServiceImpl.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/impl/HostTerminalServiceImpl.java @@ -75,6 +75,10 @@ public class HostTerminalServiceImpl implements HostTerminalService { @Override public List getTerminalThemes() { + // if (true) { + // String arr = ""; + // return JSON.parseArray(arr, HostTerminalThemeVO.class); + // } List themes = dictValueApi.getDictValue(THEME_DICT_KEY); return themes.stream() .map(s -> HostTerminalThemeVO.builder() diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/test/java/com/orion/visor/module/asset/meta/TerminalThemeGenerator.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/test/java/com/orion/visor/module/asset/meta/TerminalThemeGenerator.java index a1118e64..8b380d25 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/test/java/com/orion/visor/module/asset/meta/TerminalThemeGenerator.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/test/java/com/orion/visor/module/asset/meta/TerminalThemeGenerator.java @@ -28,13 +28,15 @@ public static void main(String[] args) { List files = Files1.listFiles("D:\\idea-project\\iTerm2-Color-Schemes\\vhs"); // 过滤的 theme List schemaFilter = Lists.of( - "Dracula", "Atom", - "catppuccin-mocha", "MaterialDesignColors", - "catppuccin-macchiato", "OneHalfDark", - "Apple System Colors", "Builtin Tango Light", - "Duotone Dark", "BlulocoLight", - "Chester", "CLRS", - "Calamity", "Tomorrow" + "Dracula", "Builtin Tango Light", + "Atom", "AtomOneLight", + "OneHalfDark", "OneHalfLight", + "Apple System Colors", "Tomorrow", + "catppuccin-mocha", "catppuccin-latte", + "catppuccin-macchiato", "BlulocoLight", + "catppuccin-frappe", "MaterialDesignColors", + "GitHub Dark", "Github", + "DimmedMonokai", "Duotone Dark" ); // 颜色大写 ValueFilter colorFilter = (Object object, String name, Object value) -> { @@ -60,7 +62,7 @@ public static void main(String[] args) { theme.setDark(Colors.isDarkColor(background)); theme.setSchema(JSON.parseObject(JSON.toJSONString(schema), TerminalThemeSchema.class)); return theme; - }).collect(Collectors.toList()); + }).skip(0).limit(50).collect(Collectors.toList()); // 排序 if (!Lists.isEmpty(schemaFilter)) { arr.sort(Comparator.comparing(s -> schemaFilter.indexOf(s.getName()))); @@ -70,11 +72,12 @@ public static void main(String[] args) { for (TerminalTheme theme : arr) { System.out.println("name: " + theme.name); System.out.println("dark: " + theme.dark); - System.out.println("value: \n" + JSON.toJSONString(theme.schema, colorFilter)); + System.out.println("value: " + JSON.toJSONString(theme.schema, colorFilter)); + System.out.println("json: " + JSON.toJSONString(theme, colorFilter)); System.out.println(); } - // String json = JSON.toJSONString(arr, colorFilter); - // System.out.println("\n" + json); + String json = JSON.toJSONString(arr, colorFilter); + System.out.println("\n" + json); } /* diff --git a/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/AuthenticationApi.java b/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/AuthenticationApi.java new file mode 100644 index 00000000..d7858ac5 --- /dev/null +++ b/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/AuthenticationApi.java @@ -0,0 +1,24 @@ +package com.orion.visor.module.infra.api; + +import com.orion.visor.module.infra.entity.dto.user.SystemUserAuthDTO; + +/** + * 认证服务实现 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/8/14 21:37 + */ +public interface AuthenticationApi { + + /** + * 通过密码认证 + * + * @param username username + * @param password password + * @param addFailedCount addFailedCount + * @return result + */ + SystemUserAuthDTO authByPassword(String username, String password, boolean addFailedCount); + +} diff --git a/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/PermissionApi.java b/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/PermissionApi.java new file mode 100644 index 00000000..35b9552c --- /dev/null +++ b/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/PermissionApi.java @@ -0,0 +1,58 @@ +package com.orion.visor.module.infra.api; + +import java.util.List; + +/** + * 权限 对外服务类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/8/19 15:22 + */ +public interface PermissionApi { + + /** + * 用户是否为管理员用户 + * + * @param id id + * @return isAdmin + */ + boolean isAdminUser(Long id); + + /** + * 检查当前用户是否含有此角色 + * + * @param userId userId + * @param role role + * @return 是否包含 + */ + boolean hasRole(Long userId, String role); + + /** + * 检查当前用户是否含有任意角色 + * + * @param userId userId + * @param roles roles + * @return 是否包含 + */ + boolean hasAnyRole(Long userId, List roles); + + /** + * 检查当前用户是否含有此权限 + * + * @param userId userId + * @param permission permission + * @return 是否包含 + */ + boolean hasPermission(Long userId, String permission); + + /** + * 检查当前用户是否含任意权限 + * + * @param userId userId + * @param permissions permissions + * @return 是否包含 + */ + boolean hasAnyPermission(Long userId, List permissions); + +} diff --git a/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/SystemUserApi.java b/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/SystemUserApi.java index 2dff70f6..fc28d14b 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/SystemUserApi.java +++ b/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/api/SystemUserApi.java @@ -12,19 +12,27 @@ public interface SystemUserApi { /** - * 通过 id 查询用户 + * 通过 id 查询用户名 * * @param id id - * @return user + * @return username */ - SystemUserDTO getUserById(Long id); + String getUsernameById(Long id); /** - * 用户是否为管理员用户 + * 通过 id 查询花名 * * @param id id - * @return isAdmin + * @return nickname */ - boolean isAdminUser(Long id); + String getNicknameById(Long id); + + /** + * 通过 id 查询用户 + * + * @param id id + * @return user + */ + SystemUserDTO getUserById(Long id); } diff --git a/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/entity/dto/user/SystemUserAuthDTO.java b/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/entity/dto/user/SystemUserAuthDTO.java new file mode 100644 index 00000000..452c8e7f --- /dev/null +++ b/orion-visor-module-infra/orion-visor-module-infra-provider/src/main/java/com/orion/visor/module/infra/entity/dto/user/SystemUserAuthDTO.java @@ -0,0 +1,45 @@ +package com.orion.visor.module.infra.entity.dto.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 用户状态检查 业务对象 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/8/14 21:52 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(name = "SystemUserAuthDTO", description = "用户认证 业务对象") +public class SystemUserAuthDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "id") + private Long id; + + @Schema(description = "用户名") + private String username; + + @Schema(description = "花名") + private String nickname; + + @Schema(description = "密码是否正确") + private Boolean passRight; + + @Schema(description = "认证是否通过") + private Boolean authed; + + @Schema(description = "错误信息") + private String errorMessage; + +} diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/AuthenticationApiImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/AuthenticationApiImpl.java new file mode 100644 index 00000000..fd8e499f --- /dev/null +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/AuthenticationApiImpl.java @@ -0,0 +1,51 @@ +package com.orion.visor.module.infra.api.impl; + +import com.orion.visor.framework.common.constant.ErrorMessage; +import com.orion.visor.framework.common.utils.Valid; +import com.orion.visor.module.infra.api.AuthenticationApi; +import com.orion.visor.module.infra.entity.domain.SystemUserDO; +import com.orion.visor.module.infra.entity.dto.user.SystemUserAuthDTO; +import com.orion.visor.module.infra.service.AuthenticationService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * 认证服务实现 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/8/14 21:37 + */ +@Slf4j +@Service +public class AuthenticationApiImpl implements AuthenticationApi { + + @Resource + private AuthenticationService authenticationService; + + @Override + public SystemUserAuthDTO authByPassword(String username, String password, boolean addFailedCount) { + SystemUserAuthDTO result = new SystemUserAuthDTO(); + try { + // 登录预检 + SystemUserDO user = authenticationService.preCheckLogin(username, password); + result.setId(user.getId()); + result.setUsername(user.getUsername()); + result.setNickname(user.getNickname()); + // 检查用户密码 + boolean passRight = authenticationService.checkUserPassword(user, password, addFailedCount); + result.setPassRight(passRight); + Valid.isTrue(passRight, ErrorMessage.USERNAME_PASSWORD_ERROR); + // 检查用户状态 + authenticationService.checkUserStatus(user); + result.setAuthed(true); + } catch (Exception e) { + result.setAuthed(false); + result.setErrorMessage(e.getMessage()); + } + return result; + } + +} diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/PermissionApiImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/PermissionApiImpl.java new file mode 100644 index 00000000..4210978c --- /dev/null +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/PermissionApiImpl.java @@ -0,0 +1,48 @@ +package com.orion.visor.module.infra.api.impl; + +import com.orion.visor.module.infra.api.PermissionApi; +import com.orion.visor.module.infra.service.PermissionService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 权限 对外服务类实现 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/8/19 15:25 + */ +@Service +public class PermissionApiImpl implements PermissionApi { + + @Resource + private PermissionService permissionService; + + @Override + public boolean isAdminUser(Long id) { + return permissionService.isAdminUser(id); + } + + @Override + public boolean hasRole(Long userId, String role) { + return permissionService.hasRole(userId, role); + } + + @Override + public boolean hasAnyRole(Long userId, List roles) { + return permissionService.hasAnyRole(userId, roles); + } + + @Override + public boolean hasPermission(Long userId, String permission) { + return permissionService.hasPermission(userId, permission); + } + + @Override + public boolean hasAnyPermission(Long userId, List permissions) { + return permissionService.hasAnyPermission(userId, permissions); + } + +} diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/SystemUserApiImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/SystemUserApiImpl.java index ddad654f..2a612577 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/SystemUserApiImpl.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/api/impl/SystemUserApiImpl.java @@ -5,7 +5,6 @@ import com.orion.visor.module.infra.dao.SystemUserDAO; import com.orion.visor.module.infra.entity.domain.SystemUserDO; import com.orion.visor.module.infra.entity.dto.user.SystemUserDTO; -import com.orion.visor.module.infra.service.SystemUserService; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -23,8 +22,25 @@ public class SystemUserApiImpl implements SystemUserApi { @Resource private SystemUserDAO systemUserDAO; - @Resource - private SystemUserService systemUserService; + @Override + public String getUsernameById(Long id) { + return systemUserDAO.of() + .createWrapper() + .select(SystemUserDO::getUsername) + .eq(SystemUserDO::getId, id) + .then() + .getOne(SystemUserDO::getUsername); + } + + @Override + public String getNicknameById(Long id) { + return systemUserDAO.of() + .createWrapper() + .select(SystemUserDO::getNickname) + .eq(SystemUserDO::getId, id) + .then() + .getOne(SystemUserDO::getNickname); + } @Override public SystemUserDTO getUserById(Long id) { @@ -35,9 +51,4 @@ public SystemUserDTO getUserById(Long id) { return SystemUserProviderConvert.MAPPER.to(user); } - @Override - public boolean isAdminUser(Long id) { - return systemUserService.isAdminUser(id); - } - } diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/controller/PermissionController.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/controller/UserPermissionController.java similarity index 77% rename from orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/controller/PermissionController.java rename to orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/controller/UserPermissionController.java index 4ebba516..dbce87cf 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/controller/PermissionController.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/controller/UserPermissionController.java @@ -5,7 +5,7 @@ import com.orion.visor.framework.web.core.annotation.RestWrapper; import com.orion.visor.module.infra.entity.vo.SystemMenuVO; import com.orion.visor.module.infra.entity.vo.UserPermissionVO; -import com.orion.visor.module.infra.service.PermissionService; +import com.orion.visor.module.infra.service.UserPermissionService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -26,22 +26,23 @@ * @version 1.0.0 * @since 2023/7/14 11:20 */ -@Tag(name = "infra - 权限服务") +@Tag(name = "infra - 用户权限服务") @Slf4j @Validated @RestWrapper @RestController -@RequestMapping("/infra/permission") -public class PermissionController { +@RequestMapping("/infra/user-permission") +@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"}) +public class UserPermissionController { @Resource - private PermissionService permissionService; + private UserPermissionService userPermissionService; @PutMapping("/refresh-cache") @Operation(summary = "刷新角色权限缓存") @PreAuthorize("@ss.hasPermission('infra:system-menu:management:refresh-cache')") public Boolean refreshCache() { - permissionService.initPermissionCache(); + userPermissionService.initPermissionCache(); return true; } @@ -49,14 +50,14 @@ public Boolean refreshCache() { @GetMapping("/menu") @Operation(summary = "获取用户菜单") public List getUserMenuList() { - return permissionService.getUserMenuList(); + return userPermissionService.getUserMenuList(); } @IgnoreLog(IgnoreLogMode.RET) @GetMapping("/user") @Operation(summary = "获取用户权限聚合信息") public UserPermissionVO getUserPermission() { - return permissionService.getUserPermission(); + return userPermissionService.getUserPermission(); } } diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/dao/SystemRoleDAO.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/dao/SystemRoleDAO.java index 7e1a19e4..6f162ad5 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/dao/SystemRoleDAO.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/dao/SystemRoleDAO.java @@ -34,11 +34,22 @@ default List selectByCodeList(Collection codeList) { /** * 通过 userId 和 roleCode 查询 roleId (检查用户是否包含某个角色) * - * @param userId userId - * @param code code + * @param userId userId + * @param codeList codeList * @return roleId */ - Long getRoleIdByUserIdAndRoleCode(@Param("userId") Long userId, @Param("code") String code); + List getRoleIdByUserIdAndRoleCode(@Param("userId") Long userId, + @Param("codeList") List codeList); + + /** + * 通过 roleId 和 permission 查询 permission (检查角色是否包含某个权限) + * + * @param roleIdList roleIdList + * @param permissionList permissionList + * @return permission + */ + List getPermissionByRoleIdAndPermission(@Param("roleIdList") List roleIdList, + @Param("permissionList") List permissionList); /** * 查询用户角色 diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/define/config/AppAuthenticationConfig.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/define/config/AppAuthenticationConfig.java index d75a20bd..3c08bb98 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/define/config/AppAuthenticationConfig.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/define/config/AppAuthenticationConfig.java @@ -31,6 +31,11 @@ public class AppAuthenticationConfig { */ private Integer maxRefreshCount; + /** + * 登录失败发送站内信阈值 + */ + private Integer loginFailedSendThreshold; + /** * 登录失败锁定次数 */ diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/define/message/SystemUserMessageDefine.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/define/message/SystemUserMessageDefine.java new file mode 100644 index 00000000..b107e166 --- /dev/null +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/define/message/SystemUserMessageDefine.java @@ -0,0 +1,53 @@ +package com.orion.visor.module.infra.define.message; + +import com.orion.visor.module.infra.define.SystemMessageDefine; +import com.orion.visor.module.infra.enums.MessageClassifyEnum; +import lombok.Getter; + +/** + * 用户 系统消息定义 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/5/14 17:23 + */ +@Getter +public enum SystemUserMessageDefine implements SystemMessageDefine { + + /** + * 登录失败 + */ + LOGIN_FAILED(MessageClassifyEnum.NOTICE, + "登录失败", + "您的账号在 ${time} 登录系统时身份认证失败, 您的密码可能已经泄漏。如非本人操作请尽快修改密码。(${address} - ${location})"), + + ; + + SystemUserMessageDefine(MessageClassifyEnum classify, String title, String content) { + this.classify = classify; + this.type = this.name(); + this.title = title; + this.content = content; + } + + /** + * 消息分类 + */ + private final MessageClassifyEnum classify; + + /** + * 消息类型 + */ + private final String type; + + /** + * 标题 + */ + private final String title; + + /** + * 内容 + */ + private final String content; + +} diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/framework/service/impl/SecurityFrameworkServiceImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/framework/service/impl/SecurityFrameworkServiceImpl.java index 1340a508..86963219 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/framework/service/impl/SecurityFrameworkServiceImpl.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/framework/service/impl/SecurityFrameworkServiceImpl.java @@ -8,7 +8,7 @@ import com.orion.visor.module.infra.enums.LoginTokenStatusEnum; import com.orion.visor.module.infra.enums.UserStatusEnum; import com.orion.visor.module.infra.service.AuthenticationService; -import com.orion.visor.module.infra.service.PermissionService; +import com.orion.visor.module.infra.service.UserPermissionService; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -27,30 +27,30 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService { private AuthenticationService authenticationService; @Resource - private PermissionService permissionService; + private UserPermissionService userPermissionService; @Override public boolean hasPermission(String permission) { // 检查是否有权限 - return permissionService.hasPermission(permission); + return userPermissionService.hasPermission(permission); } @Override public boolean hasAnyPermission(String... permissions) { // 检查是否有权限 - return permissionService.hasAnyPermission(permissions); + return userPermissionService.hasAnyPermission(permissions); } @Override public boolean hasRole(String role) { // 检查是否有角色 - return permissionService.hasRole(role); + return userPermissionService.hasRole(role); } @Override public boolean hasAnyRole(String... roles) { // 检查是否有角色 - return permissionService.hasAnyRole(roles); + return userPermissionService.hasAnyRole(roles); } @Override diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/AuthenticationService.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/AuthenticationService.java index 8c6a11d2..d05a661d 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/AuthenticationService.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/AuthenticationService.java @@ -1,6 +1,7 @@ package com.orion.visor.module.infra.service; import com.orion.visor.framework.common.security.LoginUser; +import com.orion.visor.module.infra.entity.domain.SystemUserDO; import com.orion.visor.module.infra.entity.dto.LoginTokenDTO; import com.orion.visor.module.infra.entity.request.user.UserLoginRequest; import com.orion.visor.module.infra.entity.vo.UserLoginVO; @@ -48,4 +49,30 @@ public interface AuthenticationService { */ LoginTokenDTO getLoginTokenInfo(String loginToken); + /** + * 登录预检查 + * + * @param username username + * @param password password + * @return user + */ + SystemUserDO preCheckLogin(String username, String password); + + /** + * 检查用户密码 + * + * @param user user + * @param password password + * @param addFailedCount addFailedCount + * @return passRight + */ + boolean checkUserPassword(SystemUserDO user, String password, boolean addFailedCount); + + /** + * 检查用户状态 + * + * @param user user + */ + void checkUserStatus(SystemUserDO user); + } diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/PermissionService.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/PermissionService.java index 6c3ebde1..1ff6d7f7 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/PermissionService.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/PermissionService.java @@ -1,92 +1,58 @@ package com.orion.visor.module.infra.service; -import com.orion.visor.module.infra.entity.domain.SystemRoleDO; -import com.orion.visor.module.infra.entity.dto.SystemMenuCacheDTO; -import com.orion.visor.module.infra.entity.vo.SystemMenuVO; -import com.orion.visor.module.infra.entity.vo.UserPermissionVO; - import java.util.List; -import java.util.Map; /** * 权限服务 * * @author Jiahang Li * @version 1.0.0 - * @since 2023/7/16 1:03 + * @since 2024/8/19 15:29 */ public interface PermissionService { /** - * 获取 角色缓存 - * - * @return cache - */ - Map getRoleCache(); - - /** - * 获取 菜单缓存 以作角色权限直接引用 + * 检测用户是否是为管理员 * - * @return cache - */ - List getMenuCache(); - - /** - * 获取 角色菜单关联 - * - * @return cache - */ - Map> getRoleMenuCache(); - - /** - * 初始化权限缓存 + * @param userId userId + * @return 是否为管理员 */ - void initPermissionCache(); + boolean isAdminUser(Long userId); /** - * 检查当前用户是否含有此角色 (有效性判断) + * 检查当前用户是否含有此角色 * - * @param role role + * @param userId userId + * @param role role * @return 是否包含 */ - boolean hasRole(String role); + boolean hasRole(Long userId, String role); /** - * 检查当前用户是否含有任意角色 (有效性判断) + * 检查当前用户是否含有任意角色 * - * @param roles roles + * @param userId userId + * @param roles roles * @return 是否包含 */ - boolean hasAnyRole(String... roles); + boolean hasAnyRole(Long userId, List roles); /** - * 检查当前用户是否含有此权限 (有效性判断) + * 检查当前用户是否含有此权限 * + * @param userId userId * @param permission permission * @return 是否包含 */ - boolean hasPermission(String permission); + boolean hasPermission(Long userId, String permission); /** - * 检查当前用户是否含任意权限 (有效性判断) + * 检查当前用户是否含任意权限 * + * @param userId userId * @param permissions permissions * @return 是否包含 */ - boolean hasAnyPermission(String... permissions); - - /** - * 获取用户菜单 - * - * @return 菜单 - */ - List getUserMenuList(); - - /** - * 获取用户权限 - * - * @return 权限信息 - */ - UserPermissionVO getUserPermission(); + boolean hasAnyPermission(Long userId, List permissions); } diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/SystemUserService.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/SystemUserService.java index 20b6aaa4..bee42ec2 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/SystemUserService.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/SystemUserService.java @@ -92,12 +92,4 @@ public interface SystemUserService { */ void resetPassword(UserResetPasswordRequest request); - /** - * 检测用户是否是为管理员 - * - * @param userId userId - * @return 是否为管理员 - */ - boolean isAdminUser(Long userId); - } diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/UserPermissionService.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/UserPermissionService.java new file mode 100644 index 00000000..1991a232 --- /dev/null +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/UserPermissionService.java @@ -0,0 +1,92 @@ +package com.orion.visor.module.infra.service; + +import com.orion.visor.module.infra.entity.domain.SystemRoleDO; +import com.orion.visor.module.infra.entity.dto.SystemMenuCacheDTO; +import com.orion.visor.module.infra.entity.vo.SystemMenuVO; +import com.orion.visor.module.infra.entity.vo.UserPermissionVO; + +import java.util.List; +import java.util.Map; + +/** + * 用户权限服务 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023/7/16 1:03 + */ +public interface UserPermissionService { + + /** + * 获取 角色缓存 + * + * @return cache + */ + Map getRoleCache(); + + /** + * 获取 菜单缓存 以作角色权限直接引用 + * + * @return cache + */ + List getMenuCache(); + + /** + * 获取 角色菜单关联 + * + * @return cache + */ + Map> getRoleMenuCache(); + + /** + * 初始化权限缓存 + */ + void initPermissionCache(); + + /** + * 检查当前用户是否含有此角色 (有效性判断) + * + * @param role role + * @return 是否包含 + */ + boolean hasRole(String role); + + /** + * 检查当前用户是否含有任意角色 (有效性判断) + * + * @param roles roles + * @return 是否包含 + */ + boolean hasAnyRole(String... roles); + + /** + * 检查当前用户是否含有此权限 (有效性判断) + * + * @param permission permission + * @return 是否包含 + */ + boolean hasPermission(String permission); + + /** + * 检查当前用户是否含任意权限 (有效性判断) + * + * @param permissions permissions + * @return 是否包含 + */ + boolean hasAnyPermission(String... permissions); + + /** + * 获取用户菜单 + * + * @return 菜单 + */ + List getUserMenuList(); + + /** + * 获取用户权限 + * + * @return 权限信息 + */ + UserPermissionVO getUserPermission(); + +} diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/AuthenticationServiceImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/AuthenticationServiceImpl.java index bfb44a34..a0632323 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/AuthenticationServiceImpl.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/AuthenticationServiceImpl.java @@ -1,14 +1,17 @@ package com.orion.visor.module.infra.service.impl; import com.alibaba.fastjson.JSON; +import com.orion.lang.annotation.Keep; import com.orion.lang.define.wrapper.Pair; import com.orion.lang.utils.Exceptions; +import com.orion.lang.utils.Strings; import com.orion.lang.utils.collect.Lists; import com.orion.lang.utils.crypto.Signatures; +import com.orion.lang.utils.time.Dates; import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs; -import com.orion.visor.framework.common.annotation.Keep; import com.orion.visor.framework.common.constant.Const; import com.orion.visor.framework.common.constant.ErrorMessage; +import com.orion.visor.framework.common.constant.ExtraFieldConst; import com.orion.visor.framework.common.security.LoginUser; import com.orion.visor.framework.common.security.UserRole; import com.orion.visor.framework.common.utils.CryptoUtils; @@ -17,30 +20,30 @@ import com.orion.visor.framework.redis.core.utils.RedisStrings; import com.orion.visor.framework.redis.core.utils.RedisUtils; import com.orion.visor.framework.security.core.utils.SecurityUtils; +import com.orion.visor.module.infra.api.SystemMessageApi; import com.orion.visor.module.infra.convert.SystemUserConvert; import com.orion.visor.module.infra.dao.SystemUserDAO; import com.orion.visor.module.infra.dao.SystemUserRoleDAO; import com.orion.visor.module.infra.define.cache.UserCacheKeyDefine; import com.orion.visor.module.infra.define.config.AppAuthenticationConfig; +import com.orion.visor.module.infra.define.message.SystemUserMessageDefine; import com.orion.visor.module.infra.entity.domain.SystemUserDO; import com.orion.visor.module.infra.entity.dto.LoginTokenDTO; import com.orion.visor.module.infra.entity.dto.LoginTokenIdentityDTO; +import com.orion.visor.module.infra.entity.dto.message.SystemMessageDTO; import com.orion.visor.module.infra.entity.request.user.UserLoginRequest; import com.orion.visor.module.infra.entity.vo.UserLoginVO; import com.orion.visor.module.infra.enums.LoginTokenStatusEnum; import com.orion.visor.module.infra.enums.UserStatusEnum; import com.orion.visor.module.infra.service.AuthenticationService; -import com.orion.visor.module.infra.service.PermissionService; +import com.orion.visor.module.infra.service.UserPermissionService; import com.orion.web.servlet.web.Servlets; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; -import java.util.Date; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -64,7 +67,10 @@ public class AuthenticationServiceImpl implements AuthenticationService { private SystemUserRoleDAO systemUserRoleDAO; @Resource - private PermissionService permissionService; + private UserPermissionService userPermissionService; + + @Resource + private SystemMessageApi systemMessageApi; @Keep @Resource @@ -72,39 +78,35 @@ public class AuthenticationServiceImpl implements AuthenticationService { @Override public UserLoginVO login(UserLoginRequest request, HttpServletRequest servletRequest) { + // 获取登录信息 + String remoteAddr = IpUtils.getRemoteAddr(servletRequest); + String location = IpUtils.getLocation(remoteAddr); + String userAgent = Servlets.getUserAgent(servletRequest); // 设置日志上下文的用户 否则登录失败不会记录日志 OperatorLogs.setUser(SystemUserConvert.MAPPER.toLoginUser(request)); // 登录前检查 - this.preCheckLogin(request); - // 获取登录用户 - SystemUserDO user = systemUserDAO.of() - .createWrapper() - .eq(SystemUserDO::getUsername, request.getUsername()) - .then() - .getOne(); - Valid.notNull(user, ErrorMessage.USERNAME_PASSWORD_ERROR); + SystemUserDO user = this.preCheckLogin(request.getUsername(), request.getPassword()); // 重新设置日志上下文 OperatorLogs.setUser(SystemUserConvert.MAPPER.toLoginUser(user)); - // 检查密码 - boolean passwordCorrect = this.checkPassword(request, user); - Valid.isTrue(passwordCorrect, ErrorMessage.USERNAME_PASSWORD_ERROR); - // 检查用户状态 - UserStatusEnum.checkUserStatus(user.getStatus()); + // 用户密码校验 + boolean passRight = this.checkUserPassword(user, request.getPassword(), true); + // 发送站内信 + this.sendLoginFailedErrorMessage(passRight, user, remoteAddr, location); + Valid.isTrue(passRight, ErrorMessage.USERNAME_PASSWORD_ERROR); + // 用户状态校验 + this.checkUserStatus(user); + Long id = user.getId(); // 设置上次登录时间 - this.setLastLoginTime(user.getId()); + this.setLastLoginTime(id); // 删除用户缓存 this.deleteUserCache(user); // 重设用户缓存 this.setUserCache(user); - // 获取登录信息 - String remoteAddr = IpUtils.getRemoteAddr(servletRequest); - String location = IpUtils.getLocation(remoteAddr); - String userAgent = Servlets.getUserAgent(servletRequest); long current = System.currentTimeMillis(); // 不允许多端登录 if (!appAuthenticationConfig.getAllowMultiDevice()) { // 无效化其他缓存 - this.invalidOtherDeviceToken(user.getId(), current, remoteAddr, location, userAgent); + this.invalidOtherDeviceToken(id, current, remoteAddr, location, userAgent); } // 生成 loginToken String token = this.generatorLoginToken(user, current, remoteAddr, location, userAgent); @@ -189,62 +191,83 @@ public LoginTokenDTO getLoginTokenInfo(String loginToken) { return refresh; } - /** - * 获取 token pair - * - * @param loginToken loginToken - * @return pair - */ - private Pair getLoginTokenPair(String loginToken) { - if (loginToken == null) { - return null; - } - try { - String value = CryptoUtils.decryptBase62(loginToken); - String[] pair = value.split(":"); - return Pair.of(Long.valueOf(pair[0]), Long.valueOf(pair[1])); - } catch (Exception e) { - return null; - } - } - - /** - * 登录预检查 - * - * @param request request - */ - private void preCheckLogin(UserLoginRequest request) { + @Override + public SystemUserDO preCheckLogin(String username, String password) { // 检查密码长度是否正确 MD5 长度为 32 - if (request.getPassword().length() != Const.MD5_LEN) { + if (password.length() != Const.MD5_LEN) { throw Exceptions.argument(ErrorMessage.USERNAME_PASSWORD_ERROR); } // 检查登录失败次数 - String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(request.getUsername()); + String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(username); String failedCount = redisTemplate.opsForValue().get(failedCountKey); if (failedCount != null && Integer.parseInt(failedCount) >= appAuthenticationConfig.getLoginFailedLockCount()) { throw Exceptions.argument(ErrorMessage.MAX_LOGIN_FAILED); } + // 获取登录用户 + SystemUserDO user = systemUserDAO.of() + .createWrapper() + .eq(SystemUserDO::getUsername, username) + .then() + .getOne(); + Valid.notNull(user, ErrorMessage.USERNAME_PASSWORD_ERROR); + return user; + } + + @Override + public boolean checkUserPassword(SystemUserDO user, String password, boolean addFailedCount) { + // 检查密码 + boolean passRight = user.getPassword().equals(Signatures.md5(password)); + if (!passRight && addFailedCount) { + // 刷新登录失败缓存 + String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(user.getUsername()); + redisTemplate.opsForValue().increment(failedCountKey); + RedisUtils.setExpire(failedCountKey, appAuthenticationConfig.getLoginFailedLockTime(), TimeUnit.MINUTES); + } + return passRight; + } + + @Override + public void checkUserStatus(SystemUserDO user) { + // 检查用户状态 + UserStatusEnum.checkUserStatus(user.getStatus()); } /** - * 检查密码 + * 发送登录失败错误消息 * - * @param request request - * @param user user - * @return 是否正确 + * @param passRight passRight + * @param user user + * @param remoteAddr remoteAddr + * @param location location */ - @SuppressWarnings("ALL") - private boolean checkPassword(UserLoginRequest request, SystemUserDO user) { - // 密码正确 - if (user.getPassword().equals(Signatures.md5(request.getPassword()))) { - return true; + private void sendLoginFailedErrorMessage(boolean passRight, SystemUserDO user, + String remoteAddr, String location) { + if (passRight) { + return; + } + String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(user.getUsername()); + String failedCountStr = redisTemplate.opsForValue().get(failedCountKey); + if (failedCountStr == null || !Strings.isInteger(failedCountStr)) { + return; } - // 刷新登录失败缓存 - String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(request.getUsername()); - redisTemplate.opsForValue().increment(failedCountKey); - RedisUtils.setExpire(failedCountKey, appAuthenticationConfig.getLoginFailedLockTime(), TimeUnit.MINUTES); - return false; + // 直接用相等 因为只触发一次 + if (!appAuthenticationConfig.getLoginFailedSendThreshold().equals(Integer.valueOf(failedCountStr))) { + return; + } + // 发送站内信 + Map params = new HashMap<>(); + params.put(ExtraFieldConst.ADDRESS, remoteAddr); + params.put(ExtraFieldConst.LOCATION, location); + params.put(ExtraFieldConst.TIME, Dates.current()); + SystemMessageDTO message = SystemMessageDTO.builder() + .receiverId(user.getId()) + .receiverUsername(user.getUsername()) + .relKey(user.getUsername()) + .params(params) + .build(); + // 发送 + systemMessageApi.create(SystemUserMessageDefine.LOGIN_FAILED, message); } /** @@ -273,6 +296,25 @@ private void deleteUserCache(SystemUserDO user) { redisTemplate.delete(Lists.of(userInfoKey, loginFailedCountKey)); } + /** + * 获取 token pair + * + * @param loginToken loginToken + * @return pair + */ + private Pair getLoginTokenPair(String loginToken) { + if (loginToken == null) { + return null; + } + try { + String value = CryptoUtils.decryptBase62(loginToken); + String[] pair = value.split(":"); + return Pair.of(Long.valueOf(pair[0]), Long.valueOf(pair[1])); + } catch (Exception e) { + return null; + } + } + /** * 设置用户缓存 * @@ -283,7 +325,7 @@ private LoginUser setUserCache(SystemUserDO user) { Long id = user.getId(); // 查询用户角色 List roleIds = systemUserRoleDAO.selectRoleIdByUserId(id); - List roleList = permissionService.getRoleCache() + List roleList = userPermissionService.getRoleCache() .values() .stream() .filter(s -> roleIds.contains(s.getId())) diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/PermissionServiceImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/PermissionServiceImpl.java index 9893243f..7c4815f7 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/PermissionServiceImpl.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/PermissionServiceImpl.java @@ -1,305 +1,67 @@ package com.orion.visor.module.infra.service.impl; -import com.orion.lang.utils.Arrays1; import com.orion.lang.utils.collect.Lists; -import com.orion.lang.utils.collect.Maps; -import com.orion.visor.framework.common.constant.Const; -import com.orion.visor.framework.common.security.LoginUser; -import com.orion.visor.framework.common.security.UserRole; -import com.orion.visor.framework.security.core.utils.SecurityUtils; -import com.orion.visor.module.infra.convert.SystemMenuConvert; -import com.orion.visor.module.infra.convert.SystemUserConvert; -import com.orion.visor.module.infra.dao.SystemMenuDAO; import com.orion.visor.module.infra.dao.SystemRoleDAO; -import com.orion.visor.module.infra.dao.SystemRoleMenuDAO; import com.orion.visor.module.infra.define.RoleDefine; -import com.orion.visor.module.infra.entity.domain.SystemMenuDO; import com.orion.visor.module.infra.entity.domain.SystemRoleDO; -import com.orion.visor.module.infra.entity.domain.SystemRoleMenuDO; -import com.orion.visor.module.infra.entity.dto.SystemMenuCacheDTO; -import com.orion.visor.module.infra.entity.vo.SystemMenuVO; -import com.orion.visor.module.infra.entity.vo.UserCollectInfoVO; -import com.orion.visor.module.infra.entity.vo.UserPermissionVO; -import com.orion.visor.module.infra.enums.MenuStatusEnum; -import com.orion.visor.module.infra.enums.MenuTypeEnum; -import com.orion.visor.module.infra.enums.PreferenceTypeEnum; import com.orion.visor.module.infra.enums.RoleStatusEnum; import com.orion.visor.module.infra.service.PermissionService; -import com.orion.visor.module.infra.service.PreferenceService; -import com.orion.visor.module.infra.service.SystemMenuService; -import com.orion.visor.module.infra.service.TipsService; -import lombok.Getter; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import javax.annotation.PostConstruct; import javax.annotation.Resource; -import java.util.*; -import java.util.concurrent.Future; -import java.util.function.Function; +import java.util.List; import java.util.stream.Collectors; -import java.util.stream.Stream; /** - * 权限服务 + * 权限 服务实现类 * * @author Jiahang Li * @version 1.0.0 - * @since 2023/7/16 1:05 + * @since 2024/8/19 15:29 */ -@Slf4j @Service public class PermissionServiceImpl implements PermissionService { - @Getter - private final Map roleCache = new HashMap<>(); - - @Getter - private final List menuCache = new ArrayList<>(); - - @Getter - private final Map> roleMenuCache = new HashMap<>(); - @Resource private SystemRoleDAO systemRoleDAO; - @Resource - private SystemMenuDAO systemMenuDAO; - - @Resource - private SystemRoleMenuDAO systemRoleMenuDAO; - - @Resource - private SystemMenuService systemMenuService; - - @Resource - private PreferenceService preferenceService; - - @Resource - private TipsService tipsService; - - @PostConstruct @Override - public void initPermissionCache() { - long start = System.currentTimeMillis(); - log.info("initPermissionCache-start"); - roleCache.clear(); - menuCache.clear(); - roleMenuCache.clear(); - // 加载所有角色 - List roles = systemRoleDAO.selectList(null); - for (SystemRoleDO role : roles) { - roleCache.put(role.getId(), role); - } - // 加载所有菜单信息 - List menuList = systemMenuDAO.selectList(null); - List menus = SystemMenuConvert.MAPPER.toCache(menuList); - Map menuMapping = menus.stream() - .collect(Collectors.toMap(SystemMenuCacheDTO::getId, Function.identity())); - menuCache.addAll(menus); - // 查询所有角色菜单 - systemRoleMenuDAO.selectList(null) - .stream() - .collect(Collectors.groupingBy(SystemRoleMenuDO::getRoleId, - Collectors.mapping(SystemRoleMenuDO::getMenuId, Collectors.toList()))) - .forEach((roleId, menuIdList) -> { - // 获取菜单引用 - List roleMenus = menuIdList.stream() - .map(menuMapping::get) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - // 获取角色引用 - roleMenuCache.put(roleId, roleMenus); - }); - log.info("initPermissionCache-end used: {}ms", System.currentTimeMillis() - start); + public boolean isAdminUser(Long userId) { + return this.hasAnyRole(userId, Lists.of(RoleDefine.ADMIN_CODE)); } @Override - public boolean hasRole(String role) { - // 获取用户角色 - Map roles = this.getUserEnabledRoles(); - if (roles.isEmpty()) { - return false; - } - // 检查是否为超级管理员或包含此角色 - return RoleDefine.containsAdmin(roles.values()) || roles.containsValue(role); + public boolean hasRole(Long userId, String role) { + return this.hasAnyRole(userId, Lists.of(role)); } @Override - public boolean hasAnyRole(String... roles) { - if (Arrays1.isEmpty(roles)) { - return true; - } - // 获取用户角色 - Map enableRoles = this.getUserEnabledRoles(); - if (enableRoles.isEmpty()) { - return false; - } - // 检查是否为超级管理员 || 有此角色 - return RoleDefine.containsAdmin(enableRoles.values()) - || Arrays.stream(roles).anyMatch(enableRoles::containsValue); + public boolean hasAnyRole(Long userId, List roles) { + return !systemRoleDAO.getRoleIdByUserIdAndRoleCode(userId, roles).isEmpty(); } @Override - public boolean hasPermission(String permission) { - // 获取用户角色 - Map roles = this.getUserEnabledRoles(); - if (roles.isEmpty()) { - return false; - } - // 检查是否为超级管理员 - if (RoleDefine.containsAdmin(roles.values())) { - return true; - } - // 检查普通角色是否有此权限 - return roles.keySet() - .stream() - .anyMatch(s -> this.checkRoleHasPermission(s, permission)); + public boolean hasPermission(Long userId, String permission) { + return this.hasAnyPermission(userId, Lists.singleton(permission)); } @Override - public boolean hasAnyPermission(String... permissions) { - if (Arrays1.isEmpty(permissions)) { - return true; - } - // 获取用户角色 - Map roles = this.getUserEnabledRoles(); + public boolean hasAnyPermission(Long userId, List permissions) { + // 查询用户角色 + List roles = systemRoleDAO.selectRoleByUserId(userId); + roles.removeIf(s -> !RoleStatusEnum.ENABLED.getStatus().equals(s.getStatus())); if (roles.isEmpty()) { return false; } - // 检查是否为超级管理员 - if (RoleDefine.containsAdmin(roles.values())) { + // 判断是否为 admin + boolean isAdmin = roles.stream().anyMatch(s -> s.getCode().equals(RoleDefine.ADMIN_CODE)); + if (isAdmin) { return true; } - // 检查用户角色是否包含权限 - return Arrays.stream(permissions) - .anyMatch(perm -> roles.keySet() - .stream() - .anyMatch(s -> this.checkRoleHasPermission(s, perm))); - } - - @Override - public List getUserMenuList() { - // 获取用户角色 - Map roles = this.getUserEnabledRoles(); - if (roles.isEmpty()) { - return Lists.empty(); - } - // 查询角色菜单 - Stream mergeStream; - if (RoleDefine.containsAdmin(roles.values())) { - // 管理员拥有全部菜单 - mergeStream = menuCache.stream(); - } else { - // 当前用户所适配的角色菜单 - mergeStream = roles.keySet() - .stream() - .map(roleMenuCache::get) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .distinct(); - } - // 状态过滤 - List menus = mergeStream - .filter(s -> MenuStatusEnum.ENABLED.getStatus().equals(s.getStatus())) - .filter(s -> !MenuTypeEnum.FUNCTION.getType().equals(s.getType())) - .map(SystemMenuConvert.MAPPER::to) + List roleIdList = roles.stream() + .map(SystemRoleDO::getId) .collect(Collectors.toList()); - // 构建菜单树 - return systemMenuService.buildSystemMenuTree(menus); - } - - @SneakyThrows - @Override - public UserPermissionVO getUserPermission() { - // 获取用户信息 - UserCollectInfoVO user = SystemUserConvert.MAPPER.toCollectInfo(SecurityUtils.getLoginUser()); - Long id = user.getId(); - // 获取用户系统偏好 - Future> systemPreference = preferenceService.getPreferenceAsync(id, PreferenceTypeEnum.SYSTEM); - // 获取用户角色 - Map roles = this.getUserEnabledRoles(); - // 获取用户权限 - List permissions; - if (roles.isEmpty()) { - permissions = Lists.empty(); - } else { - if (RoleDefine.containsAdmin(roles.values())) { - // 管理员拥有全部权限 - permissions = Lists.of(Const.ASTERISK); - } else { - // 当前用户所适配的角色的权限 - permissions = roles.keySet() - .stream() - .map(roleMenuCache::get) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .filter(s -> MenuStatusEnum.ENABLED.getStatus().equals(s.getStatus())) - .map(SystemMenuCacheDTO::getPermission) - .filter(Objects::nonNull) - .distinct() - .collect(Collectors.toList()); - } - } - // 设置已提示的 key - user.setTippedKeys(tipsService.getTippedKeys()); - // 获取异步结果 - user.setSystemPreference(systemPreference.get()); - // 组装数据 - return UserPermissionVO.builder() - .user(user) - .roles(roles.values()) - .permissions(permissions) - .build(); - } - - /** - * 检查角色是否有权限 - * - * @param roleId roleId - * @param permission permission - * @return 是否有权限 - */ - private boolean checkRoleHasPermission(Long roleId, String permission) { - // 获取角色权限列表 - List menus = roleMenuCache.get(roleId); - if (Lists.isEmpty(menus)) { - return false; - } - // 检查是否有此权限 - return menus.stream() - .filter(s -> MenuStatusEnum.ENABLED.getStatus().equals(s.getStatus())) - .map(SystemMenuCacheDTO::getPermission) - .filter(Objects::nonNull) - .anyMatch(permission::equals); - } - - /** - * 获取用户启用的角色 - * - * @return roles - */ - private Map getUserEnabledRoles() { - // 获取当前用户角色 - List userRoles = Optional.ofNullable(SecurityUtils.getLoginUser()) - .map(LoginUser::getRoles) - .orElse(Lists.empty()); - if (Lists.isEmpty(userRoles)) { - return Maps.empty(); - } - // 获取角色编码 - Map roles = userRoles.stream() - .map(UserRole::getId) - .map(roleCache::get) - .filter(Objects::nonNull) - // 过滤未启用的角色 - .filter(r -> RoleStatusEnum.ENABLED.getStatus().equals(r.getStatus())) - .collect(Collectors.toMap(SystemRoleDO::getId, SystemRoleDO::getCode)); - if (Maps.isEmpty(roles)) { - return Maps.empty(); - } - return roles; + return !systemRoleDAO.getPermissionByRoleIdAndPermission(roleIdList, permissions).isEmpty(); } } diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemMenuServiceImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemMenuServiceImpl.java index ab98a343..05ca0f94 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemMenuServiceImpl.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemMenuServiceImpl.java @@ -21,7 +21,7 @@ import com.orion.visor.module.infra.enums.MenuStatusEnum; import com.orion.visor.module.infra.enums.MenuTypeEnum; import com.orion.visor.module.infra.enums.MenuVisibleEnum; -import com.orion.visor.module.infra.service.PermissionService; +import com.orion.visor.module.infra.service.UserPermissionService; import com.orion.visor.module.infra.service.SystemMenuService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; @@ -51,7 +51,7 @@ public class SystemMenuServiceImpl implements SystemMenuService { private SystemRoleMenuDAO systemRoleMenuDAO; @Resource - private PermissionService permissionService; + private UserPermissionService userPermissionService; @Override public Long createSystemMenu(SystemMenuCreateRequest request) { @@ -68,7 +68,7 @@ public Long createSystemMenu(SystemMenuCreateRequest request) { int effect = systemMenuDAO.insert(record); log.info("SystemMenuService-createSystemMenu effect: {}, record: {}", effect, JSON.toJSONString(record)); // 保存至缓存 - List menuCache = permissionService.getMenuCache(); + List menuCache = userPermissionService.getMenuCache(); menuCache.add(SystemMenuConvert.MAPPER.toCache(record)); return record.getId(); } @@ -89,7 +89,7 @@ public Integer updateSystemMenuById(SystemMenuUpdateRequest request) { // 重新查询转换为缓存 SystemMenuCacheDTO cache = SystemMenuConvert.MAPPER.toCache(systemMenuDAO.selectById(id)); // 获取原始缓存 - permissionService.getMenuCache() + userPermissionService.getMenuCache() .stream() .filter(s -> s.getId().equals(id)) .findFirst() @@ -115,7 +115,7 @@ public List getSystemMenuByIdList(SystemMenuQueryRequest request) Integer type = request.getType(); Integer status = request.getStatus(); // 从缓存中查询 - List menus = permissionService.getMenuCache() + List menus = userPermissionService.getMenuCache() .stream() .filter(s -> Strings.isBlank(name) || s.getName().contains(name)) .filter(s -> type == null || s.getType().equals(type)) @@ -197,7 +197,7 @@ public Integer updateSystemMenuStatus(SystemMenuUpdateStatusRequest request) { // 添加日志参数 OperatorLogs.add(OperatorLogs.NAME, record.getName()); // 从缓存中查询 - List cache = permissionService.getMenuCache(); + List cache = userPermissionService.getMenuCache(); // 获取要更新的id List updateIdList = this.getChildrenIdList(id, cache, record.getType()); // 修改状态 @@ -229,7 +229,7 @@ public Integer deleteSystemMenu(Long id) { // 添加日志参数 OperatorLogs.add(OperatorLogs.NAME, record.getName()); // 从缓存中查询 - List cache = permissionService.getMenuCache(); + List cache = userPermissionService.getMenuCache(); // 获取要删除的id List deletedIdList = this.getChildrenIdList(id, cache, record.getType()); // 删除菜单 @@ -239,7 +239,7 @@ public Integer deleteSystemMenu(Long id) { // 删除菜单缓存 cache.removeIf(s -> deletedIdList.contains(s.getId())); // 删除引用缓存 - permissionService.getRoleMenuCache() + userPermissionService.getRoleMenuCache() .values() .forEach(roleMenus -> roleMenus.removeIf(s -> deletedIdList.contains(s.getId()))); log.info("SystemMenuService-deleteSystemMenu deletedIdList: {}, effect: {}", deletedIdList, effect); diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemRoleMenuServiceImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemRoleMenuServiceImpl.java index 0232b3b1..517ff648 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemRoleMenuServiceImpl.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemRoleMenuServiceImpl.java @@ -16,7 +16,7 @@ import com.orion.visor.module.infra.entity.domain.SystemRoleMenuDO; import com.orion.visor.module.infra.entity.dto.SystemMenuCacheDTO; import com.orion.visor.module.infra.entity.request.menu.SystemRoleGrantMenuRequest; -import com.orion.visor.module.infra.service.PermissionService; +import com.orion.visor.module.infra.service.UserPermissionService; import com.orion.visor.module.infra.service.SystemRoleMenuService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -49,7 +49,7 @@ public class SystemRoleMenuServiceImpl implements SystemRoleMenuService { private SystemRoleMenuDAO systemRoleMenuDAO; @Resource - private PermissionService permissionService; + private UserPermissionService userPermissionService; @Override @Transactional(rollbackFor = Exception.class) @@ -104,7 +104,7 @@ public Integer grantRoleMenu(SystemRoleGrantMenuRequest request) { effect += insertMenuIdList.size(); } // 更新缓存 - Map> cache = permissionService.getRoleMenuCache(); + Map> cache = userPermissionService.getRoleMenuCache(); List roleCache = cache.computeIfAbsent(roleId, s -> new ArrayList<>()); roleCache.clear(); roleCache.addAll(SystemMenuConvert.MAPPER.toCache(menuList)); diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemRoleServiceImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemRoleServiceImpl.java index 6a61e011..78e0fadb 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemRoleServiceImpl.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemRoleServiceImpl.java @@ -20,7 +20,7 @@ import com.orion.visor.module.infra.entity.vo.SystemRoleVO; import com.orion.visor.module.infra.enums.RoleStatusEnum; import com.orion.visor.module.infra.service.DataPermissionService; -import com.orion.visor.module.infra.service.PermissionService; +import com.orion.visor.module.infra.service.UserPermissionService; import com.orion.visor.module.infra.service.SystemRoleService; import com.orion.visor.module.infra.service.SystemUserRoleService; import lombok.extern.slf4j.Slf4j; @@ -51,7 +51,7 @@ public class SystemRoleServiceImpl implements SystemRoleService { private SystemRoleMenuDAO systemRoleMenuDAO; @Resource - private PermissionService permissionService; + private UserPermissionService userPermissionService; @Resource private SystemUserRoleService systemUserRoleService; @@ -72,7 +72,7 @@ public Long createSystemRole(SystemRoleCreateRequest request) { int effect = systemRoleDAO.insert(record); log.info("SystemRoleService-createSystemRole effect: {}, domain: {}", effect, JSON.toJSONString(record)); // 设置到缓存 - permissionService.getRoleCache().put(record.getId(), record); + userPermissionService.getRoleCache().put(record.getId(), record); return record.getId(); } @@ -92,7 +92,7 @@ public Integer updateSystemRoleById(SystemRoleUpdateRequest request) { int effect = systemRoleDAO.updateById(updateRecord); log.info("SystemRoleService-updateSystemRoleById effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord)); // 设置到缓存 - SystemRoleDO roleCache = permissionService.getRoleCache().get(id); + SystemRoleDO roleCache = userPermissionService.getRoleCache().get(id); roleCache.setName(updateRecord.getName()); return effect; } @@ -117,7 +117,7 @@ public Integer updateRoleStatus(SystemRoleStatusRequest request) { int effect = systemRoleDAO.updateById(updateRecord); log.info("SystemRoleService-updateRoleStatus effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord)); // 修改本地缓存状态 - SystemRoleDO roleCache = permissionService.getRoleCache().get(id); + SystemRoleDO roleCache = userPermissionService.getRoleCache().get(id); roleCache.setStatus(status); // 删除数据权限缓存 dataPermissionService.clearRoleCache(id); @@ -180,9 +180,9 @@ public Integer deleteSystemRoleById(Long id) { // 删除角色菜单关联 effect += systemRoleMenuDAO.deleteByRoleId(id); // 删除角色缓存 - permissionService.getRoleCache().remove(id); + userPermissionService.getRoleCache().remove(id); // 删除菜单缓存 - permissionService.getRoleMenuCache().remove(id); + userPermissionService.getRoleMenuCache().remove(id); // 删除用户缓存中的角色 systemUserRoleService.deleteUserCacheRoleAsync(id, userIdList); // 删除数据权限缓存 diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemUserServiceImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemUserServiceImpl.java index 0db470d8..c86c213b 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemUserServiceImpl.java +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/SystemUserServiceImpl.java @@ -25,7 +25,6 @@ import com.orion.visor.module.infra.dao.SystemRoleDAO; import com.orion.visor.module.infra.dao.SystemUserDAO; import com.orion.visor.module.infra.dao.SystemUserRoleDAO; -import com.orion.visor.module.infra.define.RoleDefine; import com.orion.visor.module.infra.define.cache.TipsCacheKeyDefine; import com.orion.visor.module.infra.define.cache.UserCacheKeyDefine; import com.orion.visor.module.infra.define.config.AppAuthenticationConfig; @@ -302,11 +301,6 @@ public void resetPassword(UserResetPasswordRequest request) { } } - @Override - public boolean isAdminUser(Long userId) { - return systemRoleDAO.getRoleIdByUserIdAndRoleCode(userId, RoleDefine.ADMIN_CODE) != null; - } - /** * 检查用户名否存在 * diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/UserPermissionServiceImpl.java b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/UserPermissionServiceImpl.java new file mode 100644 index 00000000..f5f5056d --- /dev/null +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/java/com/orion/visor/module/infra/service/impl/UserPermissionServiceImpl.java @@ -0,0 +1,305 @@ +package com.orion.visor.module.infra.service.impl; + +import com.orion.lang.utils.Arrays1; +import com.orion.lang.utils.collect.Lists; +import com.orion.lang.utils.collect.Maps; +import com.orion.visor.framework.common.constant.Const; +import com.orion.visor.framework.common.security.LoginUser; +import com.orion.visor.framework.common.security.UserRole; +import com.orion.visor.framework.security.core.utils.SecurityUtils; +import com.orion.visor.module.infra.convert.SystemMenuConvert; +import com.orion.visor.module.infra.convert.SystemUserConvert; +import com.orion.visor.module.infra.dao.SystemMenuDAO; +import com.orion.visor.module.infra.dao.SystemRoleDAO; +import com.orion.visor.module.infra.dao.SystemRoleMenuDAO; +import com.orion.visor.module.infra.define.RoleDefine; +import com.orion.visor.module.infra.entity.domain.SystemMenuDO; +import com.orion.visor.module.infra.entity.domain.SystemRoleDO; +import com.orion.visor.module.infra.entity.domain.SystemRoleMenuDO; +import com.orion.visor.module.infra.entity.dto.SystemMenuCacheDTO; +import com.orion.visor.module.infra.entity.vo.SystemMenuVO; +import com.orion.visor.module.infra.entity.vo.UserCollectInfoVO; +import com.orion.visor.module.infra.entity.vo.UserPermissionVO; +import com.orion.visor.module.infra.enums.MenuStatusEnum; +import com.orion.visor.module.infra.enums.MenuTypeEnum; +import com.orion.visor.module.infra.enums.PreferenceTypeEnum; +import com.orion.visor.module.infra.enums.RoleStatusEnum; +import com.orion.visor.module.infra.service.PreferenceService; +import com.orion.visor.module.infra.service.SystemMenuService; +import com.orion.visor.module.infra.service.TipsService; +import com.orion.visor.module.infra.service.UserPermissionService; +import lombok.Getter; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.Future; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 用户权限服务 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023/7/16 1:05 + */ +@Slf4j +@Service +public class UserPermissionServiceImpl implements UserPermissionService { + + @Getter + private final Map roleCache = new HashMap<>(); + + @Getter + private final List menuCache = new ArrayList<>(); + + @Getter + private final Map> roleMenuCache = new HashMap<>(); + + @Resource + private SystemRoleDAO systemRoleDAO; + + @Resource + private SystemMenuDAO systemMenuDAO; + + @Resource + private SystemRoleMenuDAO systemRoleMenuDAO; + + @Resource + private SystemMenuService systemMenuService; + + @Resource + private PreferenceService preferenceService; + + @Resource + private TipsService tipsService; + + @PostConstruct + @Override + public void initPermissionCache() { + long start = System.currentTimeMillis(); + log.info("initPermissionCache-start"); + roleCache.clear(); + menuCache.clear(); + roleMenuCache.clear(); + // 加载所有角色 + List roles = systemRoleDAO.selectList(null); + for (SystemRoleDO role : roles) { + roleCache.put(role.getId(), role); + } + // 加载所有菜单信息 + List menuList = systemMenuDAO.selectList(null); + List menus = SystemMenuConvert.MAPPER.toCache(menuList); + Map menuMapping = menus.stream() + .collect(Collectors.toMap(SystemMenuCacheDTO::getId, Function.identity())); + menuCache.addAll(menus); + // 查询所有角色菜单 + systemRoleMenuDAO.selectList(null) + .stream() + .collect(Collectors.groupingBy(SystemRoleMenuDO::getRoleId, + Collectors.mapping(SystemRoleMenuDO::getMenuId, Collectors.toList()))) + .forEach((roleId, menuIdList) -> { + // 获取菜单引用 + List roleMenus = menuIdList.stream() + .map(menuMapping::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + // 获取角色引用 + roleMenuCache.put(roleId, roleMenus); + }); + log.info("initPermissionCache-end used: {}ms", System.currentTimeMillis() - start); + } + + @Override + public boolean hasRole(String role) { + // 获取用户角色 + Map roles = this.getUserEnabledRoles(); + if (roles.isEmpty()) { + return false; + } + // 检查是否为超级管理员或包含此角色 + return RoleDefine.containsAdmin(roles.values()) || roles.containsValue(role); + } + + @Override + public boolean hasAnyRole(String... roles) { + if (Arrays1.isEmpty(roles)) { + return true; + } + // 获取用户角色 + Map enableRoles = this.getUserEnabledRoles(); + if (enableRoles.isEmpty()) { + return false; + } + // 检查是否为超级管理员 || 有此角色 + return RoleDefine.containsAdmin(enableRoles.values()) + || Arrays.stream(roles).anyMatch(enableRoles::containsValue); + } + + @Override + public boolean hasPermission(String permission) { + // 获取用户角色 + Map roles = this.getUserEnabledRoles(); + if (roles.isEmpty()) { + return false; + } + // 检查是否为超级管理员 + if (RoleDefine.containsAdmin(roles.values())) { + return true; + } + // 检查普通角色是否有此权限 + return roles.keySet() + .stream() + .anyMatch(s -> this.checkRoleHasPermission(s, permission)); + } + + @Override + public boolean hasAnyPermission(String... permissions) { + if (Arrays1.isEmpty(permissions)) { + return true; + } + // 获取用户角色 + Map roles = this.getUserEnabledRoles(); + if (roles.isEmpty()) { + return false; + } + // 检查是否为超级管理员 + if (RoleDefine.containsAdmin(roles.values())) { + return true; + } + // 检查用户角色是否包含权限 + return Arrays.stream(permissions) + .anyMatch(perm -> roles.keySet() + .stream() + .anyMatch(s -> this.checkRoleHasPermission(s, perm))); + } + + @Override + public List getUserMenuList() { + // 获取用户角色 + Map roles = this.getUserEnabledRoles(); + if (roles.isEmpty()) { + return Lists.empty(); + } + // 查询角色菜单 + Stream mergeStream; + if (RoleDefine.containsAdmin(roles.values())) { + // 管理员拥有全部菜单 + mergeStream = menuCache.stream(); + } else { + // 当前用户所适配的角色菜单 + mergeStream = roles.keySet() + .stream() + .map(roleMenuCache::get) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .distinct(); + } + // 状态过滤 + List menus = mergeStream + .filter(s -> MenuStatusEnum.ENABLED.getStatus().equals(s.getStatus())) + .filter(s -> !MenuTypeEnum.FUNCTION.getType().equals(s.getType())) + .map(SystemMenuConvert.MAPPER::to) + .collect(Collectors.toList()); + // 构建菜单树 + return systemMenuService.buildSystemMenuTree(menus); + } + + @SneakyThrows + @Override + public UserPermissionVO getUserPermission() { + // 获取用户信息 + UserCollectInfoVO user = SystemUserConvert.MAPPER.toCollectInfo(SecurityUtils.getLoginUser()); + Long id = user.getId(); + // 获取用户系统偏好 + Future> systemPreference = preferenceService.getPreferenceAsync(id, PreferenceTypeEnum.SYSTEM); + // 获取用户角色 + Map roles = this.getUserEnabledRoles(); + // 获取用户权限 + List permissions; + if (roles.isEmpty()) { + permissions = Lists.empty(); + } else { + if (RoleDefine.containsAdmin(roles.values())) { + // 管理员拥有全部权限 + permissions = Lists.of(Const.ASTERISK); + } else { + // 当前用户所适配的角色的权限 + permissions = roles.keySet() + .stream() + .map(roleMenuCache::get) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .filter(s -> MenuStatusEnum.ENABLED.getStatus().equals(s.getStatus())) + .map(SystemMenuCacheDTO::getPermission) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + } + } + // 设置已提示的 key + user.setTippedKeys(tipsService.getTippedKeys()); + // 获取异步结果 + user.setSystemPreference(systemPreference.get()); + // 组装数据 + return UserPermissionVO.builder() + .user(user) + .roles(roles.values()) + .permissions(permissions) + .build(); + } + + /** + * 检查角色是否有权限 + * + * @param roleId roleId + * @param permission permission + * @return 是否有权限 + */ + private boolean checkRoleHasPermission(Long roleId, String permission) { + // 获取角色权限列表 + List menus = roleMenuCache.get(roleId); + if (Lists.isEmpty(menus)) { + return false; + } + // 检查是否有此权限 + return menus.stream() + .filter(s -> MenuStatusEnum.ENABLED.getStatus().equals(s.getStatus())) + .map(SystemMenuCacheDTO::getPermission) + .filter(Objects::nonNull) + .anyMatch(permission::equals); + } + + /** + * 获取用户启用的角色 + * + * @return roles + */ + private Map getUserEnabledRoles() { + // 获取当前用户角色 + List userRoles = Optional.ofNullable(SecurityUtils.getLoginUser()) + .map(LoginUser::getRoles) + .orElse(Lists.empty()); + if (Lists.isEmpty(userRoles)) { + return Maps.empty(); + } + // 获取角色编码 + Map roles = userRoles.stream() + .map(UserRole::getId) + .map(roleCache::get) + .filter(Objects::nonNull) + // 过滤未启用的角色 + .filter(r -> RoleStatusEnum.ENABLED.getStatus().equals(r.getStatus())) + .collect(Collectors.toMap(SystemRoleDO::getId, SystemRoleDO::getCode)); + if (Maps.isEmpty(roles)) { + return Maps.empty(); + } + return roles; + } + +} diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 25cbef2d..619bde55 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -22,6 +22,11 @@ "type": "java.lang.Integer", "description": "凭证续签最大次数." }, + { + "name": "app.authentication.loginFailedSendThreshold", + "type": "java.lang.Integer", + "description": "登录失败发送站内信阈值." + }, { "name": "app.authentication.loginFailedLockCount", "type": "java.lang.Integer", diff --git a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/mapper/SystemRoleMapper.xml b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/mapper/SystemRoleMapper.xml index 0dd00832..d00aaea7 100644 --- a/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/mapper/SystemRoleMapper.xml +++ b/orion-visor-module-infra/orion-visor-module-infra-service/src/main/resources/mapper/SystemRoleMapper.xml @@ -24,12 +24,42 @@ SELECT role_id FROM system_user_role WHERE user_id = #{userId} - AND deleted = 0 - AND role_id IN (SELECT id FROM system_role WHERE CODE = #{code} AND deleted = 0) LIMIT 1 + AND deleted = 0 + AND role_id IN + (SELECT id + FROM system_role + WHERE deleted = 0 + AND status = 1 + AND code IN + + #{item} + + ) + + +