2021与蓝度共同重构项目,服务端
liuhaonan
2022-01-18 51b53373d150e4107a51fcf502d0598b7d82c455
功能完善/回滚数据之后新增的填哥的代码
已添加7个文件
已修改32个文件
1284 ■■■■■ 文件已修改
dao/src/main/java/com/sandu/ximon/dao/bo/MenuNode.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dao/src/main/java/com/sandu/ximon/dao/domain/Menu.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/enums/ResponseStatusEnums.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/execption/ApiError.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/execption/BusinessException.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/execption/EntityExistException.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/log/LogService.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/redis/UserModel.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/redis/online/OnlineUser.java 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/redis/online/OnlineUserService.java 226 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/JwtAccessDeniedHandler.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/JwtAuthenticationEntryPoint.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/LoginUserInfo.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/TokenFilter.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/config/SecurityConfig.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/config/SecurityProperties.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/jwt/JwtTokenProvider.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/token/JwtTokenProvider.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/token/RedisTokenProvider.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/security/token/TokenProvider.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/service/BaseService.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/service/impl/BaseServiceImpl.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/util/RequestHolder.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/util/SpringContextHolder.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sandu-common/src/main/java/com/sandu/common/util/ThrowableUtil.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/AdminController.java 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/IpVolumeFileController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/MenuController.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/PoleController.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/amqp/processor/LightDataProcessor.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/BaseInvokeSyncService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/param/MenuParam.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/security/SecurityUtils.java 87 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/service/LightService.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/service/LightTaskService.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/service/MenuService.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/service/PoleService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/resources/application-test.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/test/java/com/sandu/ximon/admin/BaseTopicTests.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dao/src/main/java/com/sandu/ximon/dao/bo/MenuNode.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.sandu.ximon.dao.bo;
import com.sandu.ximon.dao.domain.Menu;
import lombok.Data;
import java.util.List;
/**
 * èœå•树形节点
 *
 * @author chenjiantian
 * @date 2021/4/27 19:00
 */
@Data
public class MenuNode extends Menu {
    private List<MenuNode> children;
}
dao/src/main/java/com/sandu/ximon/dao/domain/Menu.java
@@ -67,7 +67,7 @@
    private String permission;
    /**
     * ç±»åž‹ï¼Œ0:菜单,1:按钮
     * ç±»åž‹ï¼Œ0:目录   1:菜单   2:按钮
     */
    private Integer type;
@@ -83,4 +83,4 @@
    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}
}
sandu-common/src/main/java/com/sandu/common/enums/ResponseStatusEnums.java
@@ -21,6 +21,7 @@
     */
    TOKEN_INVALID(40011, "token无效"),
    TOKEN_EXPIRED(40012, "token过期"),
    TOKEN_NONE(40013, "token为空"),
    SINGLE_LOGIN(40014, "该账号在其他设备登录,请重新登录"),
    FORBIDDEN(40030, "没有相关权限"),
sandu-common/src/main/java/com/sandu/common/execption/ApiError.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.execption;
import com.fasterxml.jackson.annotation.JsonFormat;
sandu-common/src/main/java/com/sandu/common/execption/BusinessException.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.execption;
import com.sandu.common.enums.ResponseStatusEnums;
sandu-common/src/main/java/com/sandu/common/execption/EntityExistException.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.execption;
import org.springframework.util.StringUtils;
sandu-common/src/main/java/com/sandu/common/log/LogService.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.log;
import org.aspectj.lang.ProceedingJoinPoint;
sandu-common/src/main/java/com/sandu/common/redis/UserModel.java
@@ -1,14 +1,21 @@
package com.sandu.common.redis;
import com.sandu.common.security.config.SecurityProperties;
import com.sandu.common.util.SpringContextHolder;
/**
 * @author chenjiantian
 * @date 2021/7/20 12:00
 */
public class UserModel extends BasePrefix{
public class UserModel extends BasePrefix {
    @Override
    public String getModelName() {
        return "user";
        String onlineKey = SpringContextHolder.getBean(SecurityProperties.class).getOnlineKey();
        if (onlineKey == null) {
            throw new IllegalArgumentException("请配置onlineKey");
        }
        return onlineKey;
    }
    public UserModel(int expireSeconds, String prefix) {
@@ -17,5 +24,8 @@
    public static UserModel User = new UserModel(60, "gl");
    public static UserModel USER_TOKEN = new UserModel(60 * 60 * 24 * 7, "token");
    public static UserModel USER_INFO = new UserModel(60 * 60 * 24 * 7, "info");
}
sandu-common/src/main/java/com/sandu/common/redis/online/OnlineUser.java
@@ -1,26 +1,26 @@
package com.sandu.common.redis.online;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
 * @author chenjiantian
 * @date 2021/8/6 16:31
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OnlineUser {
    private Long userId;
    // è¿™é‡ŒæŒ‡æ‰‹æœºå·
    private String userName;
    private String token;
    private String ip;
    private String browser;
    private LocalDateTime loginTime;
}
//package com.sandu.common.redis.online;
//
//import lombok.AllArgsConstructor;
//import lombok.Data;
//import lombok.NoArgsConstructor;
//
//import java.time.LocalDateTime;
//
///**
// * @author chenjiantian
// * @date 2021/8/6 16:31
// */
//@Data
//@AllArgsConstructor
//@NoArgsConstructor
//public class OnlineUser {
//
//    private Long userId;
//    // è¿™é‡ŒæŒ‡æ‰‹æœºå·
//    private String userName;
//    private String token;
//    private String ip;
//    private String browser;
//    private LocalDateTime loginTime;
//
//}
sandu-common/src/main/java/com/sandu/common/redis/online/OnlineUserService.java
@@ -1,115 +1,115 @@
package com.sandu.common.redis.online;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentInfo;
import cn.hutool.http.useragent.UserAgentUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sandu.common.redis.RedisService;
import com.sandu.common.security.config.SecurityProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UserDetails;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
 * @author chenjiantian
 * @date 2021/8/6 16:26
 * åœ¨çº¿ç”¨æˆ·æœåŠ¡ç±»
 * åœ¨ BaseRedisConfig æ³¨å…¥
 */
@Slf4j
public class OnlineUserService {
    private final SecurityProperties properties;
    private final RedisService redisService;
    public OnlineUserService(SecurityProperties properties, RedisService redisService) {
        this.properties = properties;
        this.redisService = redisService;
    }
    /**
     * ä¿å­˜åœ¨çº¿ç”¨æˆ·ä¿¡æ¯
     */
    public void save(UserDetails userDetails, String token, Long userId,HttpServletRequest request) {
        String ip = ServletUtil.getClientIP(request);
        UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
        String browser = Optional.ofNullable(userAgent).map(UserAgent::getBrowser).map(UserAgentInfo::getName).orElse("");
        OnlineUser onlineUser = new OnlineUser(userId,userDetails.getUsername(), token, ip, browser, LocalDateTime.now());
//        redisService.set(properties.getOnlineKey() + token, onlineUser, properties.getTokenValidityInSeconds() / 1000);
        redisService.set(properties.getOnlineKey() + userDetails.getUsername(), onlineUser);
    }
    /**
     * æŸ¥è¯¢å…¨éƒ¨æ•°æ®
     *
     * @param filter
     * @return
     */
    public List<OnlineUser> getAll(String filter) {
        Set<String> keys = redisService.keys(properties.getOnlineKey() + "*");
        List<OnlineUser> onlineUsers = new ArrayList<>();
        for (String key : keys) {
            OnlineUser onlineUser = (OnlineUser) redisService.get(key);
            if (StringUtils.isNotBlank(filter)) {
                if (onlineUser.toString().contains(filter)) {
                    onlineUsers.add(onlineUser);
                }
            } else {
                onlineUsers.add(onlineUser);
            }
        }
        onlineUsers.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
        return onlineUsers;
    }
    private boolean kickOut(String token) throws Exception {
        token = properties.getOnlineKey() + token;
        return redisService.del(token);
    }
    public OnlineUser getOne(String key) {
        return (OnlineUser) redisService.get(key);
    }
    /**
     * æ£€æµ‹ç”¨æˆ·æ˜¯å¦åœ¨ä¹‹å‰å·²ç»ç™»å½•,已经登录踢下线
     *
     * @param userName ç”¨æˆ·å
     */
    public void checkLoginOnUser(String userName, String ignoreToken) {
//        List<OnlineUser> onlineUsers = getAll(userName);
//        if (onlineUsers == null || onlineUsers.isEmpty()) {
//package com.sandu.common.redis.online;
//
//import cn.hutool.extra.servlet.ServletUtil;
//import cn.hutool.http.useragent.UserAgent;
//import cn.hutool.http.useragent.UserAgentInfo;
//import cn.hutool.http.useragent.UserAgentUtil;
//import com.baomidou.mybatisplus.core.toolkit.StringUtils;
//import com.sandu.common.redis.RedisService;
//import com.sandu.common.security.config.SecurityProperties;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.security.core.userdetails.UserDetails;
//
//import javax.servlet.http.HttpServletRequest;
//import java.time.LocalDateTime;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Optional;
//import java.util.Set;
//
///**
// * @author chenjiantian
// * @date 2021/8/6 16:26
// * åœ¨çº¿ç”¨æˆ·æœåŠ¡ç±»
// * åœ¨ BaseRedisConfig æ³¨å…¥
// */
//@Slf4j
//public class OnlineUserService {
//
//    private final SecurityProperties properties;
//    private final RedisService redisService;
//
//    public OnlineUserService(SecurityProperties properties, RedisService redisService) {
//        this.properties = properties;
//        this.redisService = redisService;
//    }
//
//    /**
//     * ä¿å­˜åœ¨çº¿ç”¨æˆ·ä¿¡æ¯
//     */
//    public void save(UserDetails userDetails, String token, Long userId,HttpServletRequest request) {
//        String ip = ServletUtil.getClientIP(request);
//        UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
//        String browser = Optional.ofNullable(userAgent).map(UserAgent::getBrowser).map(UserAgentInfo::getName).orElse("");
//        OnlineUser onlineUser = new OnlineUser(userId,userDetails.getUsername(), token, ip, browser, LocalDateTime.now());
////        redisService.set(properties.getOnlineKey() + token, onlineUser, properties.getTokenValidityInSeconds() / 1000);
//        redisService.set(properties.getOnlineKey() + userDetails.getUsername(), onlineUser);
//    }
//
//    /**
//     * æŸ¥è¯¢å…¨éƒ¨æ•°æ®
//     *
//     * @param filter
//     * @return
//     */
//    public List<OnlineUser> getAll(String filter) {
//        Set<String> keys = redisService.keys(properties.getOnlineKey() + "*");
//
//        List<OnlineUser> onlineUsers = new ArrayList<>();
//        for (String key : keys) {
//            OnlineUser onlineUser = (OnlineUser) redisService.get(key);
//            if (StringUtils.isNotBlank(filter)) {
//                if (onlineUser.toString().contains(filter)) {
//                    onlineUsers.add(onlineUser);
//                }
//            } else {
//                onlineUsers.add(onlineUser);
//            }
//        }
//        onlineUsers.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
//        return onlineUsers;
//    }
//
//    private boolean kickOut(String token) throws Exception {
//        token = properties.getOnlineKey() + token;
//        return redisService.del(token);
//    }
//
//    public OnlineUser getOne(String key) {
//        return (OnlineUser) redisService.get(key);
//    }
//
//    /**
//     * æ£€æµ‹ç”¨æˆ·æ˜¯å¦åœ¨ä¹‹å‰å·²ç»ç™»å½•,已经登录踢下线
//     *
//     * @param userName ç”¨æˆ·å
//     */
//    public void checkLoginOnUser(String userName, String ignoreToken) {
////        List<OnlineUser> onlineUsers = getAll(userName);
////        if (onlineUsers == null || onlineUsers.isEmpty()) {
////            return;
////        }
//        OnlineUser onlineUser = getOne(properties.getOnlineKey() + userName);
//        if(onlineUser == null){
//            return;
//        }
        OnlineUser onlineUser = getOne(properties.getOnlineKey() + userName);
        if(onlineUser == null){
            return;
        }
//        for (OnlineUser onlineUser : onlineUsers) {
            if (onlineUser.getUserName().equals(userName)) {
                try {
                    String token = onlineUser.getToken();
                    if (StringUtils.isNotBlank(ignoreToken) && !ignoreToken.equals(token)) {
                        this.kickOut(token);
                    } else if (StringUtils.isBlank(ignoreToken)) {
                        this.kickOut(token);
                    }
                } catch (Exception e) {
                    log.error("checkUser is error", e);
                }
            }
//        }
    }
    public void updateOne(OnlineUser onlineUser) {
        redisService.set(properties.getOnlineKey() + onlineUser.getUserName(), onlineUser);
    }
}
////        for (OnlineUser onlineUser : onlineUsers) {
//            if (onlineUser.getUserName().equals(userName)) {
//                try {
//                    String token = onlineUser.getToken();
//                    if (StringUtils.isNotBlank(ignoreToken) && !ignoreToken.equals(token)) {
//                        this.kickOut(token);
//                    } else if (StringUtils.isBlank(ignoreToken)) {
//                        this.kickOut(token);
//                    }
//                } catch (Exception e) {
//                    log.error("checkUser is error", e);
//                }
//            }
////        }
//    }
//
//    public void updateOne(OnlineUser onlineUser) {
//        redisService.set(properties.getOnlineKey() + onlineUser.getUserName(), onlineUser);
//    }
//}
sandu-common/src/main/java/com/sandu/common/security/JwtAccessDeniedHandler.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.security;
import org.springframework.security.access.AccessDeniedException;
sandu-common/src/main/java/com/sandu/common/security/JwtAuthenticationEntryPoint.java
@@ -1,20 +1,17 @@
package com.sandu.common.security;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.sandu.common.enums.ResponseStatusEnums;
import com.sandu.common.redis.online.OnlineUser;
import com.sandu.common.redis.online.OnlineUserService;
import com.sandu.common.security.config.SecurityProperties;
import com.sandu.common.security.jwt.JwtTokenProvider;
import com.sandu.common.security.token.TokenProvider;
import com.sandu.common.util.ResponseUtil;
import com.sandu.common.util.SpringContextHolder;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@@ -25,70 +22,91 @@
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Autowired
    private JwtTokenProvider tokenProvider;
    @Resource
    private TokenProvider tokenProvider;
    @Resource
    private SecurityProperties properties;
    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException) throws IOException {
        String token = tokenProvider.getToken(request);
        SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
        String token = request.getHeader(properties.getHeader());
        if (!StringUtils.hasText(token)) {
            writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_NONE.getCode(), ResponseStatusEnums.TOKEN_NONE.getMessage()));
            return;
        }
        LoginUserInfo loginUserInfo = tokenProvider.validateToken(token);
        if (loginUserInfo == null) {
            writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
            return;
        }
        Throwable exception = tokenProvider.getException(token);
        // jwt过期 æ›¿æ¢æ–°çš„jwt
        if (exception instanceof ExpiredJwtException) {
            String usernameForce = tokenProvider.getSubjectForce(token);
            if (properties.isCacheOnline()) {
                OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
                OnlineUser onlineUser = onlineUserService.getOne(properties.getOnlineKey() + usernameForce);
                if (onlineUser == null || !token.equals(onlineUser.getToken())) {
                    // redis上没有 æˆ–者不是当前用户的token è¿”回失效
                    writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
                } else {
                    // è¿”回过期,携带新的token
                    String refreshToken = tokenProvider.refreshToken(token);
                    onlineUser.setToken(refreshToken);
                    onlineUserService.updateOne(onlineUser);
                    writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_EXPIRED.getCode(), ResponseStatusEnums.TOKEN_EXPIRED.getMessage(), properties.getTokenStartWith() + refreshToken));
                }
            } else {
                // è¿”回过期,携带新的token
                String refreshToken = properties.getTokenStartWith() + tokenProvider.refreshToken(token);
                writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_EXPIRED.getCode(), ResponseStatusEnums.TOKEN_EXPIRED.getMessage(), null));
            }
            return;
        if (!StrUtil.equals(loginUserInfo.getToken(), token)) {
            writeResponse(response, ResponseUtil.error(ResponseStatusEnums.SINGLE_LOGIN.getCode(), ResponseStatusEnums.SINGLE_LOGIN.getMessage()));
        }
        // å…¶ä»–jwt解析异常
        if (exception != null) {
            writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
        } else {
            //jwt解析正常 çœ‹çœ‹æ˜¯ä¸æ˜¯redis的问题
            if (properties.isCacheOnline()) {
                String usernameForce = tokenProvider.getSubjectForce(token);
                OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
                OnlineUser onlineUser = onlineUserService.getOne(properties.getOnlineKey() + usernameForce);
                if (onlineUser != null && !token.equals(onlineUser.getToken())) {
                    // å’ŒæœåŠ¡å™¨ä¿å­˜çš„token不一样,说明在其他地方登录
                    writeResponse(response, ResponseUtil.error(ResponseStatusEnums.SINGLE_LOGIN.getCode(), ResponseStatusEnums.SINGLE_LOGIN.getMessage()));
                } else {
                    // æœåŠ¡å™¨æ²¡æœ‰åœ¨çº¿ç”¨æˆ·token或者token不一致 éƒ½è¿”回token失效
                    writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
                }
            } else {
                writeResponse(response, ResponseUtil.error(ResponseStatusEnums.FAIL.getCode(), "认证出错"));
            }
        }
        return;
//        String token = tokenProvider.getToken(request);
//        SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
//
//        if (!StringUtils.hasText(token)) {
//            writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
//            return;
//        }
//
//
//        Throwable exception = tokenProvider.getException(token);
//
//        // jwt过期 æ›¿æ¢æ–°çš„jwt
//        if (exception instanceof ExpiredJwtException) {
//            String usernameForce = tokenProvider.getSubjectForce(token);
//            if (properties.isCacheOnline()) {
//                OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
//                OnlineUser onlineUser = onlineUserService.getOne(properties.getOnlineKey() + usernameForce);
//                if (onlineUser == null || !token.equals(onlineUser.getToken())) {
//                    // redis上没有 æˆ–者不是当前用户的token è¿”回失效
//                    writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
//                } else {
//                    // è¿”回过期,携带新的token
//                    String refreshToken = tokenProvider.refreshToken(token);
//                    onlineUser.setToken(refreshToken);
//                    onlineUserService.updateOne(onlineUser);
//                    writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_EXPIRED.getCode(), ResponseStatusEnums.TOKEN_EXPIRED.getMessage(), properties.getTokenStartWith() + refreshToken));
//                }
//            } else {
//                // è¿”回过期,携带新的token
//                String refreshToken = properties.getTokenStartWith() + tokenProvider.refreshToken(token);
//                writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_EXPIRED.getCode(), ResponseStatusEnums.TOKEN_EXPIRED.getMessage(), null));
//            }
//            return;
//        }
//
//        // å…¶ä»–jwt解析异常
//        if (exception != null) {
//            writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
//        } else {
//            //jwt解析正常 çœ‹çœ‹æ˜¯ä¸æ˜¯redis的问题
//            if (properties.isCacheOnline()) {
//                String usernameForce = tokenProvider.getSubjectForce(token);
//                OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
//                OnlineUser onlineUser = onlineUserService.getOne(properties.getOnlineKey() + usernameForce);
//                if (onlineUser != null && !token.equals(onlineUser.getToken())) {
//                    // å’ŒæœåŠ¡å™¨ä¿å­˜çš„token不一样,说明在其他地方登录
//                    writeResponse(response, ResponseUtil.error(ResponseStatusEnums.SINGLE_LOGIN.getCode(), ResponseStatusEnums.SINGLE_LOGIN.getMessage()));
//                } else {
//                    // æœåŠ¡å™¨æ²¡æœ‰åœ¨çº¿ç”¨æˆ·token或者token不一致 éƒ½è¿”回token失效
//                    writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
//                }
//            } else {
//                writeResponse(response, ResponseUtil.error(ResponseStatusEnums.FAIL.getCode(), "认证出错"));
//            }
//        }
//        return;
    }
sandu-common/src/main/java/com/sandu/common/security/LoginUserInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
package com.sandu.common.security;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sandu.common.enums.AdminStatusStatus;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
/**
 * @author chenjiantian
 * @date 2022/1/8 16:22
 * ç™»å½•用户的信息
 */
@Data
public class LoginUserInfo implements UserDetails {
    private Long userId;
    private String account;
    private String name;
    private String token;
    private String role;
    /**
     * ç”¨æˆ·æƒé™ ç”¨,分隔
     */
    private String permission;
    /**
     * 0 "禁用",  1 "正常" ,2:token è¿‡æœŸ 3:未找到用户信息 4:在其它地方登录 5:IP限制 6:token è§£æžå¤±è´¥
     */
    private Integer status;
    private Long createTimestamp;
    private String ip;
    // ç®¡ç†å‘˜ç±»åž‹ï¼Œç®¡ç†å‘˜ 0官方管理员,1客户管理员 ã€‚查看AdministratorEnums
    private Integer administratorType;
    @JsonIgnore
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if (StrUtil.isBlank(permission)) {
            return null;
        }
        return Arrays.stream(permission.split(","))
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
    }
    @JsonIgnore
    @Override
    public String getPassword() {
        return null;
    }
    @JsonIgnore
    @Override
    public String getUsername() {
        return account;
    }
    @JsonIgnore
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @JsonIgnore
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @JsonIgnore
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @JsonIgnore
    @Override
    public boolean isEnabled() {
        return AdminStatusStatus.NORMAL.getCode().equals(status);
    }
}
sandu-common/src/main/java/com/sandu/common/security/TokenFilter.java
@@ -1,22 +1,19 @@
package com.sandu.common.security;
import com.sandu.common.redis.online.OnlineUser;
import com.sandu.common.redis.online.OnlineUserService;
import cn.hutool.core.util.StrUtil;
import com.sandu.common.security.config.SecurityProperties;
import com.sandu.common.security.jwt.JwtTokenProvider;
import com.sandu.common.util.SpringContextHolder;
import com.sandu.common.security.token.TokenProvider;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
@@ -26,40 +23,32 @@
 * @author chenjiantian
 */
@Slf4j
public class TokenFilter extends GenericFilterBean {
@AllArgsConstructor
public class TokenFilter extends OncePerRequestFilter {
    private final JwtTokenProvider tokenProvider;
    public TokenFilter(JwtTokenProvider tokenProvider) {
        this.tokenProvider = tokenProvider;
    }
    private final TokenProvider tokenProvider;
    private final SecurityProperties properties;
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String token = tokenProvider.getToken(httpServletRequest);
        SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(properties.getHeader());
        if (token != null && token.startsWith(properties.getTokenStartWith())) {
            token = token.substring(properties.getTokenStartWith().length());
        }
        if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
            Authentication authentication = tokenProvider.getAuthentication(token);
            // æ˜¯å¦ä½¿ç”¨redis缓存用户功能
            if (!properties.isCacheOnline()) {
        LoginUserInfo loginUserInfo = tokenProvider.validateToken(token);
        if (loginUserInfo != null) {
            if (StrUtil.equals(loginUserInfo.getToken(), token)) {
                Authentication authentication = new UsernamePasswordAuthenticationToken(
                        loginUserInfo, null,
                        loginUserInfo.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authentication);
            } else {
                OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
                OnlineUser onlineUser = onlineUserService.getOne(properties.getOnlineKey() + ((UserDetails) authentication.getPrincipal()).getUsername());
                if (onlineUser != null) {
                    // åŒ¹é…ä¸Šå½“前用户的token才合法,防止jwt不受控制
                    if (token.equals(onlineUser.getToken())) {
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    }
                }
            }
        }
        filterChain.doFilter(servletRequest, servletResponse);
        filterChain.doFilter(request, response);
    }
}
sandu-common/src/main/java/com/sandu/common/security/config/SecurityConfig.java
@@ -1,16 +1,11 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.security.config;
import com.sandu.common.security.JwtAccessDeniedHandler;
import com.sandu.common.security.JwtAuthenticationEntryPoint;
import com.sandu.common.security.TokenFilter;
import com.sandu.common.security.annotation.AnonymousAccess;
import com.sandu.common.security.jwt.JwtTokenProvider;
import com.sandu.common.security.token.TokenProvider;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -41,25 +36,15 @@
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final JwtTokenProvider tokenProvider;
    private final TokenProvider tokenProvider;
    private final CorsFilter corsFilter;
    private final SecurityProperties properties;
    private final JwtAuthenticationEntryPoint authenticationErrorHandler;
    private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
    private final ApplicationContext applicationContext;
    public SecurityConfig(JwtTokenProvider tokenProvider, CorsFilter corsFilter,
                          JwtAuthenticationEntryPoint authenticationErrorHandler,
                          JwtAccessDeniedHandler jwtAccessDeniedHandler,
                          ApplicationContext applicationContext) {
        this.tokenProvider = tokenProvider;
        this.corsFilter = corsFilter;
        this.authenticationErrorHandler = authenticationErrorHandler;
        this.jwtAccessDeniedHandler = jwtAccessDeniedHandler;
        this.applicationContext = applicationContext;
    }
    @Bean
    GrantedAuthorityDefaults grantedAuthorityDefaults() {
@@ -143,7 +128,6 @@
    @Bean
    public TokenFilter jwtAuthenticationTokenFilter() {
        TokenFilter customFilter = new TokenFilter(tokenProvider);
        return customFilter;
        return new TokenFilter(tokenProvider, properties);
    }
}
sandu-common/src/main/java/com/sandu/common/security/config/SecurityProperties.java
@@ -1,5 +1,6 @@
package com.sandu.common.security.config;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -36,7 +37,7 @@
    private Long tokenValidityInSeconds;
    /**
     * åœ¨çº¿ç”¨æˆ· key,根据 key æŸ¥è¯¢ redis ä¸­åœ¨çº¿ç”¨æˆ·çš„æ•°æ®
     * åœ¨çº¿ç”¨æˆ· model name
     */
    private String onlineKey;
@@ -46,6 +47,9 @@
    private boolean cacheOnline = false;
    public String getTokenStartWith() {
        if(StrUtil.isBlank(tokenStartWith)){
            return "";
        }
        return tokenStartWith + " ";
    }
}
sandu-common/src/main/java/com/sandu/common/security/jwt/JwtTokenProvider.java
@@ -25,7 +25,6 @@
 * @date 2021/4/23 16:43
 */
@Slf4j
@Component
public class JwtTokenProvider implements InitializingBean {
    private static final String AUTHORITIES_KEY = "auth";
sandu-common/src/main/java/com/sandu/common/security/token/JwtTokenProvider.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,95 @@
package com.sandu.common.security.token;
import com.sandu.common.enums.AdminStatusStatus;
import com.sandu.common.security.LoginUserInfo;
import com.sandu.common.security.config.SecurityProperties;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.DecodingException;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import java.security.Key;
import java.util.Date;
import java.util.stream.Collectors;
/**
 * @author chenjiantian
 * @date 2022/1/8 18:12
 */
@Component
@Slf4j
@ConditionalOnProperty(prefix = "sandu.jwt", name = "cache-online", havingValue = "false")
public class JwtTokenProvider implements TokenProvider, InitializingBean {
    private static final String AUTHORITIES_KEY = "auth";
    private static final String CREDENTIALS_KEY = "cred";
    private static final String ADMINISTRATOR_KEY = "admin";
    private final SecurityProperties properties;
    private Key key;
    public JwtTokenProvider(SecurityProperties properties) {
        this.properties = properties;
    }
    @Override
    public void afterPropertiesSet() {
        byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret());
        this.key = Keys.hmacShaKeyFor(keyBytes);
    }
    @Override
    public String createToken(LoginUserInfo loginUserInfo) {
        if (loginUserInfo.getUserId() == null) {
            throw new IllegalArgumentException("用户id不能为空");
        }
        String authorities = loginUserInfo.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.joining(","));
        long now = (new Date()).getTime();
        Date expiration = new Date(now + properties.getTokenValidityInSeconds());
        return Jwts.builder()
                .setSubject(loginUserInfo.getUserId().toString())
                .claim(AUTHORITIES_KEY, authorities)
                .claim(CREDENTIALS_KEY, loginUserInfo.getAccount())
                .claim(ADMINISTRATOR_KEY, loginUserInfo.getAdministratorType())
                .setExpiration(expiration)
                .signWith(key, SignatureAlgorithm.HS512)
                .compact();
    }
    @Override
    public LoginUserInfo validateToken(String token) {
        try {
            Claims claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
            LoginUserInfo loginUserInfo = new LoginUserInfo();
            loginUserInfo.setUserId(Long.valueOf(claims.getSubject()));
            loginUserInfo.setAccount(String.valueOf(claims.get(CREDENTIALS_KEY)));
            loginUserInfo.setPermission(claims.get(AUTHORITIES_KEY).toString());
            loginUserInfo.setAdministratorType(Integer.parseInt(claims.get(ADMINISTRATOR_KEY).toString()));
            loginUserInfo.setToken(token);
            loginUserInfo.setStatus(AdminStatusStatus.NORMAL.getCode());
            return loginUserInfo;
        } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
            log.info("Invalid JWT signature.");
//            e.printStackTrace();
        } catch (ExpiredJwtException e) {
            log.info("Expired JWT token.");
//            e.printStackTrace();
        } catch (UnsupportedJwtException | DecodingException e) {
            log.info("Unsupported JWT token.");
//            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            log.info("JWT token compact of handler are invalid.");
//            e.printStackTrace();
        }
        return null;
    }
}
sandu-common/src/main/java/com/sandu/common/security/token/RedisTokenProvider.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
package com.sandu.common.security.token;
import cn.hutool.core.util.IdUtil;
import com.sandu.common.redis.RedisService;
import com.sandu.common.redis.UserModel;
import com.sandu.common.security.LoginUserInfo;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
/**
 * @author chenjiantian
 * @date 2022/1/8 16:39
 */
@AllArgsConstructor
@Component
@ConditionalOnProperty(prefix = "sandu.jwt", name = "cache-online", havingValue = "true")
public class RedisTokenProvider implements TokenProvider {
    private final RedisService redisService;
    @Override
    public String createToken(LoginUserInfo loginUserInfo) {
        if (loginUserInfo.getUserId() == null) {
            throw new IllegalArgumentException("用户id不能为空");
        }
        String token = IdUtil.simpleUUID();
        loginUserInfo.setToken(token);
        loginUserInfo.setCreateTimestamp(System.currentTimeMillis());
        redisService.set(UserModel.USER_TOKEN.key(token), loginUserInfo.getUserId(), UserModel.USER_TOKEN.expireSeconds());
        redisService.set(UserModel.USER_INFO.key(loginUserInfo.getUserId().toString()), loginUserInfo);
        return token;
    }
    @Override
    public LoginUserInfo validateToken(String token) {
        if (token == null) {
            return null;
        }
        Long userId = (Long) redisService.get(UserModel.USER_TOKEN.key(token));
        if (userId == null) {
            return null;
        }
        LoginUserInfo userInfo = (LoginUserInfo) redisService.get(UserModel.USER_INFO.key(userId.toString()));
        if (userInfo != null) {
            if (redisService.getExpire(token) < UserModel.USER_TOKEN.expireSeconds()) {
                redisService.expire(token, UserModel.USER_TOKEN.expireSeconds());
            }
        }
        return userInfo;
    }
}
sandu-common/src/main/java/com/sandu/common/security/token/TokenProvider.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.sandu.common.security.token;
import com.sandu.common.security.LoginUserInfo;
/**
 * @author chenjiantian
 * @date 2022/1/8 16:10
 */
public interface TokenProvider {
    /**
     * ç”Ÿæˆtoken
     * @param loginUserInfo ç”¨æˆ·ä¿¡æ¯
     * @return token
     */
    String createToken(LoginUserInfo loginUserInfo);
    /**
     * éªŒè¯token æœ‰æ²¡æœ‰ä¿å­˜ç”¨æˆ·ä¿¡æ¯
     * @param token token
     * @return null表示token æ²¡æœ‰å…³è”用户信息
     */
    LoginUserInfo validateToken(String token);
}
sandu-common/src/main/java/com/sandu/common/service/BaseService.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.service;
import com.baomidou.mybatisplus.extension.service.IService;
sandu-common/src/main/java/com/sandu/common/service/impl/BaseServiceImpl.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.service.impl;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
sandu-common/src/main/java/com/sandu/common/util/RequestHolder.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.util;
import org.springframework.web.context.request.RequestContextHolder;
sandu-common/src/main/java/com/sandu/common/util/SpringContextHolder.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.util;
import lombok.extern.slf4j.Slf4j;
sandu-common/src/main/java/com/sandu/common/util/ThrowableUtil.java
@@ -1,9 +1,4 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.common.util;
import java.io.PrintWriter;
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/AdminController.java
@@ -10,9 +10,11 @@
import com.sandu.common.enums.ResponseStatusEnums;
import com.sandu.common.execption.BusinessException;
import com.sandu.common.object.BaseConditionVO;
import com.sandu.common.security.LoginUserInfo;
import com.sandu.common.security.annotation.AnonymousAccess;
import com.sandu.common.security.config.SecurityProperties;
import com.sandu.common.security.jwt.JwtTokenProvider;
import com.sandu.common.security.token.TokenProvider;
import com.sandu.common.util.IpUtil;
import com.sandu.common.util.ResponseUtil;
import com.sandu.ximon.admin.dto.AdminJwtUser;
import com.sandu.ximon.admin.param.AdminLoginParam;
@@ -26,9 +28,6 @@
import com.sandu.ximon.dao.enums.AdministratorEnums;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
@@ -56,7 +55,7 @@
    private final PasswordEncoder passwordEncoder;
    private final AdminService adminService;
    private final RoleService roleService;
    private final JwtTokenProvider tokenProvider;
    private final TokenProvider tokenProvider;
    @AnonymousAccess
@@ -70,16 +69,22 @@
            return ResponseUtil.error(ResponseStatusEnums.BAD_CREDENTIALS.getCode(), ResponseStatusEnums.BAD_CREDENTIALS.getMessage());
        }
        UserDetails userJwtUser = new AdminJwtUser(admin, roleService.mapToGrantedAuthorities(admin.getId()));
        if(!userJwtUser.isEnabled()){
        if (!userJwtUser.isEnabled()) {
            return ResponseUtil.error(ResponseStatusEnums.DISABLE_ACCOUNT.getCode(), ResponseStatusEnums.DISABLE_ACCOUNT.getMessage());
        }
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userJwtUser, AdministratorEnums.ADMIN.getCode(), userJwtUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        LoginUserInfo loginUserInfo = new LoginUserInfo();
        loginUserInfo.setUserId(admin.getId());
        loginUserInfo.setName(admin.getNickName());
        loginUserInfo.setAccount(admin.getUsername());
        loginUserInfo.setStatus(admin.getStatus());
        loginUserInfo.setIp(IpUtil.getRealIp());
        loginUserInfo.setAdministratorType(AdministratorEnums.ADMIN.getCode());
        loginUserInfo.setPermission("tenant");
        // ç”Ÿæˆä»¤ç‰Œ
        String token = tokenProvider.createToken(authentication);
        final AdminJwtUser jwtUser = (AdminJwtUser) authentication.getPrincipal();
        String token = tokenProvider.createToken(loginUserInfo);
        // æ›´æ–°æœ€åŽç™»å½•æ—¶é—´
        Admin update = new Admin();
@@ -90,25 +95,23 @@
        // è¿”回 token ä¸Ž ç”¨æˆ·ä¿¡æ¯
        Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
            put("token", properties.getTokenStartWith() + token);
            put("user", jwtUser);
            put("user", admin);
        }};
//        if (singleLogin) {
//            //踢掉之前已经登录的token
//            onlineUserService.checkLoginOnUser(authUser.getUsername(), token);
//        }
        return ResponseUtil.success(authInfo);
    }
    @GetMapping(value = "/info")
    public ResponseVO<Object> getUserInfo() {
        Integer administratorIdentity = SecurityUtils.getAdministratorIdentity();
        Long userId = SecurityUtils.getUserId();
        Admin admin = adminService.getById(userId);
        List<Role> roles = roleService.listByAdminId(admin.getId());
        if(CollectionUtil.isEmpty(roles)){
            return ResponseUtil.fail("用户没有角色,无法获取数据");
        }
        List<Menu> menus = menuService.listByRoleIds(roles.stream().map(Role::getId).collect(Collectors.toList()));
        MapBuilder<Object, Object> builder = MapUtil.builder().put("info", admin);
        if(CollectionUtil.isNotEmpty(menus)){
        List<Menu> collect = menus.stream().filter(menu -> menu.getType() == 0).collect(Collectors.toList());
        MapBuilder<Object, Object> builder = MapUtil.builder().put("admin", admin);
        if (CollectionUtil.isNotEmpty(menus)) {
            List<Menu> collect = menus.stream().filter(menu -> menu.getType() == 0 || menu.getType() == 1).collect(Collectors.toList());
            builder.put("menus", collect);
        }
        return ResponseUtil.success(builder.build());
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/IpVolumeFileController.java
@@ -43,6 +43,6 @@
        if (null != keyword) {
            wrapper.like(IpVolumeFile::getFileName, keyword);
        }
        return ResponseUtil.success(ipVolumeFileService.list(wrapper));
        return ResponseUtil.successPage(ipVolumeFileService.list(wrapper));
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/MenuController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
package com.sandu.ximon.admin.controller;
import com.sandu.common.domain.ResponseVO;
import com.sandu.common.util.ResponseUtil;
import com.sandu.ximon.admin.param.MenuParam;
import com.sandu.ximon.admin.service.MenuService;
import com.sandu.ximon.dao.bo.MenuNode;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * @author chenjiantian
 * @date 2021/4/27 18:47
 */
@AllArgsConstructor
@RestController
@RequestMapping("/admin/menu")
public class MenuController {
    private final MenuService menuService;
//    @GetMapping("treeMenuList")
//    @PreAuthorize("@el.check('menu:list','role:list')")
//    public ResponseVO<Object> treeMenuList() {
//        List<Menu> list = menuService.list(Wrappers.lambdaQuery(Menu.class).eq(Menu::getType, 0));
//        List<MenuNode> menuTrees = menuService.buildTree(list);
//        return ResponseUtil.success(menuTrees);
//    }
    @GetMapping("/treeList")
    public ResponseVO<Object> treeList() {
        List<MenuNode> menuTrees = menuService.treeList();
        return ResponseUtil.success(menuTrees);
    }
    @PostMapping("/update/{menuId}")
    public ResponseVO<Object> update(@PathVariable Long menuId, @Validated @RequestBody MenuParam param) {
        boolean result = menuService.updateMenu(menuId,param);
        if (result) {
            return ResponseUtil.success("添加成功");
        } else {
            return ResponseUtil.fail("添加失败");
        }
    }
    @PostMapping
    public ResponseVO<Object> addMenu(@Validated @RequestBody MenuParam param) {
        boolean result = menuService.addMenu(param);
        if (result) {
            return ResponseUtil.success("添加成功");
        } else {
            return ResponseUtil.fail("添加失败");
        }
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/PoleController.java
@@ -74,9 +74,11 @@
    /**
     * è®¾ç½®ä¸‰å…ƒç 
     */
    @PostMapping("/setMac/{baseMac}")
    @PostMapping("/setMac")
    public ResponseVO<Object> setMac(@PathVariable String baseMac) {
    //public ResponseVO<Object> setMac() {
        return ResponseUtil.success(poleService.setMac(baseMac));
       // return ResponseUtil.success(poleService.setMac());
    }
    /**
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/amqp/processor/LightDataProcessor.java
@@ -38,8 +38,10 @@
            log.info("心跳相应");
            A5LightHeartbeatReportInnerFrame heartbeatReportInnerFrame = new A5LightHeartbeatReportInnerFrame().transformFrame(frame.getPayload());
            SpringContextHolder.getBean(LightReportDataService.class).saveReportData(deviceName, heartbeatReportInnerFrame.getHeartBeatDataPackage());
            SpringContextHolder.getBean(LightService.class).saveLight(deviceName,heartbeatReportInnerFrame.getHeartBeatDataPackage());
            if (heartbeatReportInnerFrame.isValidate()) {
                SpringContextHolder.getBean(LightReportDataService.class).saveReportData(deviceName, heartbeatReportInnerFrame.getHeartBeatDataPackage());
                SpringContextHolder.getBean(LightService.class).saveLight(deviceName, heartbeatReportInnerFrame.getHeartBeatDataPackage());
            }
        } else if (A5LightReportEnum.Time_Synchronized.getCode().equals(functionCode)) {
//            log.info("请求时间同步");
@@ -48,7 +50,7 @@
        } else if (A5LightReportEnum.Error_Code.getCode().equals(functionCode)) {
            log.info("故障码上报");
            A5LightErrorCodeReportInnerFrame codeRespInnerFrame = new A5LightErrorCodeReportInnerFrame().transformFrame(frame.getPayload());
            if (codeRespInnerFrame.getErrorCode() != 0) {
            if (codeRespInnerFrame.isValidate() && codeRespInnerFrame.getErrorCode() != 0) {
                SpringContextHolder.getBean(LightReportErrorService.class).saveReportError(deviceName, codeRespInnerFrame);
            }
        }
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/BaseInvokeSyncService.java
@@ -61,8 +61,7 @@
        result = result.replace("\\", "");
        Map map = JSON.parseObject(result, Map.class);
        result = (String) map.get("msg");
        CommonFrame connectFrame = FrameUtils.transformMessageToFrame(result);
        return connectFrame;
        return FrameUtils.transformMessageToFrame(result);
    }
    /**
ximon-admin/src/main/java/com/sandu/ximon/admin/param/MenuParam.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
package com.sandu.ximon.admin.param;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
 * @author chenjiantian
 * @date 2022/1/17 18:11
 */
@Data
public class MenuParam {
    /**
     * èœå•title
     */
    @NotBlank(message = "菜单名称不能为空")
    private String title;
    /**
     * ä¸Šçº§èœå•ID
     */
    private Long pid;
    /**
     * æŽ’序
     */
    private Integer seq;
    /**
     * èœå•图标
     */
    private String icon;
    /**
     * è¯·æ±‚路径
     */
    private String path;
    /**
     * èœå•是否隐藏
     */
    private Boolean hidden;
    /**
     * ç»„件路径映射
     */
    private String component;
    /**
     * è·¯ç”±åç§°
     */
    private String routerName;
    /**
     * æƒé™åç§°
     */
    private String permission;
    /**
     * ç±»åž‹ï¼Œ0:菜单,1:按钮
     */
    private Integer type;
}
ximon-admin/src/main/java/com/sandu/ximon/admin/security/SecurityUtils.java
@@ -1,27 +1,11 @@
/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * æ³¨æ„ï¼š
 * æœ¬è½¯ä»¶ä¸ºwww.yixiang.co开发研制
 */
package com.sandu.ximon.admin.security;
import cn.hutool.json.JSONObject;
import com.sandu.common.enums.ResponseStatusEnums;
import com.sandu.common.execption.BusinessException;
import com.sandu.common.redis.online.OnlineUser;
import com.sandu.common.redis.online.OnlineUserService;
import com.sandu.common.security.config.SecurityProperties;
import com.sandu.common.security.jwt.JwtTokenProvider;
import com.sandu.common.util.RequestHolder;
import com.sandu.common.util.SpringContextHolder;
import com.sandu.common.security.LoginUserInfo;
import com.sandu.ximon.dao.enums.AdministratorEnums;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import javax.servlet.http.HttpServletRequest;
/**
 * èŽ·å–å½“å‰ç™»å½•çš„ç”¨æˆ·
@@ -34,22 +18,18 @@
    /**
     * èŽ·å–å½“å‰ç™»å½•ç”¨æˆ·ä¿¡æ¯
     */
    private static UserDetails getUserDetails() {
    private static LoginUserInfo getUserDetails() {
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            throw new BusinessException(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage());
        }
        Integer administratorIdentity = getAdministratorIdentity();
        if (AdministratorEnums.ADMIN.getCode().equals(administratorIdentity)) {
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            UserDetailsService userDetailsService = SpringContextHolder.getBean("adminDetailsService");
            return userDetailsService.loadUserByUsername(userDetails.getUsername());
        } else if (AdministratorEnums.CUSTOMER.getCode().equals(administratorIdentity)) {
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            UserDetailsService userDetailsService = SpringContextHolder.getBean("customerDetailsService");
            return userDetailsService.loadUserByUsername(userDetails.getUsername());
        if (authentication.getPrincipal() instanceof LoginUserInfo) {
            LoginUserInfo loginUserInfo = (LoginUserInfo) authentication.getPrincipal();
            if (!loginUserInfo.isEnabled()) {
                throw new BusinessException(ResponseStatusEnums.DISABLE_ACCOUNT.getCode(), ResponseStatusEnums.DISABLE_ACCOUNT.getMessage());
            }
            return loginUserInfo;
        }
        return null;
    }
@@ -59,12 +39,11 @@
     * @return å½“前登录用户登录名
     */
    public static String getUsername() {
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            throw new BusinessException(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage());
        LoginUserInfo loginUserInfo = getUserDetails();
        if (loginUserInfo != null) {
            return loginUserInfo.getUsername();
        }
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        return userDetails.getUsername();
        return null;
    }
    /**
@@ -73,11 +52,11 @@
     * @return
     */
    public static Integer getAdministratorIdentity() {
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
        LoginUserInfo loginUserInfo = getUserDetails();
        if (loginUserInfo == null) {
            throw new BusinessException(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage());
        }
        return (Integer) authentication.getCredentials();
        return loginUserInfo.getAdministratorType();
    }
    /**
@@ -86,39 +65,25 @@
     * @return å½“前登录账号的id
     */
    public static Long getUserId() {
        SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
        if (!properties.isCacheOnline()) {
            UserDetails obj = getUserDetails();
            if (obj == null) {
                return null;
            }
            if (!obj.isEnabled()) {
                throw new BusinessException(ResponseStatusEnums.DISABLE_ACCOUNT.getCode(), ResponseStatusEnums.DISABLE_ACCOUNT.getMessage());
            }
            JSONObject json = new JSONObject(obj);
            return json.getJSONObject("user").get("id", Long.class);
        } else {
            HttpServletRequest httpServletRequest = RequestHolder.getHttpServletRequest();
            JwtTokenProvider tokenProvider = SpringContextHolder.getBean(JwtTokenProvider.class);
            OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
            String username = tokenProvider.getSubjectForce(tokenProvider.getToken(httpServletRequest));
            OnlineUser one = onlineUserService.getOne(properties.getOnlineKey() + username);
            if (one != null) {
                return one.getUserId();
            } else {
                return null;
            }
        LoginUserInfo loginUserInfo = getUserDetails();
        if (loginUserInfo != null) {
            return loginUserInfo.getUserId();
        }
        return null;
    }
    /**
     * èŽ·å–å®¢æˆ·è´¦å·çš„id å¦‚果当前身份是运营人员,返回null
     *
     * @return
     */
    public static Long getClientId() {
        Integer administratorIdentity = SecurityUtils.getAdministratorIdentity();
        if (AdministratorEnums.CUSTOMER.getCode().equals(administratorIdentity)) {
            return SecurityUtils.getUserId();
        LoginUserInfo loginUserInfo = getUserDetails();
        if (loginUserInfo == null) {
            return null;
        }
        if (AdministratorEnums.CUSTOMER.getCode().equals(loginUserInfo.getAdministratorType())) {
            return loginUserInfo.getUserId();
        }
        return null;
    }
ximon-admin/src/main/java/com/sandu/ximon/admin/service/LightService.java
@@ -131,25 +131,30 @@
        for (LightControlParam param : paramList) {
            A5LightBrightnessReqInnerFrame lightControlFrame = new A5LightBrightnessReqInnerFrame(param.getBrightness());
            A5Frame a5Frame = new A5Frame(A5OrderEnum.REQUEST_LIGHT_DATA.getCode(), lightControlFrame);
            WrapResponseCommonFrame<A5LightBrightnessRespInnerFrame> frame = MainBoardInvokeSyncService.getInstance()
                    .sendRRPC(param.getDeviceCode(), a5Frame, A5LightBrightnessRespInnerFrame.class);
            Map<String, Object> map = new HashMap<>();
            map.put("deviceCode", param.getDeviceCode());
            if (frame == null) {
            try {
                map.put("deviceCode", param.getDeviceCode());
                WrapResponseCommonFrame<A5LightBrightnessRespInnerFrame> frame = MainBoardInvokeSyncService.getInstance()
                        .sendRRPC(param.getDeviceCode(), a5Frame, A5LightBrightnessRespInnerFrame.class);
                if (frame == null) {
                    map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode());
                    resultList.add(map);
                    continue;
                }
                String responseStatus = frame.getResponseInnerFrame().getResponseStatus();
                int status = HexUtil.hexToInt(responseStatus);
                map.put("status", status);
                resultList.add(map);
                // æ›´æ–°äº®åº¦æˆåŠŸï¼Œä¿®æ”¹åˆ°æ•°æ®åº“
                if (DeviceRespStatusEnums.SUCCESS.getCode().equals(status)) {
                    Light light = new Light();
                    light.setLightPercent(param.getBrightness());
                    update(light, Wrappers.lambdaUpdate(Light.class).eq(Light::getDeviceCode, param.getDeviceCode()));
                }
            }catch (BusinessException e){
                map.put("status", DeviceRespStatusEnums.OTHER_ERROR.getCode());
                resultList.add(map);
                continue;
            }
            String responseStatus = frame.getResponseInnerFrame().getResponseStatus();
            int status = HexUtil.hexToInt(responseStatus);
            map.put("status", status);
            resultList.add(map);
            // æ›´æ–°äº®åº¦æˆåŠŸï¼Œä¿®æ”¹åˆ°æ•°æ®åº“
            if (DeviceRespStatusEnums.SUCCESS.getCode().equals(status)) {
                Light light = new Light();
                light.setLightPercent(param.getBrightness());
                update(light, Wrappers.lambdaUpdate(Light.class).eq(Light::getDeviceCode, param.getDeviceCode()));
            }
        }
ximon-admin/src/main/java/com/sandu/ximon/admin/service/LightTaskService.java
@@ -85,7 +85,7 @@
        List<Long> poleIdList = param.getPoleIdList();
        if (CollectionUtil.isNotEmpty(poleIdList)) {
            List<LightTaskPoleRelation> lightTaskPoleRelationList = sendControllerFrame(lightTask, poleIdList,lightTask.getFramePayload());
            List<LightTaskPoleRelation> lightTaskPoleRelationList = sendControllerFrame(lightTask, poleIdList, lightTask.getFramePayload());
            // æ·»åŠ ç»‘å®šç¯æ†
            if (!lightTaskPoleRelationService.saveBatch(lightTaskPoleRelationList)) {
@@ -126,7 +126,7 @@
        List<Long> poleIdList = param.getPoleIdList();
        if (CollectionUtil.isNotEmpty(poleIdList)) {
            List<LightTaskPoleRelation> lightTaskPoleRelationList = sendControllerFrame(lightTask, poleIdList,lightTask.getFramePayload());
            List<LightTaskPoleRelation> lightTaskPoleRelationList = sendControllerFrame(lightTask, poleIdList, lightTask.getFramePayload());
            lightTaskPoleRelationService.remove(Wrappers.lambdaQuery(LightTaskPoleRelation.class).eq(LightTaskPoleRelation::getTaskId, lightTask.getTaskId()));
            // æ·»åŠ ç»‘å®šç¯æ†
@@ -181,7 +181,7 @@
    }
    // æ¯ä¸ªè·¯ç¯å‘送控制帧 è¿”回关联列表
    private List<LightTaskPoleRelation> sendControllerFrame(LightTask lightTask, List<Long> poleIdList,String framePayload) {
    private List<LightTaskPoleRelation> sendControllerFrame(LightTask lightTask, List<Long> poleIdList, String framePayload) {
        List<LightTaskPoleRelation> lightTaskPoleRelationList = new ArrayList<>();
        List<Pole> poles = poleService.listByIds(poleIdList);
@@ -190,17 +190,21 @@
        }
        for (Pole pole : poles) {
            // rrpc å‘生定时命令
            A5LightTimerRespInnerFrame a5LightTimerRespInnerFrame = sendTimeRRpc(framePayload, pole.getDeviceCode());
            LightTaskPoleRelation lightTaskPoleRelation = new LightTaskPoleRelation();
            lightTaskPoleRelation.setPoleId(pole.getId());
            lightTaskPoleRelation.setTaskId(lightTask.getTaskId());
            if (a5LightTimerRespInnerFrame == null) {
            // rrpc å‘生定时命令
            try {
                A5LightTimerRespInnerFrame a5LightTimerRespInnerFrame = sendTimeRRpc(framePayload, pole.getDeviceCode());
                if (a5LightTimerRespInnerFrame == null) {
                    lightTaskPoleRelation.setIssueStatus(DeviceRespStatusEnums.OTHER_ERROR.getCode());
                } else {
                    lightTaskPoleRelation.setIssueStatus(HexUtil.hexToInt(a5LightTimerRespInnerFrame.getResponseStatus()));
                }
            } catch (BusinessException e) {
                lightTaskPoleRelation.setIssueStatus(DeviceRespStatusEnums.OTHER_ERROR.getCode());
            } else {
                lightTaskPoleRelation.setIssueStatus(HexUtil.hexToInt(a5LightTimerRespInnerFrame.getResponseStatus()));
            }
            lightTaskPoleRelationList.add(lightTaskPoleRelation);
        }
        return lightTaskPoleRelationList;
@@ -288,7 +292,6 @@
    /**
     * ä¸‹å‘单个灯杆的任务
     *
     */
    public boolean issueLightTask(LightTaskIssueParam param) {
        LightTask lightTask = getById(param.getTaskId());
@@ -296,7 +299,7 @@
            throw new BusinessException("找不到任务");
        }
        String framePayload = buildControlFramePayload(lightTask.getOpenOrder(), lightTask.getCloseOrder(), lightTask.getControlOrder(), lightTask.getWeek());
        List<LightTaskPoleRelation> lightTaskPoleRelationList = sendControllerFrame(lightTask, ListUtil.toList(param.getPoleId()),framePayload);
        List<LightTaskPoleRelation> lightTaskPoleRelationList = sendControllerFrame(lightTask, ListUtil.toList(param.getPoleId()), framePayload);
        if (CollectionUtil.isNotEmpty(lightTaskPoleRelationList)) {
            return lightTaskPoleRelationService.update(lightTaskPoleRelationList.get(0),
                    Wrappers.lambdaUpdate(LightTaskPoleRelation.class).eq(LightTaskPoleRelation::getPoleId, param.getPoleId())
ximon-admin/src/main/java/com/sandu/ximon/admin/service/MenuService.java
@@ -3,13 +3,18 @@
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sandu.common.execption.BusinessException;
import com.sandu.common.execption.EntityExistException;
import com.sandu.common.service.impl.BaseServiceImpl;
import com.sandu.ximon.admin.param.MenuParam;
import com.sandu.ximon.dao.bo.MenuNode;
import com.sandu.ximon.dao.domain.AdminRoleRelation;
import com.sandu.ximon.dao.domain.Menu;
import com.sandu.ximon.dao.domain.RoleMenuRelation;
import com.sandu.ximon.dao.mapper.AdminRoleRelationMapper;
import com.sandu.ximon.dao.mapper.MenuMapper;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -34,7 +39,56 @@
        if (CollectionUtil.isEmpty(menuIdList)) {
            return null;
        }
        List<Menu> menus = listByIds(menuIdList);
        return menus;
        return listByIds(menuIdList);
    }
    public boolean addMenu(MenuParam param) {
        Menu menu = new Menu();
        BeanUtils.copyProperties(param,menu);
        return save(menu);
    }
//    public Set<Menu> listMenuByRoles(Set<Role> roles) {
//        List<Long> roleIds = roles.stream().map(Role::getId).collect(Collectors.toList());
//        Set<Menu> menus = menuDao.listMenuByRoleIds(roleIds);
//        return menus;
//    }
//
//    /**
//     * æŠŠèœå•转成树形结构
//     */
//    public List<MenuNode> buildTree(List<Menu> menuList) {
//        return menuList.stream()
//                .filter(menu -> menu.getPid().equals(0L))
//                .map(menu -> covertMenuNode(menu, menuList)).collect(Collectors.toList());
//    }
    private MenuNode covertMenuNode(Menu menu, List<Menu> menuList) {
        MenuNode node = new MenuNode();
        BeanUtils.copyProperties(menu, node);
        List<MenuNode> children = menuList.stream()
                .filter(subMenu -> subMenu.getPid().equals(menu.getId()))
                .map(subMenu -> covertMenuNode(subMenu, menuList)).collect(Collectors.toList());
        node.setChildren(children);
        return node;
    }
    public boolean updateMenu(Long menuId,MenuParam param) {
        Menu one = getById(menuId);
        if (one == null) {
            throw new BusinessException("找不到菜单信息");
        }
        Menu menu = new Menu();
        BeanUtils.copyProperties(param,menu);
        menu.setId(menuId);
        return updateById(menu);
    }
    public List<MenuNode> treeList() {
        List<Menu> list = list();
        return list.stream()
                .filter(menu -> menu.getPid().equals(0L))
                .map(menu -> covertMenuNode(menu, list)).collect(Collectors.toList());
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/service/PoleService.java
@@ -209,13 +209,14 @@
    public boolean setMac(String baseMac) {
   // public boolean setMac() {
        //Pole pole = getById(poleId);
       /* if (pole == null) {
            throw new BusinessException("未找到该灯杆");
        }*/
        boolean setMac = false;
        // String baseMac = "baseDevice";
         //String baseMac = "baseDevice";
        A1Frame a1Frame = new A1Frame(A1OrderEnum.REQUEST_READ_DEVICE_UNIQUE_MAC.getCode(), new EmptyRequestInnerFrame());
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance()
                .sendRRPC(baseMac, a1Frame);
ximon-admin/src/main/resources/application-test.yml
@@ -25,7 +25,7 @@
    # ä»¤ç‰Œè¿‡æœŸæ—¶é—´ æ­¤å¤„单位/毫秒 ï¼Œå¯åœ¨æ­¤ç½‘站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html 1个月
    token-validity-in-seconds: 2629800000
    # åœ¨çº¿ç”¨æˆ·key
    online-key: online-token
    online-key: light-user
    # æ˜¯å¦å¯åЍredis缓存用户信息
    cache-online: false
  upload:
ximon-admin/src/test/java/com/sandu/ximon/admin/BaseTopicTests.java
@@ -1,8 +1,10 @@
package com.sandu.ximon.admin;
import cn.hutool.core.collection.CollectionUtil;
import com.aliyuncs.iot.model.v20180120.QueryDeviceDetailResponse;
import com.aliyuncs.iot.model.v20180120.RegisterDeviceResponse;
import com.sandu.common.execption.BusinessException;
import com.sandu.ximon.admin.dto.DeviceStatus;
import com.sandu.ximon.admin.manager.iot.frame.A1Frame;
import com.sandu.ximon.admin.manager.iot.frame.A5Frame;
import com.sandu.ximon.admin.manager.iot.frame.FrameBuilder;
@@ -18,31 +20,49 @@
import com.sandu.ximon.admin.manager.iot.rrpc.enums.A2OrderEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.A5OrderEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.mainboard.MainBoardInvokeSyncService;
import com.sandu.ximon.admin.service.PoleService;
import com.sandu.ximon.admin.service.RoleMenuRelationService;
import com.sandu.ximon.dao.domain.RoleMenuRelation;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
@Slf4j
class BaseTopicTests {
@Autowired
    PoleService poleService;
@Autowired
    RoleMenuRelationService roleMenuRelationService;
    // æŸ¥è¯¢è®¾å¤‡è¯¦æƒ…
    @Test
    void queryDeviceDetail() {
        QueryDeviceDetailResponse.Data data = MainBoardInvokeSyncService.getInstance().queryDeviceDetail("baseDevice", null);
        QueryDeviceDetailResponse.Data data = MainBoardInvokeSyncService.getInstance().queryDeviceDetail("32313243305007ff8d60ffff", null);
        System.out.println(data.toString());
        List<DeviceStatus> statusList = poleService.listStatusByDeviceCode(CollectionUtil.toList("32313243305008ff0805ffff","32313243305007ff8d60ffff"));
        System.out.println(statusList);
    }
    // æŽ§åˆ¶ç¯çš„亮度级别 0-100
    @Test
    void rrpcLightControl() {
        // 32313243305008ff1a06ffff
        A5LightBrightnessReqInnerFrame lightControlFrame = new A5LightBrightnessReqInnerFrame(80);
        A5Frame a5Frame = new A5Frame(A5OrderEnum.REQUEST_LIGHT_DATA.getCode(), lightControlFrame);
        WrapResponseCommonFrame<A5LightBrightnessRespInnerFrame> frame = MainBoardInvokeSyncService.getInstance()
                .sendRRPC("32313243305008ff1a06ffff", a5Frame, A5LightBrightnessRespInnerFrame.class);
        System.out.println(frame.toString());
        try {
            WrapResponseCommonFrame<A5LightBrightnessRespInnerFrame> frame = MainBoardInvokeSyncService.getInstance()
                    .sendRRPC("32313243305005ff2930ffff", a5Frame, A5LightBrightnessRespInnerFrame.class);
            System.out.println(frame.toString());
        }catch (BusinessException e){
            e.printStackTrace();
        }
    }