From bf15d653248d55ba674b5dbd8b5ace17f09fb2fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=A5=88=E7=A7=91=E6=96=AF=EF=BC=88NexIoT=EF=BC=89?=
<16120872+nexiot@user.noreply.gitee.com>
Date: Tue, 7 Oct 2025 12:33:49 +0800
Subject: [PATCH] =?UTF-8?q?news=EF=BC=9A=E8=B0=83=E6=95=B4security?=
=?UTF-8?q?=E5=92=8Cadmin=E7=9A=84=E6=A8=A1=E5=9D=97=E5=85=B3=E7=B3=BB?=
=?UTF-8?q?=EF=BC=8C=E4=B8=BA=E5=90=8E=E7=BB=AD=E6=8F=92=E4=BB=B6=E5=92=8C?=
=?UTF-8?q?=E6=A8=A1=E5=9D=97=E6=8F=90=E4=BE=9B=E6=9B=B4=E5=A5=BD=E7=9A=84?=
=?UTF-8?q?=E6=89=A9=E5=B1=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
cn-universal-admin/pom.xml | 18 ++
.../admin/common/aspectj/DataScopeAspect.java | 12 +-
.../admin/common/aspectj/LogAspect.java | 22 +-
.../admin/common/service/BaseServiceImpl.java | 8 +-
.../admin/config/SecurityConfig.java | 27 --
.../service/GenTableServiceImpl.java | 2 +-
.../admin/generator/web/GenController.java | 2 +-
.../service/impl/NetworkServiceImpl.java | 60 ++--
.../admin/network/utils/UserContextUtil.java | 2 +-
.../admin/network/web/NetworkController.java | 8 +-
.../IoTDeviceFunctionTaskServiceImpl.java | 2 +-
.../impl/IoTDeviceGroupServiceImpl.java | 2 +-
.../service/impl/IoTDeviceServiceImpl.java | 2 +-
.../service/impl/IoTProductServiceImpl.java | 2 +-
.../impl/IoTProductSortServiceImpl.java | 2 +-
.../platform/web/IoTBatchFunsController.java | 4 +-
.../web/IoTCertificateController.java | 4 +-
.../platform/web/IoTDeviceController.java | 42 +--
.../web/IoTDeviceGroupController.java | 6 +-
.../platform/web/IoTDeviceLogController.java | 2 +-
.../web/IoTDeviceLogV1Controller.java | 2 +-
.../web/IoTDeviceProtocolController.java | 8 +-
.../web/IoTDeviceSubscribeController.java | 6 +-
.../web/IoTProductCategoryController.java | 6 +-
.../platform/web/IoTProductController.java | 18 +-
.../platform/web/IoTUserAppController.java | 18 +-
.../admin/platform/web/IoTUserController.java | 58 ++--
.../system/monitor/SysLoginLogController.java | 8 +-
.../system/monitor/SysOperlogController.java | 8 +-
.../notice/NoticeChannelController.java | 4 +-
.../system/notice/NoticeRecordController.java | 2 +-
.../notice/NoticeTemplateController.java | 4 +-
.../admin/system/oss/SysOssController.java | 4 +-
.../admin/system/quartz/SysJobController.java | 4 +-
.../system/quartz/SysJobLogController.java | 2 +-
.../impl/IoTDeviceSubscribeServiceImpl.java | 2 +-
.../impl/IoTUserApplicationServiceImpl.java | 8 +-
.../service/impl/SysDictDataServiceImpl.java | 2 +-
.../service/impl/SysMenuServiceImpl.java | 8 +-
.../service/impl/SysRoleServiceImpl.java | 4 +-
.../admin/system/web/IndexController.java | 3 +-
.../admin/system/web/RuleController.java | 11 +-
.../system/web/RulegoChainController.java | 7 +-
.../system/web/SceneLinkageController.java | 7 +-
.../admin/system/web/SysConfigController.java | 7 +-
.../system/web/SysDictDataController.java | 3 +-
.../system/web/SysDictTypeController.java | 3 +-
.../admin/system/web/SysMenuController.java | 7 +-
.../system/web/SysProfileController.java | 25 +-
.../admin/system/web/SysRoleController.java | 21 +-
.../admin/system/web/SysUserController.java | 8 +-
.../system/web/SystemProtocolController.java | 1 +
.../main/resources/vm/java/controller.java.vm | 2 +-
.../resources/vm/java/serviceImpl.java.vm | 2 +-
.../cn-universal-common/pom.xml | 6 +
.../common/annotation/DataScope.java | 2 +-
.../cn/universal}/common/annotation/Log.java | 6 +-
.../common/enums/BusinessStatus.java | 2 +-
.../universal}/common/enums/BusinessType.java | 2 +-
.../universal}/common/enums/HttpMethod.java | 2 +-
.../universal}/common/enums/OperatorType.java | 2 +-
.../universal/common/utils/LocationUtils.java | 290 ++++++++++++++++++
.../src/main/resources/ip2region_v4.xdb | Bin 0 -> 11042429 bytes
.../cn-universal-security/pom.xml | 6 -
.../universal/security}/BaseController.java | 22 +-
.../security/KiteUserDetailsService.java | 8 +-
.../OAuth2CaptchaAuthenticationProvider.java | 14 +-
.../provider/SmsAuthenticationProvider.java | 15 +-
.../security/service/AdminLogService.java | 75 +++--
.../security/service/IoTUserService.java | 144 ++-------
.../service/impl/IoTUserServiceImpl.java | 30 +-
.../security}/utils/SecurityUtils.java | 21 +-
.../persistence/page}/PageUtils.java | 9 +-
.../persistence/query/IoTAPIQuery.java | 10 +-
.../resources/mybatis/IoTDeviceMapper.xml | 3 +
.../web/controller/DashboardController.java | 22 +-
.../web/controller/FenceController.java | 2 +-
.../web/controller/IoTApiController.java | 49 +--
.../controller/common/BaseApiController.java | 11 +-
79 files changed, 737 insertions(+), 528 deletions(-)
delete mode 100644 cn-universal-admin/src/main/java/cn/universal/admin/config/SecurityConfig.java
rename {cn-universal-admin/src/main/java/cn/universal/admin => cn-universal-framework/cn-universal-common/src/main/java/cn/universal}/common/annotation/DataScope.java (93%)
rename {cn-universal-admin/src/main/java/cn/universal/admin => cn-universal-framework/cn-universal-common/src/main/java/cn/universal}/common/annotation/Log.java (86%)
rename {cn-universal-admin/src/main/java/cn/universal/admin => cn-universal-framework/cn-universal-common/src/main/java/cn/universal}/common/enums/BusinessStatus.java (90%)
rename {cn-universal-admin/src/main/java/cn/universal/admin => cn-universal-framework/cn-universal-common/src/main/java/cn/universal}/common/enums/BusinessType.java (93%)
rename {cn-universal-admin/src/main/java/cn/universal/admin => cn-universal-framework/cn-universal-common/src/main/java/cn/universal}/common/enums/HttpMethod.java (95%)
rename {cn-universal-admin/src/main/java/cn/universal/admin => cn-universal-framework/cn-universal-common/src/main/java/cn/universal}/common/enums/OperatorType.java (90%)
create mode 100644 cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/utils/LocationUtils.java
create mode 100644 cn-universal-framework/cn-universal-common/src/main/resources/ip2region_v4.xdb
rename {cn-universal-admin/src/main/java/cn/universal/admin/system/web => cn-universal-infrastructure/cn-universal-security/src/main/java/cn/universal/security}/BaseController.java (83%)
rename cn-universal-admin/src/main/java/cn/universal/admin/system/service/AsyncService.java => cn-universal-infrastructure/cn-universal-security/src/main/java/cn/universal/security/service/AdminLogService.java (57%)
rename cn-universal-admin/src/main/java/cn/universal/admin/system/service/IIotUserService.java => cn-universal-infrastructure/cn-universal-security/src/main/java/cn/universal/security/service/IoTUserService.java (37%)
rename {cn-universal-admin/src/main/java/cn/universal/admin/system => cn-universal-infrastructure/cn-universal-security/src/main/java/cn/universal/security}/service/impl/IoTUserServiceImpl.java (89%)
rename {cn-universal-admin/src/main/java/cn/universal/admin/common => cn-universal-infrastructure/cn-universal-security/src/main/java/cn/universal/security}/utils/SecurityUtils.java (87%)
rename {cn-universal-admin/src/main/java/cn/universal/admin/common/utils => cn-universal-persistence/src/main/java/cn/universal/persistence/page}/PageUtils.java (79%)
diff --git a/cn-universal-admin/pom.xml b/cn-universal-admin/pom.xml
index 4e13709..90e910d 100644
--- a/cn-universal-admin/pom.xml
+++ b/cn-universal-admin/pom.xml
@@ -114,12 +114,30 @@
${project.version}
compile
+
+ cn.universal.iot
+ cn-tcp-protocol
+ compile
+ ${project.version}
+
+
+ cn.universal.iot
+ cn-udp-protocol
+ compile
+ ${project.version}
+
cn.universal.iot
cn-universal-notice
${project.version}
compile
+
+ cn.universal.iot
+ cn-universal-security
+ ${project.version}
+ compile
+
\ No newline at end of file
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/common/aspectj/DataScopeAspect.java b/cn-universal-admin/src/main/java/cn/universal/admin/common/aspectj/DataScopeAspect.java
index c16de5f..2acb01f 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/common/aspectj/DataScopeAspect.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/common/aspectj/DataScopeAspect.java
@@ -14,9 +14,9 @@ package cn.universal.admin.common.aspectj;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
-import cn.universal.admin.common.annotation.DataScope;
-import cn.universal.admin.common.utils.SecurityUtils;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.common.annotation.DataScope;
+import cn.universal.security.utils.SecurityUtils;
+import cn.universal.security.service.IoTUserService;
import cn.universal.common.domain.BaseEntity;
import cn.universal.common.utils.ReflectUtils;
import cn.universal.persistence.entity.IoTUser;
@@ -39,10 +39,10 @@ public class DataScopeAspect {
/** 数据范围 */
public static final String SCOPE = "scope";
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
// 配置织入点
- @Pointcut("@annotation(cn.universal.admin.common.annotation.DataScope)")
+ @Pointcut("@annotation(cn.universal.common.annotation.DataScope)")
public void dataScopePointCut() {}
@Before("dataScopePointCut()")
@@ -57,7 +57,7 @@ public class DataScopeAspect {
if (controllerDataScope == null) {
return;
}
- IoTUser iotUser = iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId());
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId());
if (!iotUser.isAdmin()) {
dataScopeFilter(joinPoint, controllerDataScope, iotUser.getUnionId());
}
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/common/aspectj/LogAspect.java b/cn-universal-admin/src/main/java/cn/universal/admin/common/aspectj/LogAspect.java
index 589d26b..13ee936 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/common/aspectj/LogAspect.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/common/aspectj/LogAspect.java
@@ -15,16 +15,17 @@ package cn.universal.admin.common.aspectj;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessStatus;
-import cn.universal.admin.common.enums.HttpMethod;
-import cn.universal.admin.common.utils.SecurityUtils;
-import cn.universal.admin.system.service.AsyncService;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessStatus;
+import cn.universal.common.enums.HttpMethod;
+import cn.universal.common.utils.LocationUtils;
import cn.universal.common.utils.ServletUtils;
import cn.universal.common.utils.SpringUtils;
import cn.universal.persistence.entity.IoTUser;
import cn.universal.persistence.entity.SysOperLog;
+import cn.universal.security.service.AdminLogService;
+import cn.universal.security.service.IoTUserService;
+import cn.universal.security.utils.SecurityUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -50,11 +51,11 @@ import org.springframework.web.servlet.HandlerMapping;
@Component
public class LogAspect {
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
// 配置织入点
- @Pointcut("@annotation(cn.universal.admin.common.annotation.Log)")
+ @Pointcut("@annotation(cn.universal.common.annotation.Log)")
public void logPointCut() {}
/**
@@ -87,7 +88,7 @@ public class LogAspect {
}
// 获取当前的用户
- IoTUser iotUser = iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId());
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId());
// *========数据库日志=========*//
SysOperLog operLog = new SysOperLog();
@@ -95,6 +96,7 @@ public class LogAspect {
// 请求的地址
String ip = ServletUtils.getClientIP();
operLog.setOperIp(ip);
+ operLog.setOperLocation(LocationUtils.getLocationByIp(ip));
// 返回参数
operLog.setJsonResult(JSONUtil.toJsonStr(jsonResult));
@@ -116,7 +118,7 @@ public class LogAspect {
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog);
// 保存数据库
- SpringUtils.getBean(AsyncService.class).recordOper(operLog);
+ SpringUtils.getBean(AdminLogService.class).recordOper(operLog);
} catch (Exception exp) {
// 记录本地异常日志
log.error("==前置通知异常==");
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/common/service/BaseServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/common/service/BaseServiceImpl.java
index c16ba72..ece5604 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/common/service/BaseServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/common/service/BaseServiceImpl.java
@@ -12,21 +12,21 @@
package cn.universal.admin.common.service;
-import cn.universal.admin.system.service.IIotUserService;
import cn.universal.persistence.entity.IoTUser;
+import cn.universal.security.service.IoTUserService;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.Cacheable;
public class BaseServiceImpl implements BaseService {
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
@Override
@Cacheable(cacheNames = "user_parent_entity", key = "''+#unionId", unless = "#result == null")
public IoTUser queryIotUser(String unionId) {
- IoTUser iotUser = iIotUserService.selectUserByUnionId(unionId);
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(unionId);
if (iotUser.getParentUnionId() != null) {
- iotUser = iIotUserService.selectUserByUnionId(iotUser.getParentUnionId());
+ iotUser = ioTUserService.selectUserByUnionId(iotUser.getParentUnionId());
return iotUser;
}
return iotUser;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/config/SecurityConfig.java b/cn-universal-admin/src/main/java/cn/universal/admin/config/SecurityConfig.java
deleted file mode 100644
index 8056134..0000000
--- a/cn-universal-admin/src/main/java/cn/universal/admin/config/SecurityConfig.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package cn.universal.admin.config;
-
-import lombok.Data;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-/**
- * 安全配置
- * 管理敏感字段的加密密钥
- */
-@Data
-@Component
-public class SecurityConfig {
-
- /**
- * 产品密钥加密密钥
- * 建议在生产环境中使用环境变量或配置中心
- */
- @Value("${security.product-secret.key:cn-universal-product-secret-key-2024}")
- private String productSecretKey;
-
- /**
- * 是否启用敏感字段加密
- */
- @Value("${security.sensitive-field.enabled:true}")
- private Boolean sensitiveFieldEnabled;
-}
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/generator/service/GenTableServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/generator/service/GenTableServiceImpl.java
index 2e6a4f2..2ed10ea 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/generator/service/GenTableServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/generator/service/GenTableServiceImpl.java
@@ -14,7 +14,7 @@ package cn.universal.admin.generator.service;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.generator.constant.GenConstants;
import cn.universal.admin.generator.domain.GenTable;
import cn.universal.admin.generator.domain.GenTableColumn;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/generator/web/GenController.java b/cn-universal-admin/src/main/java/cn/universal/admin/generator/web/GenController.java
index 99a5c5f..29bf787 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/generator/web/GenController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/generator/web/GenController.java
@@ -17,7 +17,7 @@ import cn.universal.admin.generator.domain.GenTable;
import cn.universal.admin.generator.domain.GenTableColumn;
import cn.universal.admin.generator.service.IGenTableColumnService;
import cn.universal.admin.generator.service.IGenTableService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.persistence.page.TableDataInfo;
import cn.universal.persistence.query.AjaxResult;
import jakarta.servlet.http.HttpServletResponse;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/network/service/impl/NetworkServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/network/service/impl/NetworkServiceImpl.java
index 3300492..b59347e 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/network/service/impl/NetworkServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/network/service/impl/NetworkServiceImpl.java
@@ -17,7 +17,7 @@ import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.network.service.INetworkService;
import cn.universal.admin.network.utils.NetworkTypeUtil;
import cn.universal.common.constant.IoTConstant.DownCmd;
@@ -68,14 +68,10 @@ import tk.mybatis.mapper.entity.Example;
@Service
public class NetworkServiceImpl implements INetworkService {
- @Resource
- private NetworkMapper networkMapper;
- @Resource
- private IoTDeviceMapper ioTDeviceMapper;
- @Resource
- private IoTProductMapper ioTProductMapper;
- @Resource
- private IoTDeviceFenceRelMapper ioTDeviceFenceRelMapper;
+ @Resource private NetworkMapper networkMapper;
+ @Resource private IoTDeviceMapper ioTDeviceMapper;
+ @Resource private IoTProductMapper ioTProductMapper;
+ @Resource private IoTDeviceFenceRelMapper ioTDeviceFenceRelMapper;
// 直接注入 TCP 和 MQTT 服务
@Qualifier("tcpClusterService")
@@ -165,8 +161,7 @@ public class NetworkServiceImpl implements INetworkService {
IoTProduct ioTProduct = ioTProductMapper.getProductByProductKey(ioTDevice.getProductKey());
result = IoTDownlFactory.getIDown(ioTProduct.getThirdPlatform()).doAction(downRequest);
if (!result.getCode().equals(0)) {
- return R.error(
- "设备名称: " + ioTDevice.getDeviceName() + " 删除失败,原因: " + result.getMsg());
+ return R.error("设备名称: " + ioTDevice.getDeviceName() + " 删除失败,原因: " + result.getMsg());
}
ioTDeviceFenceRelMapper.deleteFenceInstance(ioTDevice.getIotId());
}
@@ -334,9 +329,7 @@ public class NetworkServiceImpl implements INetworkService {
return vo;
}
- /**
- * 检查端口是否被占用或为常用端口
- */
+ /** 检查端口是否被占用或为常用端口 */
private void checkPortAvailable(Network network, boolean isUpdate) {
if (StrUtil.isBlank(network.getConfiguration())) {
return;
@@ -349,7 +342,7 @@ public class NetworkServiceImpl implements INetworkService {
// 常用端口
Set commonPorts = new HashSet<>();
int[] arr = {
- 80, 443, 3306, 6379, 8080, 22, 21, 25, 53, 123, 1521, 5432, 8888, 9000, 5000, 7001, 27017
+ 80, 443, 3306, 6379, 8080, 22, 21, 25, 53, 123, 1521, 5432, 8888, 9000, 5000, 7001, 27017
};
for (int p : arr) {
commonPorts.add(p);
@@ -525,7 +518,7 @@ public class NetworkServiceImpl implements INetworkService {
log.info("启动网络组件成功: {}", network.getName());
return 1;
} else {
- throw new IoTException("系统协议类型模块不存在,请检查");
+ throw new RuntimeException("启动失败: " + network.getName());
}
} catch (Exception e) {
log.error("启动网络组件失败: {}", network.getName(), e);
@@ -656,7 +649,7 @@ public class NetworkServiceImpl implements INetworkService {
/**
* 检查网络组件配置的唯一性
*
- * @param network 网络组件
+ * @param network 网络组件
* @param excludeId 排除的网络组件ID(用于更新时排除自己)
*/
private void checkConfigurationUniqueness(Network network, Integer excludeId) {
@@ -720,18 +713,24 @@ public class NetworkServiceImpl implements INetworkService {
*/
private boolean startNetworkByType(Network network) {
String type = network.getType();
- switch (type) {
- case NetworkTypeConstants.TCP_CLIENT:
- case NetworkTypeConstants.TCP_SERVER:
- return startTcpNetwork(network);
- case NetworkTypeConstants.MQTT_CLIENT:
- case NetworkTypeConstants.MQTT_SERVER:
- return startMqttNetwork(network);
- case NetworkTypeConstants.UDP:
- return startUdpNetwork(network);
- default:
- log.warn("不支持的网络类型: {}", type);
- return false;
+
+ try {
+ switch (type) {
+ case NetworkTypeConstants.TCP_CLIENT:
+ case NetworkTypeConstants.TCP_SERVER:
+ return startTcpNetwork(network);
+ case NetworkTypeConstants.MQTT_CLIENT:
+ case NetworkTypeConstants.MQTT_SERVER:
+ return startMqttNetwork(network);
+ case NetworkTypeConstants.UDP:
+ return startUdpNetwork(network);
+ default:
+ log.warn("不支持的网络类型: {}", type);
+ return false;
+ }
+ } catch (Exception e) {
+ log.error("启动网络组件失败: type={}, name={}", type, network.getName(), e);
+ return false;
}
}
@@ -804,6 +803,7 @@ public class NetworkServiceImpl implements INetworkService {
throw new IoTException("TCP模块未注入,无法启动TCP网络组件");
}
+
String productKey = network.getProductKey();
if (StrUtil.isBlank(productKey)) {
log.error("TCP网络组件缺少productKey: {}", network.getName());
@@ -837,6 +837,7 @@ public class NetworkServiceImpl implements INetworkService {
throw new IoTException("TCP模块未注入,无法启动TCP网络组件");
}
+
String productKey = network.getProductKey();
if (StrUtil.isBlank(productKey)) {
log.error("TCP网络组件缺少productKey: {}", network.getName());
@@ -869,6 +870,7 @@ public class NetworkServiceImpl implements INetworkService {
throw new IoTException("TCP模块未注入,无法启动TCP网络组件");
}
+
String productKey = network.getProductKey();
if (StrUtil.isBlank(productKey)) {
log.error("TCP网络组件缺少productKey: {}", network.getName());
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/network/utils/UserContextUtil.java b/cn-universal-admin/src/main/java/cn/universal/admin/network/utils/UserContextUtil.java
index cf03da6..6278a5f 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/network/utils/UserContextUtil.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/network/utils/UserContextUtil.java
@@ -12,7 +12,7 @@
package cn.universal.admin.network.utils;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.persistence.entity.IoTUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/network/web/NetworkController.java b/cn-universal-admin/src/main/java/cn/universal/admin/network/web/NetworkController.java
index 1cd0310..4794602 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/network/web/NetworkController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/network/web/NetworkController.java
@@ -14,11 +14,11 @@ package cn.universal.admin.network.web;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.network.service.INetworkService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.common.domain.R;
import cn.universal.common.exception.IoTException;
import cn.universal.persistence.entity.IoTDevice;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceFunctionTaskServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceFunctionTaskServiceImpl.java
index c4d9229..7eeca9f 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceFunctionTaskServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceFunctionTaskServiceImpl.java
@@ -17,7 +17,7 @@ import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.universal.admin.common.service.BaseServiceImpl;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.platform.service.BatchFunctionTask;
import cn.universal.admin.platform.service.IIoTDeviceFunctionTaskService;
import cn.universal.common.exception.IoTException;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceGroupServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceGroupServiceImpl.java
index ad08cc7..a2f7543 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceGroupServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceGroupServiceImpl.java
@@ -14,7 +14,7 @@ package cn.universal.admin.platform.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.universal.admin.common.service.BaseServiceImpl;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.platform.service.IIoTDeviceGroupService;
import cn.universal.persistence.dto.IoTDeviceDTO;
import cn.universal.persistence.entity.IoTDevice;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceServiceImpl.java
index a695f67..77493ed 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTDeviceServiceImpl.java
@@ -19,7 +19,7 @@ import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.universal.admin.common.service.BaseServiceImpl;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.platform.service.IIoTDeviceService;
import cn.universal.common.constant.IoTConstant.DeviceNode;
import cn.universal.common.constant.IoTConstant.DownCmd;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTProductServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTProductServiceImpl.java
index 72c2323..537dd5f 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTProductServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTProductServiceImpl.java
@@ -27,7 +27,7 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.universal.dm.device.service.protocol.ProtocolClusterService;
import cn.universal.admin.common.service.BaseServiceImpl;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.platform.service.IIoTProductService;
import cn.universal.admin.system.service.IoTDeviceProtocolService;
import cn.universal.cache.annotation.MultiLevelCacheable;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTProductSortServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTProductSortServiceImpl.java
index 58381ad..3ca394f 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTProductSortServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/service/impl/IoTProductSortServiceImpl.java
@@ -13,7 +13,7 @@
package cn.universal.admin.platform.service.impl;
import cn.hutool.core.util.StrUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.platform.service.IIoTProductSortService;
import cn.universal.persistence.entity.IoTProductSort;
import cn.universal.persistence.entity.bo.RuleModelBO.IoTProductSortBO;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTBatchFunsController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTBatchFunsController.java
index 35d3725..b0a197e 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTBatchFunsController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTBatchFunsController.java
@@ -13,11 +13,11 @@
package cn.universal.admin.platform.web;
import cn.hutool.core.util.StrUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.platform.service.IIoTDeviceFunctionTaskService;
import cn.universal.admin.platform.service.IIoTDeviceService;
import cn.universal.admin.system.service.IIoTUserApplicationService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.common.domain.R;
import cn.universal.common.exception.IoTException;
import cn.universal.persistence.entity.IoTDevice;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTCertificateController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTCertificateController.java
index 6832fb8..5a8e6c7 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTCertificateController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTCertificateController.java
@@ -5,9 +5,9 @@ import static cn.universal.common.constant.IoTConstant.CERT_DEFAULT_KEY;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.platform.service.ICertificateService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.persistence.dto.IoTCertificateQueryDTO;
import cn.universal.persistence.entity.IoTCertificate;
import cn.universal.persistence.page.TableDataInfo;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceController.java
index d9eb512..ab2073e 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceController.java
@@ -16,15 +16,14 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.platform.service.IIoTDeviceService;
import cn.universal.admin.system.service.IIoTUserApplicationService;
import cn.universal.admin.system.service.IoTDeviceProtocolService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.common.domain.R;
import cn.universal.common.exception.IoTException;
import cn.universal.common.poi.ExcelTemplate;
@@ -192,32 +191,15 @@ public class IoTDeviceController extends BaseController {
@PostMapping
@Log(title = "新增设备", businessType = BusinessType.INSERT)
public R add(@RequestBody IoTDeviceBO devInstancebo) {
- R result = iIotDeviceService.insertDevInstance(devInstancebo);
- JSONObject jsonObject = JSONUtil.parseObj(result);
- String code = jsonObject.getStr("code");
- String msg = jsonObject.getStr("msg");
- if ("0".equals(code)) {
- return R.ok();
- } else {
- return R.error(msg);
- }
+ return iIotDeviceService.insertDevInstance(devInstancebo);
}
/** 修改设备 */
@PutMapping
@Log(title = "修改设备", businessType = BusinessType.UPDATE)
public R edit(@RequestBody IoTDeviceBO devInstancebo) {
- IoTDevice ioTDevice =
- iIotDeviceService.selectDevInstanceById(String.valueOf(devInstancebo.getId()));
- R result = iIotDeviceService.updateDevInstance(devInstancebo);
- JSONObject jsonObject = JSONUtil.parseObj(result);
- String code = jsonObject.getStr("code");
- String msg = jsonObject.getStr("msg");
- if ("0".equals(code)) {
- return R.ok();
- } else {
- return R.error(msg);
- }
+ iIotDeviceService.selectDevInstanceById(String.valueOf(devInstancebo.getId()));
+ return iIotDeviceService.updateDevInstance(devInstancebo);
}
/** 绑定设备平台 */
@@ -245,15 +227,7 @@ public class IoTDeviceController extends BaseController {
@DeleteMapping("/{ids}")
@Log(title = "删除设备", businessType = BusinessType.DELETE)
public R remove(@PathVariable String[] ids) {
- R result = iIotDeviceService.deleteDevInstanceByIds(ids);
- JSONObject jsonObject = JSONUtil.parseObj(result);
- String code = jsonObject.getStr("code");
- String msg = jsonObject.getStr("msg");
- if ("0".equals(code)) {
- return R.ok();
- } else {
- return R.error(msg);
- }
+ return iIotDeviceService.deleteDevInstanceByIds(ids);
}
/** 获取所有设备型号 */
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceGroupController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceGroupController.java
index 5de5f66..d8dcd1e 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceGroupController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceGroupController.java
@@ -12,10 +12,10 @@
package cn.universal.admin.platform.web;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.platform.service.IIoTDeviceGroupService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.persistence.entity.IoTDevice;
import cn.universal.persistence.entity.bo.IoTDeviceGroupBO;
import cn.universal.persistence.entity.vo.IoTDeviceGroupVO;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceLogController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceLogController.java
index 1614a64..3bd1667 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceLogController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceLogController.java
@@ -12,7 +12,7 @@
package cn.universal.admin.platform.web;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.dm.device.service.log.IIoTDeviceDataService;
import cn.universal.persistence.entity.IoTDeviceEvents;
import cn.universal.persistence.entity.vo.IoTDeviceLogMetadataVO;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceLogV1Controller.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceLogV1Controller.java
index 1ae552f..0dd9191 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceLogV1Controller.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceLogV1Controller.java
@@ -13,7 +13,7 @@
package cn.universal.admin.platform.web;
import cn.universal.admin.platform.service.IIoTDevLogService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.persistence.entity.IoTDeviceEvents;
import cn.universal.persistence.entity.bo.IoTDeviceLogBO;
import cn.universal.persistence.entity.vo.IoTDeviceLogVO;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceProtocolController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceProtocolController.java
index 0413cce..32620b6 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceProtocolController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceProtocolController.java
@@ -17,13 +17,13 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.IoTDeviceProtocolService;
import cn.universal.admin.system.service.impl.IoTDeviceMessageCodecService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.common.exception.CodecException;
import cn.universal.common.exception.IoTException;
import cn.universal.ossm.service.ISysOssService;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceSubscribeController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceSubscribeController.java
index 8569ae4..5bba9ff 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceSubscribeController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTDeviceSubscribeController.java
@@ -13,10 +13,10 @@
package cn.universal.admin.platform.web;
import cn.hutool.core.util.StrUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.system.service.IoTDeviceSubscribeService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.common.domain.R;
import cn.universal.common.exception.IoTException;
import cn.universal.persistence.entity.IoTDeviceSubscribe;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTProductCategoryController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTProductCategoryController.java
index 297fb78..b3ade32 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTProductCategoryController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTProductCategoryController.java
@@ -13,10 +13,10 @@
package cn.universal.admin.platform.web;
import cn.hutool.core.util.StrUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.platform.service.IIoTProductSortService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.common.exception.IoTException;
import cn.universal.persistence.entity.IoTProduct;
import cn.universal.persistence.entity.IoTProductSort;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTProductController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTProductController.java
index b13b752..6423700 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTProductController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTProductController.java
@@ -16,9 +16,9 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.network.service.INetworkService;
import cn.universal.admin.platform.dto.ConnectionInfoDTO;
import cn.universal.admin.platform.service.ConnectionInfoService;
@@ -27,8 +27,9 @@ import cn.universal.admin.platform.service.IIoTProductService;
import cn.universal.admin.platform.service.impl.IoTProductServiceImpl;
import cn.universal.admin.system.service.ISysDictTypeService;
import cn.universal.admin.system.service.IoTDeviceProtocolService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.common.constant.IoTConstant;
+import cn.universal.common.constant.IoTConstant.DownCmd;
import cn.universal.common.constant.IoTConstant.ProtocolModule;
import cn.universal.common.constant.IoTConstant.TcpFlushType;
import cn.universal.common.event.EventTopics;
@@ -319,9 +320,9 @@ public class IoTProductController extends BaseController {
}
/** 新增电信公共产品 */
- @PostMapping(value = "/ctwing/pubproadd")
+ @PostMapping(value = "/ctaiot/public/product")
@Log(title = "新增电信公共产品", businessType = BusinessType.INSERT)
- public AjaxResult addCtwingPubPro(@RequestBody String downRequest) {
+ public AjaxResult addCtAIotPublicProduct(@RequestBody String downRequest) {
String creatorId = loginIoTUnionUser(SecurityUtils.getUnionId()).getUnionId();
JSONObject jsonObject = JSONUtil.parseObj(downRequest);
JSONObject downProRequest = new JSONObject();
@@ -333,7 +334,7 @@ public class IoTProductController extends BaseController {
downProRequest.set("classifiedId", jsonObject.getStr("classifiedId"));
downProRequest.set("classifiedName", jsonObject.getStr("classifiedName"));
downProRequest.set("companyNo", jsonObject.getStr("companyNo"));
- downProRequest.set("cmd", "PUBPRO_ADD");
+ downProRequest.set("cmd", DownCmd.PUBPRO_ADD.name());
downProRequest.set("data", data);
return AjaxResult.success(
IoTDownlFactory.safeInvokeDown(
@@ -483,7 +484,7 @@ public class IoTProductController extends BaseController {
}
// 删除协议
ioTDeviceProtocolService.deleteDevProtocolById(ioTProduct.getProductKey());
-
+
// 发布产品删除事件
Map eventData = new HashMap<>();
eventData.put("type", "product");
@@ -738,7 +739,6 @@ public class IoTProductController extends BaseController {
/** 查看连接信息 */
@PostMapping("/connect/info")
- @Log(title = "查看连接信息", businessType = BusinessType.OTHER)
public AjaxResult connectInfo(@RequestParam String productKey) {
try {
ConnectionInfoDTO connectionInfo = connectionInfoService.getConnectionInfo(productKey);
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTUserAppController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTUserAppController.java
index 1cf010f..bcd7242 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTUserAppController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTUserAppController.java
@@ -23,15 +23,15 @@ import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.platform.service.IIoTDeviceService;
import cn.universal.admin.system.service.IIoTUserApplicationService;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.security.service.IoTUserService;
import cn.universal.admin.system.service.IOAuthClientDetailsService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.common.exception.IoTException;
import cn.universal.persistence.base.BaseUPRequest;
import cn.universal.persistence.entity.IoTUser;
@@ -81,7 +81,7 @@ public class IoTUserAppController extends BaseController {
@Resource private IoTUserApplicationMapper iotUserApplicationMapper;
@Resource private IOAuthClientDetailsService oauthClientDetailsService;
@Resource private IIoTDeviceService iIotDeviceService;
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
/** 查询用户应用信息列表 */
@Operation(summary = "查询用户应用信息列表")
@@ -116,7 +116,7 @@ public class IoTUserAppController extends BaseController {
public void export(HttpServletResponse response, IoTUserApplication iotUserApplication) {
IoTUser iotUser = loginIoTUnionUser(SecurityUtils.getUnionId());
iotUserApplication.setUnionId(
- iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()
+ ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()
? null
: SecurityUtils.getUnionId());
List list =
@@ -248,7 +248,7 @@ public class IoTUserAppController extends BaseController {
"修改用户应用信息,操作人={},参数={}",
SecurityUtils.getUnionId(),
JSONUtil.toJsonStr(iotUserApplication));
- IoTUser iotUser = iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId());
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId());
IoTUserApplication app =
iotUserApplicationService.selectIotUserApplicationById(iotUserApplication.getAppUniqueId());
if (app != null
@@ -332,7 +332,7 @@ public class IoTUserAppController extends BaseController {
@Operation(summary = "HTTP推送启/停用")
@PostMapping(value = "/enable")
public AjaxResult HttpEnable(@RequestBody IoTUserApplication iotUserApplication) {
- IoTUser iotUser = iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId());
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId());
IoTUserApplication app =
iotUserApplicationService.selectIotUserApplicationById(iotUserApplication.getAppUniqueId());
if (app != null
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTUserController.java b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTUserController.java
index a6baa50..c0a03e1 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTUserController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/platform/web/IoTUserController.java
@@ -20,14 +20,14 @@ import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.IIoTUserApplicationService;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.security.service.IoTUserService;
import cn.universal.admin.system.service.ISysRoleService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.common.constant.IoTConstant;
import cn.universal.common.constant.IoTUserConstants;
import cn.universal.common.exception.IoTException;
@@ -68,7 +68,7 @@ import org.springframework.web.bind.annotation.RestController;
@Slf4j
public class IoTUserController extends BaseController {
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
@Resource private ISysRoleService iSysRoleService;
@Resource private IIoTUserApplicationService iotUserApplicationService;
@@ -77,13 +77,13 @@ public class IoTUserController extends BaseController {
@GetMapping("/list")
public TableDataInfo pageList(IoTUser user) {
log.info("当前用户={}", SecurityUtils.getUnionId());
- if (iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()) {
+ if (ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()) {
user.setCreateBy(null);
} else {
user.setCreateBy(SecurityUtils.getUnionId());
}
startPage();
- List userList = iIotUserService.selectUserList(user);
+ List userList = ioTUserService.selectUserList(user);
return getDataTable(userList);
}
@@ -92,12 +92,12 @@ public class IoTUserController extends BaseController {
@Log(title = "导出用户应用信息列表", businessType = BusinessType.EXPORT)
public void export(HttpServletResponse response, IoTUser iotUser) {
log.info("导出用户,操作人={},参数={}", SecurityUtils.getUnionId(), JSONUtil.toJsonStr(iotUser));
- if (iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()) {
+ if (ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()) {
iotUser.setCreateBy(null);
} else {
iotUser.setCreateBy(SecurityUtils.getUnionId());
}
- List list = iIotUserService.selectUserList(iotUser);
+ List list = ioTUserService.selectUserList(iotUser);
ExcelUtil util = new ExcelUtil(IoTUser.class);
util.exportExcel(response, list, "用户信息数据");
}
@@ -108,7 +108,7 @@ public class IoTUserController extends BaseController {
JSONObject jsonObject = new JSONObject();
List roles = iSysRoleService.selectRoleAll();
- IoTUser currentUser = iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId());
+ IoTUser currentUser = ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId());
jsonObject.set(
"roles",
currentUser.isAdmin()
@@ -117,7 +117,7 @@ public class IoTUserController extends BaseController {
.filter(r -> SecurityUtils.getUnionId().equals(r.getCreateBy()))
.collect(Collectors.toList()));
if (StringUtils.isNotNull(id)) {
- IoTUser iotUser = iIotUserService.selectUserById(id);
+ IoTUser iotUser = ioTUserService.selectUserById(id);
if (!SecurityUtils.getUnionId().equalsIgnoreCase(iotUser.getParentUnionId())
&& !currentUser.isAdmin()) {
throw new IoTException("你无权查询用户");
@@ -137,7 +137,7 @@ public class IoTUserController extends BaseController {
public AjaxResult add(@Validated @RequestBody IoTUserBO userbo) {
log.info("新增用户,操作人={},参数={}", SecurityUtils.getUnionId(), JSONUtil.toJsonStr(userbo));
String unionId = SecurityUtils.getUnionId();
- IoTUser parentUser = iIotUserService.selectUserByUnionId(unionId);
+ IoTUser parentUser = ioTUserService.selectUserByUnionId(unionId);
if (!parentUser.isAdmin()) {
throw new IoTException("你无权操作");
}
@@ -145,10 +145,10 @@ public class IoTUserController extends BaseController {
if (Objects.isNull(user.getMobile())) {
return AjaxResult.error("新增用户'" + user.getUsername() + "'失败,手机号码不得为空");
}
- if (IoTUserConstants.NOT_UNIQUE.equals(iIotUserService.checkUserNameUnique(user))) {
+ if (IoTUserConstants.NOT_UNIQUE.equals(ioTUserService.checkUserNameUnique(user))) {
return AjaxResult.error("新增用户'" + user.getUsername() + "'失败,用户名已存在");
} else if (Validator.isNotEmpty(user.getMobile())
- && IoTUserConstants.NOT_UNIQUE.equals(iIotUserService.checkPhoneUnique(user))) {
+ && IoTUserConstants.NOT_UNIQUE.equals(ioTUserService.checkPhoneUnique(user))) {
return AjaxResult.error("新增用户'" + user.getUsername() + "'失败,手机号码已存在");
}
if (StrUtil.isNotEmpty(user.getPassword())) {
@@ -173,7 +173,7 @@ public class IoTUserController extends BaseController {
userbo.setLicense(5000);
userbo.setLicenseTotalAmount(5000);
}
- return toAjax(iIotUserService.insertUser(userbo));
+ return toAjax(ioTUserService.insertUser(userbo));
}
/** 修改用户 */
@@ -183,9 +183,9 @@ public class IoTUserController extends BaseController {
public AjaxResult edit(@Validated @RequestBody IoTUserBO userbo) {
log.info("修改用户,操作人={},参数={}", SecurityUtils.getUnionId(), JSONUtil.toJsonStr(userbo));
IoTUser user = BeanUtil.toBean(userbo, IoTUser.class);
- iIotUserService.checkUserAllowed(user);
- IoTUser updateUser = iIotUserService.selectUserById(userbo.getId());
- IoTUser iotUser = iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId());
+ ioTUserService.checkUserAllowed(user);
+ IoTUser updateUser = ioTUserService.selectUserById(userbo.getId());
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId());
// 非超管身份只能操作自己和子账户
if (!SecurityUtils.getUnionId().equalsIgnoreCase(updateUser.getParentUnionId())
&& (iotUser == null || !user.getId().equals(iotUser.getId()))
@@ -195,7 +195,7 @@ public class IoTUserController extends BaseController {
if (Validator.isEmpty(user.getMobile())) {
return error("修改用户'" + user.getUsername() + "'失败,手机号码不能为空");
}
- if (IoTUserConstants.NOT_UNIQUE.equals(iIotUserService.checkPhoneUnique(user))) {
+ if (IoTUserConstants.NOT_UNIQUE.equals(ioTUserService.checkPhoneUnique(user))) {
return error("修改用户'" + user.getUsername() + "'失败,手机号码已存在");
}
@@ -212,7 +212,7 @@ public class IoTUserController extends BaseController {
}
userbo.setUpdateBy(SecurityUtils.getUnionId());
userbo.setUpdateDate(new Date());
- int count = iIotUserService.updateUser(userbo);
+ int count = ioTUserService.updateUser(userbo);
if (count > 0) {
iotUserApplicationService.EnDisableIoTUser(
userbo.getUnionId(), IoTConstant.NORMAL.toString().equals(iotUser.getStatus()));
@@ -228,12 +228,12 @@ public class IoTUserController extends BaseController {
if (userIds != null && userIds.length > 1) {
return error("不允许批量删除");
}
- boolean isAdmin = iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin();
- IoTUser deleteUser = iIotUserService.selectUserById(userIds[0]);
+ boolean isAdmin = ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin();
+ IoTUser deleteUser = ioTUserService.selectUserById(userIds[0]);
if (!SecurityUtils.getUnionId().equalsIgnoreCase(deleteUser.getParentUnionId()) && !isAdmin) {
return error("你无权删除用户");
}
- return toAjax(iIotUserService.deleteUserByIds(userIds));
+ return toAjax(ioTUserService.deleteUserByIds(userIds));
}
/** 根据用户编号获取授权角色 */
@@ -242,8 +242,8 @@ public class IoTUserController extends BaseController {
log.info("授权用户,操作人={},参数={}", SecurityUtils.getUnionId(), id);
JSONObject object = new JSONObject();
- IoTUser currentUser = iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId());
- IoTUser user = iIotUserService.selectUserById(id);
+ IoTUser currentUser = ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId());
+ IoTUser user = ioTUserService.selectUserById(id);
if (!SecurityUtils.getUnionId().equalsIgnoreCase(user.getParentUnionId())
&& !currentUser.isAdmin()) {
return error("你无权操作用户");
@@ -261,13 +261,13 @@ public class IoTUserController extends BaseController {
/** 用户授权角色 */
@PutMapping("/authRole")
public AjaxResult insertAuthRole(String unionId, Long[] roleIds) {
- IoTUser currentUser = iIotUserService.selectUserByUnionId(SecurityUtils.getUnionId());
- IoTUser user = iIotUserService.selectUserByUnionId(unionId);
+ IoTUser currentUser = ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId());
+ IoTUser user = ioTUserService.selectUserByUnionId(unionId);
if (!SecurityUtils.getUnionId().equalsIgnoreCase(user.getParentUnionId())
&& !currentUser.isAdmin()) {
return error("你无权操作用户");
}
- iIotUserService.insertUserAuth(unionId, roleIds);
+ ioTUserService.insertUserAuth(unionId, roleIds);
return success();
}
}
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/monitor/SysLoginLogController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/monitor/SysLoginLogController.java
index 696154d..4400549 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/monitor/SysLoginLogController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/monitor/SysLoginLogController.java
@@ -12,12 +12,12 @@
package cn.universal.admin.system.monitor;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.ISysLogininforService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.persistence.entity.IoTUser;
import cn.universal.persistence.entity.SysLogininfor;
import cn.universal.persistence.page.TableDataInfo;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/monitor/SysOperlogController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/monitor/SysOperlogController.java
index 18f8f14..0fa523a 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/monitor/SysOperlogController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/monitor/SysOperlogController.java
@@ -12,12 +12,12 @@
package cn.universal.admin.system.monitor;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.ISysOperLogService;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.persistence.entity.IoTUser;
import cn.universal.persistence.entity.SysOperLog;
import cn.universal.persistence.page.TableDataInfo;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeChannelController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeChannelController.java
index e4c6ad1..6f9587b 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeChannelController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeChannelController.java
@@ -1,8 +1,8 @@
package cn.universal.admin.system.notice;
import cn.hutool.json.JSONObject;
-import cn.universal.admin.common.utils.SecurityUtils;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.utils.SecurityUtils;
+import cn.universal.security.BaseController;
import cn.universal.manager.notice.dto.NoticeChannelDTO;
import cn.universal.manager.notice.model.NoticeChannel;
import cn.universal.manager.notice.service.NoticeChannelService;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeRecordController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeRecordController.java
index c6cae8b..814fa17 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeRecordController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeRecordController.java
@@ -1,6 +1,6 @@
package cn.universal.admin.system.notice;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.manager.notice.model.NoticeSendRecord;
import cn.universal.manager.notice.service.NoticeRecordService;
import cn.universal.persistence.page.TableDataInfo;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeTemplateController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeTemplateController.java
index 78c1fc1..57eb423 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeTemplateController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/notice/NoticeTemplateController.java
@@ -1,7 +1,7 @@
package cn.universal.admin.system.notice;
-import cn.universal.admin.common.utils.SecurityUtils;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.utils.SecurityUtils;
+import cn.universal.security.BaseController;
import cn.universal.manager.notice.dto.NoticeTemplateDTO;
import cn.universal.manager.notice.model.NoticeTemplate;
import cn.universal.manager.notice.service.NoticeTemplateService;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/oss/SysOssController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/oss/SysOssController.java
index 8b23dcd..245138f 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/oss/SysOssController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/oss/SysOssController.java
@@ -14,8 +14,8 @@ package cn.universal.admin.system.oss;
import cn.hutool.core.convert.Convert;
import cn.hutool.http.HttpUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.utils.SecurityUtils;
+import cn.universal.security.BaseController;
import cn.universal.common.exception.IoTException;
import cn.universal.common.utils.FileUtils;
import cn.universal.ossm.entity.SysOss;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/quartz/SysJobController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/quartz/SysJobController.java
index 7b31802..bd428d2 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/quartz/SysJobController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/quartz/SysJobController.java
@@ -14,8 +14,8 @@ package cn.universal.admin.system.quartz;
import cn.hutool.core.util.StrUtil;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.utils.SecurityUtils;
+import cn.universal.security.BaseController;
import cn.universal.persistence.page.TableDataInfo;
import cn.universal.persistence.query.AjaxResult;
import cn.universal.quartz.constant.Constants;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/quartz/SysJobLogController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/quartz/SysJobLogController.java
index 4fd9b7a..2a30a1b 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/quartz/SysJobLogController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/quartz/SysJobLogController.java
@@ -13,7 +13,7 @@
package cn.universal.admin.system.quartz;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.persistence.page.TableDataInfo;
import cn.universal.persistence.query.AjaxResult;
import cn.universal.quartz.domain.SysJobLog;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/IoTDeviceSubscribeServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/IoTDeviceSubscribeServiceImpl.java
index d65cca4..e6f9108 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/IoTDeviceSubscribeServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/IoTDeviceSubscribeServiceImpl.java
@@ -14,7 +14,7 @@ package cn.universal.admin.system.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.universal.admin.common.service.BaseServiceImpl;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.IoTDeviceSubscribeService;
import cn.universal.common.constant.IoTConstant;
import cn.universal.common.constant.IoTConstant.DeviceSubscribe;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/IoTUserApplicationServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/IoTUserApplicationServiceImpl.java
index de64d02..db30dec 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/IoTUserApplicationServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/IoTUserApplicationServiceImpl.java
@@ -17,9 +17,9 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.universal.admin.common.service.BaseServiceImpl;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.IIoTUserApplicationService;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.security.service.IoTUserService;
import cn.universal.common.constant.IoTConstant;
import cn.universal.common.exception.IoTException;
import cn.universal.persistence.entity.IoTUser;
@@ -50,7 +50,7 @@ public class IoTUserApplicationServiceImpl extends BaseServiceImpl
implements IIoTUserApplicationService {
@Resource private IoTUserApplicationMapper iotUserApplicationMapper;
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
@Resource private OauthClientDetailsMapper oauthClientDetailsMapper;
@@ -117,7 +117,7 @@ public class IoTUserApplicationServiceImpl extends BaseServiceImpl
public IoTUserApplication checkSelf(String appUniqueId) {
IoTUserApplication a = IoTUserApplication.builder().appUniqueId(appUniqueId).build();
String unionId = queryIotUser(SecurityUtils.getUnionId()).getUnionId();
- if (!iIotUserService.selectUserByUnionId(unionId).isAdmin()) {
+ if (!ioTUserService.selectUserByUnionId(unionId).isAdmin()) {
a.setUnionId(unionId);
}
IoTUserApplication iotUserApplication = iotUserApplicationMapper.selectOne(a);
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysDictDataServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysDictDataServiceImpl.java
index fff2dd4..29d03a0 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysDictDataServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysDictDataServiceImpl.java
@@ -14,7 +14,7 @@ package cn.universal.admin.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.ISysDictDataService;
import cn.universal.admin.system.service.ISysDictTypeService;
import cn.universal.persistence.entity.admin.SysDictData;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysMenuServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysMenuServiceImpl.java
index 01fb76f..89e80eb 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysMenuServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysMenuServiceImpl.java
@@ -14,7 +14,7 @@ package cn.universal.admin.system.service.impl;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.security.service.IoTUserService;
import cn.universal.admin.system.service.ISysMenuService;
import cn.universal.common.constant.Constants;
import cn.universal.common.constant.IoTUserConstants;
@@ -51,7 +51,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
@Resource private SysRoleMenuMapper roleMenuMapper;
@Resource private SysMenuMapper menuMapper;
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
/**
* 根据用户查询系统菜单列表
@@ -75,7 +75,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
public List selectMenuList(SysMenu menu, String unionId) {
List menuList = null;
// 管理员显示所有菜单信息
- IoTUser iotUser = iIotUserService.selectUserByUnionId(unionId);
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(unionId);
if (iotUser.isAdmin()) {
menuList = menuMapper.selectMenuList(menu);
} else {
@@ -106,7 +106,7 @@ public class SysMenuServiceImpl implements ISysMenuService {
@Override
public List selectMenuTreeByUnionId(String unionId) {
List menus = null;
- IoTUser iotUser = iIotUserService.selectUserByUnionId(unionId);
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(unionId);
if (iotUser.isAdmin()) {
menus = menuMapper.selectMenuTreeAll();
} else {
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysRoleServiceImpl.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysRoleServiceImpl.java
index 6100050..3918aeb 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysRoleServiceImpl.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/service/impl/SysRoleServiceImpl.java
@@ -13,9 +13,8 @@
package cn.universal.admin.system.service.impl;
import cn.hutool.core.lang.Validator;
-import cn.universal.admin.common.annotation.DataScope;
-import cn.universal.admin.common.utils.SecurityUtils;
import cn.universal.admin.system.service.ISysRoleService;
+import cn.universal.common.annotation.DataScope;
import cn.universal.common.constant.IoTUserConstants;
import cn.universal.common.exception.IoTException;
import cn.universal.persistence.entity.admin.SysRole;
@@ -24,6 +23,7 @@ import cn.universal.persistence.entity.admin.SysUserRole;
import cn.universal.persistence.mapper.admin.SysRoleMapper;
import cn.universal.persistence.mapper.admin.SysRoleMenuMapper;
import cn.universal.persistence.mapper.admin.SysUserRoleMapper;
+import cn.universal.security.utils.SecurityUtils;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/IndexController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/IndexController.java
index f331a69..3b50ede 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/IndexController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/IndexController.java
@@ -12,10 +12,11 @@
package cn.universal.admin.system.web;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.IndexQueryService;
import cn.universal.persistence.dto.IndexQueryDTO;
import cn.universal.persistence.query.AjaxResult;
+import cn.universal.security.BaseController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/RuleController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/RuleController.java
index 5edf199..4a8877b 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/RuleController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/RuleController.java
@@ -13,10 +13,10 @@
package cn.universal.admin.system.web;
import cn.hutool.json.JSONObject;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
-import cn.universal.admin.common.utils.SecurityUtils;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
+import cn.universal.security.utils.SecurityUtils;
+import cn.universal.security.service.IoTUserService;
import cn.universal.persistence.entity.bo.RuleModelBO;
import cn.universal.persistence.entity.vo.RuleModelVO;
import cn.universal.persistence.page.TableDataInfo;
@@ -24,6 +24,7 @@ import cn.universal.persistence.query.AjaxResult;
import cn.universal.rule.model.bo.RuleBo;
import cn.universal.rule.model.bo.RuleTargetTestBO;
import cn.universal.rule.service.RuleService;
+import cn.universal.security.BaseController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -50,7 +51,7 @@ import org.springframework.web.bind.annotation.RestController;
public class RuleController extends BaseController {
@Resource private RuleService ruleService;
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
@Operation(summary = "查询规则列表")
@GetMapping("rule/list")
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/RulegoChainController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/RulegoChainController.java
index a0fefbb..0d8c583 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/RulegoChainController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/RulegoChainController.java
@@ -12,14 +12,15 @@
package cn.universal.admin.system.web;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.persistence.entity.bo.RulegoChainBO;
import cn.universal.persistence.entity.vo.RulegoChainVO;
import cn.universal.persistence.page.TableDataInfo;
import cn.universal.persistence.query.AjaxResult;
import cn.universal.rule.rulego.service.RulegoChainService;
+import cn.universal.security.BaseController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SceneLinkageController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SceneLinkageController.java
index b7a4089..cd6d4fd 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SceneLinkageController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SceneLinkageController.java
@@ -12,10 +12,10 @@
package cn.universal.admin.system.web;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.common.exception.IoTException;
import cn.universal.persistence.entity.IoTUser;
import cn.universal.persistence.entity.SceneLinkage;
@@ -24,6 +24,7 @@ import cn.universal.persistence.page.TableDataInfo;
import cn.universal.persistence.query.AjaxResult;
import cn.universal.rule.model.ExeRunContext;
import cn.universal.rule.scene.service.SceneLinkageService;
+import cn.universal.security.BaseController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysConfigController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysConfigController.java
index 22f7ee3..9d7878a 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysConfigController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysConfigController.java
@@ -12,14 +12,15 @@
package cn.universal.admin.system.web;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.ISysConfigService;
import cn.universal.common.constant.IoTUserConstants;
import cn.universal.persistence.entity.admin.SysConfig;
import cn.universal.persistence.page.TableDataInfo;
import cn.universal.persistence.query.AjaxResult;
+import cn.universal.security.BaseController;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysDictDataController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysDictDataController.java
index 7d695a8..b5a56f3 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysDictDataController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysDictDataController.java
@@ -13,13 +13,14 @@
package cn.universal.admin.system.web;
import cn.hutool.core.lang.Validator;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.ISysDictDataService;
import cn.universal.admin.system.service.ISysDictTypeService;
import cn.universal.persistence.entity.admin.SysDictData;
import cn.universal.persistence.entity.admin.vo.SysDictDataVo;
import cn.universal.persistence.page.TableDataInfo;
import cn.universal.persistence.query.AjaxResult;
+import cn.universal.security.BaseController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysDictTypeController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysDictTypeController.java
index 556b741..a60c155 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysDictTypeController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysDictTypeController.java
@@ -12,12 +12,13 @@
package cn.universal.admin.system.web;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.ISysDictTypeService;
import cn.universal.common.constant.IoTUserConstants;
import cn.universal.persistence.entity.admin.SysDictType;
import cn.universal.persistence.page.TableDataInfo;
import cn.universal.persistence.query.AjaxResult;
+import cn.universal.security.BaseController;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysMenuController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysMenuController.java
index 656e2ad..ff9ceb8 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysMenuController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysMenuController.java
@@ -13,14 +13,15 @@
package cn.universal.admin.system.web;
import cn.hutool.core.lang.Validator;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.system.service.ISysMenuService;
import cn.universal.common.constant.IoTUserConstants;
import cn.universal.common.exception.IoTException;
import cn.universal.persistence.entity.admin.SysMenu;
import cn.universal.persistence.query.AjaxResult;
+import cn.universal.security.BaseController;
+import cn.universal.security.utils.SecurityUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysProfileController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysProfileController.java
index 71bce95..597ca3b 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysProfileController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysProfileController.java
@@ -18,8 +18,8 @@ import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.security.service.IoTUserService;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.service.ISysRoleService;
import cn.universal.common.constant.IoTConstant;
import cn.universal.common.constant.IoTUserConstants;
@@ -28,6 +28,7 @@ import cn.universal.persistence.entity.IoTUser;
import cn.universal.persistence.entity.bo.IoTUserBO;
import cn.universal.persistence.entity.bo.PasswordBO;
import cn.universal.persistence.query.AjaxResult;
+import cn.universal.security.BaseController;
import jakarta.annotation.Resource;
import java.util.Date;
import java.util.Objects;
@@ -44,7 +45,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/admin/system/user/profile")
public class SysProfileController extends BaseController {
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
@Resource private ISysRoleService iSysRoleService;
/** 查询个人信息 */
@@ -53,7 +54,7 @@ public class SysProfileController extends BaseController {
JSONObject jsonObject = new JSONObject();
String unionId = SecurityUtils.getUnionId();
- IoTUser iotUser = iIotUserService.selectUserByUnionId(unionId);
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(unionId);
// 手机号脱敏
if (StrUtil.isNotEmpty(iotUser.getMobile())) {
iotUser.setMobile(PhoneUtil.hideBetween(iotUser.getMobile()).toString());
@@ -72,10 +73,10 @@ public class SysProfileController extends BaseController {
return error("修改个人信息失败,手机号码不能为空");
}
IoTUser user = BeanUtil.toBean(iotUserBo, IoTUser.class);
- if (IoTUserConstants.NOT_UNIQUE.equals(iIotUserService.checkPhoneUnique(user))) {
+ if (IoTUserConstants.NOT_UNIQUE.equals(ioTUserService.checkPhoneUnique(user))) {
return error("修改个人信息失败,手机号码已存在");
}
- IoTUser iotUser = iIotUserService.selectUserByUnionId(unionId);
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(unionId);
iotUser.setAlias(iotUserBo.getAlias());
iotUser.setEmail(iotUserBo.getEmail());
iotUser.setMobile(iotUserBo.getMobile());
@@ -87,7 +88,7 @@ public class SysProfileController extends BaseController {
origin.set(IoTConstant.EXCLUSIVE_FIRST_LOGIN, latest.get(IoTConstant.EXCLUSIVE_FIRST_LOGIN));
iotUser.setCfg(JSONUtil.toJsonStr(origin));
}
- iIotUserService.updateUserById(iotUser);
+ ioTUserService.updateUserById(iotUser);
return AjaxResult.success();
}
@@ -95,7 +96,7 @@ public class SysProfileController extends BaseController {
@PutMapping("/updatePwd")
public AjaxResult updatePwd(@RequestBody PasswordBO bo) {
String unionId = SecurityUtils.getUnionId();
- IoTUser iotUser = iIotUserService.selectUserByUnionId(unionId);
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(unionId);
Matcher matcher = IoTConstant.pattern.matcher(bo.getNewPassword());
if (!matcher.matches()) {
throw new IoTException("密码中必须包含字母、数字、特殊字符,至少8个字符,最多30个字符");
@@ -106,7 +107,7 @@ public class SysProfileController extends BaseController {
iotUser.setPassword(SecurityUtils.encryptPassword(bo.getNewPassword()));
iotUser.setUpdateBy(unionId);
iotUser.setUpdateDate(new Date());
- iIotUserService.updateUserById(iotUser);
+ ioTUserService.updateUserById(iotUser);
return AjaxResult.success();
}
@@ -114,13 +115,13 @@ public class SysProfileController extends BaseController {
@RequestMapping("/updateMobile/{mobile}")
public AjaxResult updatePwd(@PathVariable("mobile") String mobile) {
String unionId = SecurityUtils.getUnionId();
- IoTUser iotUser = iIotUserService.selectUserByUnionId(unionId);
- IoTUser user = iIotUserService.selectUserByMobile(mobile);
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(unionId);
+ IoTUser user = ioTUserService.selectUserByMobile(mobile);
if (Objects.nonNull(user)) {
throw new IoTException("手机号码已存在,请勿重复添加");
} else {
iotUser.setMobile(mobile);
- iIotUserService.updateUserById(iotUser);
+ ioTUserService.updateUserById(iotUser);
return AjaxResult.success();
}
}
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysRoleController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysRoleController.java
index 2cefbde..b3f5842 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysRoleController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysRoleController.java
@@ -13,11 +13,11 @@
package cn.universal.admin.system.web;
import cn.hutool.core.util.ObjectUtil;
-import cn.universal.admin.common.annotation.Log;
-import cn.universal.admin.common.enums.BusinessType;
+import cn.universal.common.annotation.Log;
+import cn.universal.common.enums.BusinessType;
import cn.universal.admin.common.utils.ExcelUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.security.utils.SecurityUtils;
+import cn.universal.security.service.IoTUserService;
import cn.universal.admin.system.service.ISysRoleService;
import cn.universal.common.constant.IoTUserConstants;
import cn.universal.common.exception.IoTException;
@@ -27,6 +27,7 @@ import cn.universal.persistence.entity.admin.SysUserRole;
import cn.universal.persistence.entity.bo.IoTUserBO;
import cn.universal.persistence.page.TableDataInfo;
import cn.universal.persistence.query.AjaxResult;
+import cn.universal.security.BaseController;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Date;
@@ -49,11 +50,11 @@ public class SysRoleController extends BaseController {
@Autowired private ISysRoleService roleService;
- @Autowired private IIotUserService userService;
+ @Autowired private IoTUserService ioTUserService;
@GetMapping("/list")
public TableDataInfo list(SysRole role) {
- if (!userService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()) {
+ if (!ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()) {
role.setCreateBy(SecurityUtils.getUnionId());
}
startPage();
@@ -62,7 +63,7 @@ public class SysRoleController extends BaseController {
@PostMapping("/export")
public void export(HttpServletResponse response, SysRole role) {
- if (!userService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()) {
+ if (!ioTUserService.selectUserByUnionId(SecurityUtils.getUnionId()).isAdmin()) {
role.setCreateBy(SecurityUtils.getUnionId());
}
List list = roleService.selectRoleList(role);
@@ -88,7 +89,7 @@ public class SysRoleController extends BaseController {
@Log(title = "新增角色", businessType = BusinessType.INSERT)
public AjaxResult add(@Validated @RequestBody SysRole role) {
String unionId = SecurityUtils.getUnionId();
- IoTUser parentUser = userService.selectUserByUnionId(unionId);
+ IoTUser parentUser = ioTUserService.selectUserByUnionId(unionId);
if (!parentUser.isAdmin()) {
throw new IoTException("你无权操作");
}
@@ -196,7 +197,7 @@ public class SysRoleController extends BaseController {
throw new IoTException("你无权操作");
}
startPage();
- return getDataTable(userService.selectAllocatedList(iotUserBo));
+ return getDataTable(ioTUserService.selectAllocatedList(iotUserBo));
}
/** 查询未分配用户角色列表 */
@@ -211,7 +212,7 @@ public class SysRoleController extends BaseController {
}
startPage();
user.setCreateBy(SecurityUtils.getUnionId());
- return getDataTable(userService.selectUnallocatedList(user));
+ return getDataTable(ioTUserService.selectUnallocatedList(user));
}
/** 取消授权用户 */
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysUserController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysUserController.java
index a38bd0c..ae0b3b9 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysUserController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SysUserController.java
@@ -13,9 +13,9 @@
package cn.universal.admin.system.web;
import cn.hutool.core.util.StrUtil;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import cn.universal.admin.system.permission.SysPermissionService;
-import cn.universal.admin.system.service.IIotUserService;
+import cn.universal.security.service.IoTUserService;
import cn.universal.admin.system.service.ISysMenuService;
import cn.universal.common.constant.IoTConstant;
import cn.universal.common.domain.R;
@@ -40,7 +40,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("admin")
public class SysUserController {
- @Resource private IIotUserService iIotUserService;
+ @Resource private IoTUserService ioTUserService;
@Resource private ISysMenuService menuService;
@@ -55,7 +55,7 @@ public class SysUserController {
@GetMapping("getInfo")
public R getInfo(HttpServletRequest request) {
final String unionId = SecurityUtils.getUnionId();
- IoTUser iotUser = iIotUserService.selectUserByUnionId(unionId);
+ IoTUser iotUser = ioTUserService.selectUserByUnionId(unionId);
// 更新登录时间
// 角色集合
Set roles = permissionService.getRolePermission(iotUser);
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SystemProtocolController.java b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SystemProtocolController.java
index 3651477..5463197 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SystemProtocolController.java
+++ b/cn-universal-admin/src/main/java/cn/universal/admin/system/web/SystemProtocolController.java
@@ -17,6 +17,7 @@ import cn.universal.core.protocol.ProtocolModuleRegistry;
import cn.universal.core.protocol.ProtocolModuleRuntimeRegistry;
import cn.universal.core.service.IoTDownlFactory;
import cn.universal.persistence.query.AjaxResult;
+import cn.universal.security.BaseController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
diff --git a/cn-universal-admin/src/main/resources/vm/java/controller.java.vm b/cn-universal-admin/src/main/resources/vm/java/controller.java.vm
index 0fadc1f..38580fa 100644
--- a/cn-universal-admin/src/main/resources/vm/java/controller.java.vm
+++ b/cn-universal-admin/src/main/resources/vm/java/controller.java.vm
@@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import ${packageName}.domain.${ClassName};
import ${packageName}.service.I${ClassName}Service;
-import cn.universal.admin.system.web.BaseController;
+import cn.universal.security.BaseController;
import cn.universal.persistence.query.AjaxResult;
import com.zebra.common.utils.poi.ExcelUtil;
#if($table.crud)
diff --git a/cn-universal-admin/src/main/resources/vm/java/serviceImpl.java.vm b/cn-universal-admin/src/main/resources/vm/java/serviceImpl.java.vm
index 11807e0..e61d048 100644
--- a/cn-universal-admin/src/main/resources/vm/java/serviceImpl.java.vm
+++ b/cn-universal-admin/src/main/resources/vm/java/serviceImpl.java.vm
@@ -1,6 +1,6 @@
package ${packageName}.service.impl;
-import cn.universal.admin.common.utils.SecurityUtils;
+import cn.universal.security.utils.SecurityUtils;
import java.util.Date;
import java.util.List;
#if($table.tree)
diff --git a/cn-universal-framework/cn-universal-common/pom.xml b/cn-universal-framework/cn-universal-common/pom.xml
index 766e526..d9b53a4 100644
--- a/cn-universal-framework/cn-universal-common/pom.xml
+++ b/cn-universal-framework/cn-universal-common/pom.xml
@@ -51,5 +51,11 @@
commons-fileupload
commons-fileupload
+
+
+ org.lionsoul
+ ip2region
+ 2.7.0
+
\ No newline at end of file
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/common/annotation/DataScope.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/annotation/DataScope.java
similarity index 93%
rename from cn-universal-admin/src/main/java/cn/universal/admin/common/annotation/DataScope.java
rename to cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/annotation/DataScope.java
index 8b20e5c..bb6a724 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/common/annotation/DataScope.java
+++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/annotation/DataScope.java
@@ -10,7 +10,7 @@
*
*/
-package cn.universal.admin.common.annotation;
+package cn.universal.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/common/annotation/Log.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/annotation/Log.java
similarity index 86%
rename from cn-universal-admin/src/main/java/cn/universal/admin/common/annotation/Log.java
rename to cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/annotation/Log.java
index 0f6aef9..75cd951 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/common/annotation/Log.java
+++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/annotation/Log.java
@@ -10,10 +10,10 @@
*
*/
-package cn.universal.admin.common.annotation;
+package cn.universal.common.annotation;
-import cn.universal.admin.common.enums.BusinessType;
-import cn.universal.admin.common.enums.OperatorType;
+import cn.universal.common.enums.BusinessType;
+import cn.universal.common.enums.OperatorType;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/common/enums/BusinessStatus.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/BusinessStatus.java
similarity index 90%
rename from cn-universal-admin/src/main/java/cn/universal/admin/common/enums/BusinessStatus.java
rename to cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/BusinessStatus.java
index 47aab01..a457de2 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/common/enums/BusinessStatus.java
+++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/BusinessStatus.java
@@ -10,7 +10,7 @@
*
*/
-package cn.universal.admin.common.enums;
+package cn.universal.common.enums;
/** 操作状态枚举 */
public enum BusinessStatus {
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/common/enums/BusinessType.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/BusinessType.java
similarity index 93%
rename from cn-universal-admin/src/main/java/cn/universal/admin/common/enums/BusinessType.java
rename to cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/BusinessType.java
index b96c709..347e725 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/common/enums/BusinessType.java
+++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/BusinessType.java
@@ -10,7 +10,7 @@
*
*/
-package cn.universal.admin.common.enums;
+package cn.universal.common.enums;
/** 业务操作类型枚举 */
public enum BusinessType {
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/common/enums/HttpMethod.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/HttpMethod.java
similarity index 95%
rename from cn-universal-admin/src/main/java/cn/universal/admin/common/enums/HttpMethod.java
rename to cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/HttpMethod.java
index 63178f5..893cf4c 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/common/enums/HttpMethod.java
+++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/HttpMethod.java
@@ -10,7 +10,7 @@
*
*/
-package cn.universal.admin.common.enums;
+package cn.universal.common.enums;
import java.util.HashMap;
import java.util.Map;
diff --git a/cn-universal-admin/src/main/java/cn/universal/admin/common/enums/OperatorType.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/OperatorType.java
similarity index 90%
rename from cn-universal-admin/src/main/java/cn/universal/admin/common/enums/OperatorType.java
rename to cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/OperatorType.java
index 9b0adf6..8dbb4c6 100644
--- a/cn-universal-admin/src/main/java/cn/universal/admin/common/enums/OperatorType.java
+++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/enums/OperatorType.java
@@ -10,7 +10,7 @@
*
*/
-package cn.universal.admin.common.enums;
+package cn.universal.common.enums;
/** 操作人类别枚举 */
public enum OperatorType {
diff --git a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/utils/LocationUtils.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/utils/LocationUtils.java
new file mode 100644
index 0000000..9cd5c45
--- /dev/null
+++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/utils/LocationUtils.java
@@ -0,0 +1,290 @@
+package cn.universal.common.utils;
+
+import cn.hutool.core.util.StrUtil;
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.Validate;
+import org.lionsoul.ip2region.xdb.Searcher;
+
+/**
+ * IP地址地理位置解析工具类(基于IP2Region增强版) 优化点:解决文件损坏问题、增强容错性、完善缓存机制
+ *
+ * @author Aleo
+ */
+@Slf4j
+public class LocationUtils {
+
+ // IP2Region 数据库文件名(建议使用官网最新版)
+ private static final String IP2REGION_FILE_NAME = "ip2region_v4.xdb";
+ // 缓存默认过期时间(1小时)
+ private static final long CACHE_EXPIRE_MILLIS = TimeUnit.HOURS.toMillis(1);
+ // 最大缓存数量(防止内存溢出)
+ private static final int MAX_CACHE_SIZE = 10_000;
+
+ // IP解析结果缓存(value为数组:[地理位置, 过期时间戳])
+ private static final ConcurrentHashMap IP_LOCATION_CACHE =
+ new ConcurrentHashMap<>();
+ // IP2Region搜索器(volatile保证多线程可见性)
+ private static volatile Searcher searcher;
+ // 初始化锁(防止并发初始化导致的资源竞争)
+ private static final Object INIT_LOCK = new Object();
+
+ static {
+ // 类加载时初始化一次
+ initialize();
+ }
+
+ /** 初始化IP2Region(带双重检查锁,避免并发问题) */
+ private static void initialize() {
+ // 已初始化则直接返回
+ if (searcher != null) {
+ return;
+ }
+
+ synchronized (INIT_LOCK) {
+ if (searcher != null) {
+ return;
+ }
+
+ log.info("开始初始化IP2Region,加载数据库文件: {}", IP2REGION_FILE_NAME);
+ try {
+ // 1. 尝试从资源文件加载
+ byte[] dbBuffer = loadDbFile();
+ if (dbBuffer == null || dbBuffer.length == 0) {
+ log.error("IP2Region数据库文件为空或不存在,将使用简单解析模式");
+ return;
+ }
+
+ // 2. 验证文件有效性(简单校验:文件大小至少1MB,避免明显损坏)
+ if (dbBuffer.length < 1024 * 1024) {
+ log.error("IP2Region数据库文件过小({} bytes),疑似损坏", dbBuffer.length);
+ return;
+ }
+
+ // 3. 初始化搜索器
+ searcher = Searcher.newWithBuffer(dbBuffer);
+ log.info("IP2Region初始化成功,数据库文件大小: {} bytes", dbBuffer.length);
+
+ } catch (Exception e) {
+ log.error("IP2Region初始化失败,将使用简单解析模式", e);
+ searcher = null;
+ }
+ }
+ }
+
+ /** 加载IP2Region数据库文件(支持资源文件和外部路径) */
+ private static byte[] loadDbFile() throws IOException {
+ // 优先从项目资源目录加载
+ try (InputStream is =
+ LocationUtils.class.getClassLoader().getResourceAsStream(IP2REGION_FILE_NAME)) {
+ if (is != null) {
+ return readInputStreamToBytes(is);
+ }
+ }
+
+ // 尝试从外部路径加载(方便容器部署时挂载文件)
+ String externalPath = System.getProperty("ip2region.path", IP2REGION_FILE_NAME);
+ if (Files.exists(Paths.get(externalPath))) {
+ log.info("从外部路径加载IP2Region数据库: {}", externalPath);
+ return Files.readAllBytes(Paths.get(externalPath));
+ }
+
+ log.warn("未找到IP2Region数据库文件: {}(资源目录和外部路径均不存在)", IP2REGION_FILE_NAME);
+ return null;
+ }
+
+ /** 分块读取输入流(避免大文件一次性加载导致OOM) */
+ private static byte[] readInputStreamToBytes(InputStream is) throws IOException {
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream();
+ BufferedInputStream bis = new BufferedInputStream(is)) {
+
+ byte[] buffer = new byte[8192];
+ int len;
+ while ((len = bis.read(buffer)) != -1) {
+ os.write(buffer, 0, len);
+ }
+ return os.toByteArray();
+ }
+ }
+
+ /**
+ * 根据IP地址获取地理位置信息
+ *
+ * @param ip IP地址(如183.219.12.163)
+ * @return 地理位置(格式:国家 省份 城市,如"中国 广东省 广州市")
+ */
+ public static String getLocationByIp(String ip) {
+ // 无效IP直接返回
+ if (isInvalidIp(ip)) {
+ return "未知";
+ }
+
+ // 检查缓存(过期自动清理)
+ Object[] cacheValue = IP_LOCATION_CACHE.get(ip);
+ if (cacheValue != null && cacheValue.length == 2) {
+ String location = (String) cacheValue[0];
+ long expireTime = (long) cacheValue[1];
+ if (System.currentTimeMillis() < expireTime) {
+ return location; // 缓存未过期
+ } else {
+ IP_LOCATION_CACHE.remove(ip); // 缓存过期,移除
+ }
+ }
+
+ // 尝试使用IP2Region查询(失败则降级)
+ String location;
+ try {
+ // 确保初始化完成(若之前失败,此处会重试)
+ initialize();
+ location = searcher != null ? queryByIp2Region(ip) : queryBySimpleMode(ip);
+ } catch (Exception e) {
+ log.warn("IP[{}]解析失败,自动降级到简单模式", ip, e);
+ location = queryBySimpleMode(ip);
+ }
+
+ // 缓存结果(控制缓存大小)
+ if (IP_LOCATION_CACHE.size() < MAX_CACHE_SIZE) {
+ IP_LOCATION_CACHE.put(
+ ip, new Object[] {location, System.currentTimeMillis() + CACHE_EXPIRE_MILLIS});
+ } else {
+ log.debug("IP缓存已达最大值({}),暂不缓存新结果", MAX_CACHE_SIZE);
+ }
+
+ return location;
+ }
+
+ /** 使用IP2Region查询地理位置 */
+ private static String queryByIp2Region(String ip) {
+ try {
+ Validate.notNull(searcher, "IP2Region未初始化");
+
+ String region = searcher.search(ip);
+ if (StrUtil.isBlank(region)) {
+ return "未知";
+ }
+
+ // 解析格式:国家|省份|城市|...(过滤无效值"0")
+ String[] parts = region.split("\\|");
+ StringBuilder location = new StringBuilder();
+
+ for (int i = 0; i < Math.min(3, parts.length); i++) { // 只取前3段(国家、省份、城市)
+ String part = parts[i].trim();
+ if (StrUtil.isNotBlank(part) && !"0".equals(part)) {
+ if (location.length() > 0) {
+ location.append(" ");
+ }
+ location.append(part);
+ }
+ }
+
+ return location.length() > 0 ? location.toString() : "未知";
+
+ } catch (Exception e) {
+ // 若出现数组越界等文件损坏特征,主动触发重新初始化
+ if (e.getMessage() != null && e.getMessage().contains("arraycopy")) {
+ log.error("IP2Region数据库文件可能损坏,将尝试重新加载", e);
+ reset(); // 重置搜索器,下次查询会重新初始化
+ }
+ throw new RuntimeException("IP2Region查询异常", e);
+ }
+ }
+
+ /** 简单解析模式(降级方案) */
+ private static String queryBySimpleMode(String ip) {
+ if (isPrivateIp(ip)) {
+ return "内网IP";
+ }
+ if (isChineseIp(ip)) {
+ return "中国";
+ }
+ return "未知";
+ }
+
+ // -------------------- 辅助方法 --------------------
+
+ /** 判断IP是否无效 */
+ private static boolean isInvalidIp(String ip) {
+ return StrUtil.isBlank(ip)
+ || "unknown".equalsIgnoreCase(ip)
+ || "127.0.0.1".equals(ip)
+ || "localhost".equalsIgnoreCase(ip);
+ }
+
+ /** 判断是否为私有IP(内网) */
+ private static boolean isPrivateIp(String ip) {
+ return ip.startsWith("192.168.")
+ || ip.startsWith("10.")
+ || ip.matches("^172\\.(1[6-9]|2[0-9]|3[0-1])\\.")
+ || "127.0.0.1".equals(ip);
+ }
+
+ /** 判断是否为中国IP(基于IP段特征) */
+ private static boolean isChineseIp(String ip) {
+ String[] prefixes = {
+ "1.", "14.", "27.", "36.", "39.", "42.", "49.", "58.", "59.", "60.", "61.", "101.", "103.",
+ "106.", "110.", "111.", "112.", "113.", "114.", "115.", "116.", "117.", "118.", "119.",
+ "120.", "121.", "122.", "123.", "124.", "125.", "126.", "171.", "175.", "180.", "182.",
+ "183.", "202.", "203.", "210.", "211.", "218.", "219.", "220.", "221.", "222.", "223."
+ };
+ for (String prefix : prefixes) {
+ if (ip.startsWith(prefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // -------------------- 管理方法 --------------------
+
+ /** 重置IP2Region(强制重新初始化) */
+ public static void reset() {
+ synchronized (INIT_LOCK) {
+ if (searcher != null) {
+ try {
+ searcher.close();
+ } catch (IOException e) {
+ log.warn("关闭IP2Region搜索器失败", e);
+ }
+ searcher = null;
+ }
+ log.info("IP2Region已重置,下次查询将重新初始化");
+ }
+ }
+
+ /** 清理过期缓存(可定时调用) */
+ public static void cleanExpiredCache() {
+ long now = System.currentTimeMillis();
+ int removed = 0;
+ for (Map.Entry entry : IP_LOCATION_CACHE.entrySet()) {
+ if ((long) entry.getValue()[1] < now) {
+ IP_LOCATION_CACHE.remove(entry.getKey());
+ removed++;
+ }
+ }
+ if (removed > 0) {
+ log.debug("清理过期IP缓存,共移除{}条记录", removed);
+ }
+ }
+
+ /** 检查IP2Region是否可用 */
+ public static boolean isAvailable() {
+ return searcher != null;
+ }
+
+ /** 获取当前缓存大小 */
+ public static int getCacheSize() {
+ return IP_LOCATION_CACHE.size();
+ }
+
+ /** 关闭资源(程序退出时调用) */
+ public static void shutdown() {
+ reset();
+ IP_LOCATION_CACHE.clear();
+ log.info("IP2Region工具已关闭,缓存已清理");
+ }
+}
diff --git a/cn-universal-framework/cn-universal-common/src/main/resources/ip2region_v4.xdb b/cn-universal-framework/cn-universal-common/src/main/resources/ip2region_v4.xdb
new file mode 100644
index 0000000000000000000000000000000000000000..6f86c7d9b5ea27ecbe808e2be198bac1aaee0b92
GIT binary patch
literal 11042429
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%0AxdRZi&BepqSP<9P@0l?
zlvZUMrF}U;$@i8CMkz{?P|A>eluD%iQkcY|lq%UM6-hZtb#e`*E*U^+RHji{
zkTsNc6e)=)
zU6wqQu1FP1jnalvuMDGfTkfKCPc~3`C{IxGnlu3@g-aYtX_A9du~eW`FV|7(mO+%p
zWCo>0xsTGW9HQj$8RLgisKlU@B3UREN*PME(t=W_^rLi3rcj!fRg|`6AEguVox;9{
zC`m#oL-J87m1>llq#dO`89`}6W>H#}O_UzV5lY^lHGwEaNCHafl8aJ_RHD=%ttj=#
z5K7~62c;#+o56a7D^i70qqL#aE5j(=mb)n3lZ3k%FQiK@N+nW>QiHUj)FVSEjmsUB
zmSi2J2l5yt&o3B%l)@wyrBumAsYuFEs*`Idb;$rqqcV-sf~=vmBL^s*%9&YQpCCk{
zQA(DUFJV1H(!9w)DPKxas+J~{+NBSr&?Qs!bsQU%OC3trqzk118AWMY7EoG~9h45_
z6s0rECIqEu$wa9}CQ(|EEtK};7$u)?m>`rQB@v~|l7~{245M^g9-`#6V&YIrlN^+a
zr5mL|8AEAN{Jx3n6@*F*N-2_sQlXTgR4bh*t;#k^`x3m0pEn>$GEmBwQk1Ht9i=`Q
zL1{u}QCgNwlpe_uO5Wcxfha{t2}+gHfKsdUpfn`oDBY1Il-A_|N{_{J4f_=Qr3j^R
z89-@N)=(<=wz-N@jWnawAvaLEDRU_8iO+qkGf0#wl!oOlO7~;~rGW343Y5BK3?+|s
zNjSqjXEAP@0!jl(uCbr4#Y}F5cfDSfWr$k_?pcr4*%V
zX+o)8`cN8?36y4K8Kq5mgwm0CZ(!X)phTdQAn7RON(oAp(tuK{^q@2(<0##cC6w0X
z0ZNa>^Ltp2;4fh)#Y!ql*;0g3mxOHM`UlaHj8fJAnnsiYw#+U{h2J-2DAh^}N>ft0
zjq?H3(u7jG^r18&6DZBfGD@5B2&E(O{sGPh1WE)-36hRdu9TouDGeyKN)JjyGLF(6
zSwd-D9-#DCJa=$Dz+b{pij`E9vZV;6a;ZbrES?q=|p^gjO#H3OB6~;l7Ujbl%iBE
zO(?ZXA4(%KfzqrjqqHfHP&yLthuHrRC=nD1C6AvOKa@fx
z2Bj3qLa9*7P^y&{lscs!rCTzE(!8vqv@QE6orv!~_CEwm6iP{wfl|JdqEszSD78x;
zN+U9X(yT0_v?-5JIuh^y!~Tari9jhq(oxEl5|k>X0i{;yL1{?FQMw~bD6Pu_lpc%c
z0ro%mOBhPAl8REc6rofubtqkvE|dmj6s2idKxs{OP&$xPl+OIzgrF2H$tYz?0ZLb;
z2Bl`{K7hJ9$?F#;0Htt=Ln%#iP%4%Rlvl=7t%rD|zHsa^U|8j%T<
zW@Q-dX-GVOh5ZcKQiswt=|X8hMp2rU
z1(eog2c-i!Md{3u2|+1Z5}(6M|YLCN=p
zCK#nCNkS<@@=+?4YLuF!9i=`QL1{u}QCgNwlpe_uO5R>35Tyu7Kq*~vQ7Vy2lp3TJ
zr5+hVX8kK337Gw>j9XUYh
zRL*$6)=`K=qm(R}C>6+6lxn0Ir4G4)(oLB}X--y9+LAq#j>YH2uXPk8ktij~Wt8&d
z3QASdh*F#MqBJbGQMxPlP}-1(C_ND`pVvAHkZ_dZBn_n;DMqP6>QTBb-6##p7)mp;
zh|+!8Md?sHUh-N;eiDjOjHIBHC50%JNi9k((uq>P+(Kze=22ReZIt%q1SMZz6O2-n
zB%zcc`6!i2HA+p=j#8flycBZ}w_a{eP>KpRJ+Hvtgu~x69$}at@RNve?0wjZFo%(N
z9JEK7K9oje0;O3gkH-Fk%-5Qr7_3cLJZs8gF}Kh!N#}69Fd`Eu&B~oPTrXfP-t3@s
zAg3suNiZQOMN2YDnNon#RjEO#SvpX{gIhMX;rpS
z+LsfQd^1ciN>LJ)iEA|+zuw%-!tuj~1pf&h4^fhVl2@Jy&d1lmr_gj3VZXuJn@!tW
zFxPPFFHP{<@OTJ)hnYudTgLwe?>!J(V^UGdmLinOWg4Y|zcpJZ<<*+Bzr*>194SVr
zTLw`YlNpp!>P!|&g;Iu6t+b%jDg7wjk|~ttWgDe^IYG(y?@cgDQIdpGhUBAEDorTm
z)|;JwzNc2Az7MH+LEA7JRcgR4JEJlm;jXGBn_oO8AEAC
z7EucAGBGIi%Po}VWfi4usp-M>2`<0SnHe0C`vJsf>M?gqEsfeD78o@O8s&Rr74+5X;nr>@LmSFA2Vw=vF@Pv
zmf1il;1ebsr8r4LDMyM?s*w9Ab&i_l|Hiq6hB4EMQjZLwG%j~gT9S2?9>`;qJU?mt
zQ3{h-lu{)dr6MUusZP338jw+xrey)8HQ7PwKu%FQGj2jqik4)QGNl=%8?uK|;-^g6
zr*W>K;aO8RiLt_htf90c2Ph4E&eYt&euOKZH@zrz-!-9MzydhtbfRr5|oBy
z9VO2>6NXZ%l%v!oXTF4afMjV#X;S7;T9GZ3?#`RIFJrAiy_79rKA`$5rVphf8Ct|x
zA#=%G`5KNJ((aiYlnTFY%1}!GhRH=K`kUq$rNM6*k2UO9nE19C_zvb7?ta&d{Q%cf
zh}kiBcCmgT{dxSi6LiZU
zN@FsE(yddI?h)hYhNsy=Db33)qI6$&Q92Zl7sWX8lWRUPj;{Ec(V!SdN3S&Ap)rmE
zB>|-eQWF;AsP@$+{WTaLRElS0j3a*;MXBZ~(-sxusQzhF7#-tiUrtb}j4|UV4V*Qj
zC@shuO3ksR1Em{s6QxO+Luo~}P}-AYlzh&aAe15{5v9wLhffD0RyqN@FsE(xTi)X;%(W@`yKnD1}N4N-2_sQlXTgR4XkgbxJ=<
zw`2;Xd09niTlP^p5#NLuN5K+>Qj%n#lrN`rQB@v~vKQvRBSPxM2$0jNl=NEkP
zjqjUq{vlYF3Ne1TS!8nGg1Lscx0;ADoDWEOy9ukpe1Kn#X{g0K!2Npj;GLLHC~P)0
z*Kl2ely@2LcjJ7+lXkQDA6OgkNRCkQ?lgfYMMw!sJyQ3c7)RHn3#9=WMQK_VP+F56
zln&$+r88Y71f^(6Mk!MYP`WBLC^bt5N;l*tN|Q2&(u!=Mv?s?X`MlQzp%f{JC|#C3
zl&(k>N{!NnQm+i7bX)GCbWb)=dMHm&^6EALD1}QLN@<2>Xt#2#$*Pi
zMY)gCt{kG|@t?*IrBI1MDMhkSDwHymYNZ9GPU%PKmQ0~EFRLhR%RWjc;@gA$2Eh`A
zQj%n#lrN+<^mwWCW$a
zev^xm{|8MrN&_;A(zGm~v?eG(9RZ?HOP
zwo&q)GD|3>e%5586f$k1Q7VwDDAhLqZGAd4(?%Y;O5uOBubIX#`l}p&k!s{8+ctPm%Z;{J;Ly&xs8(dwuwL~
zLDEsml@gRHMGqQ-%eVOPAly1mPlqO{brM90N
zuS3i)gv%mIQIAa$N*PlA1Zxj^kIXPi_hbX5hw=m^ujfnvO5qZRQkvwTR4f%J)ys91
zx+V5`T%Vv^eB4<_p)W8Ko@X6}d6`(0ieGHjea|{7_A^s2J?qFnz%0M~tfPZhn4njl
zbrdPZp?DrtNK)8YM{D6G|EaT%3Zl)GgtLySr1ZjBNB(JM`|?>w&6#EnrDM7BdORPB
zvrIioet&F&v(Gvz`4dx#QiDwAoOQGyYbf2$HG_Y8)=^=exs!j^k8vBK78CKW_}`Eq0q;KRsI1LI{o7eb6B5ym$Ajm;o9@oDj#A!Z*58Zu0*O5)
z52ef-rg7-3qvDU4li{*r6sr%wtM;l)<4^i^_vdLS*c%kBJrXHp1(v8xfjG;6mizwZfU6c;R^>Q!OnH={A;s@(t+$%VeLZVJIrO2wx2bnlUV!ECy!9d{fsF=X?n`so{n{NSMH(oM7;h7
z*9!=c+8L}JI1%5^#X1U>e3a7fm|T>WWF4gka_#f6j=JRdF7_iV&YDA%vc6~vQJR-+
zlul%1F4obJcz+4|A5Q1ZMPl!jy+r8}~O(z-lA>9JIuIp=8bw@slR
z&JC1FElT||k5bc1%`!@x@(86PX%0B&=rGVUyd2|)=vSByloCTs9!kBk`%0`eC@JW^f^aC
z5{Xixc)j+VqX0RH!P!h0^k66Zl7XEm)GGjB}1cUS|Tc@pb5Vqe(74=V+|N
zjQ=IpCwP{ch;obva{kst{}a{)M83bK81%9iB&7%yym$BeCG+~D_JGmp}$Y@;->VM@M-bqb@K=JM7#N8#T$
z*HMc4fk{FsL-J87m1>llq#dO`89`}6W>H#}O_UzV5lY@WCJ?0vNkFMVVtd0>iBs*rk=Vt#B!9^&|+>ygPlz}kie
z8AoaQ=O*$OSXWT?OVj!*TuY(mIg@ydy$gjWCfXy;QGlme_KI`V@FEiw6z6C-(u`e*
za}@oI>CcFB|*ohT*OnyJ5!a}?WPx=_k|r>SjWy=h(r5ZU5a+1qzswFw
zXZlSDN^KuBDIdb~AmPKN;U?x0);?~kK7rQaYLcATS_3FG^0
zoTJ=Hll_@EN6AyB_p@=1(x%PP4CWt(K4+3YkHS4`)YjKY5%g`3a0e7TkJI+zSjtNJpY1gbhz`Q}?Lv#Np
zcrDm}WKK}Z|EcNv8P*F_9GL3EI7g|E&COrNIogt(U&T4{ea=*)RP<{zcY@=GhtHcr
z7mv@kkH_cPn}ip{~icQo;g87RkbLQ=n(MJe}#=HAEfd}y99KF`ME-iYzI|Dg%I7w;%tdcP6x
zC}73Zels5T&Wgu9vP}DGJnnZDk9!mu|L?`)UOkwzO%wUQ@s9H3*7xHb)$N#&AI9T;
zEts=ibL#=V4oeSB>QCZvKZ$tUBf?Chv>*p4oywU<@wgWRUQ;qrs*x3xF8|b2q0}fj
zd-1scK|JnxUE&YAQ$JQjB1&Gv-^N8T6B1C$<1U|NEsgFiH>Z%)8xAttyde{HJ&HNlbp
z4b%Ri1V@9PFrIS>_}%9O*SBoazk%-$sVk=Dn+cBcR?YSr#sibc6%@{KTeqs}`TeA=YPoOhIZ)?}kpB;_d8$pT7=
z=gbq7y5o#T{CWKDCcdYHq7)-#D9t9AgT(WWwl0{si#QIrFH_0q9VMig5|k>X2PN-k
zOfE{}Qg<0+hXJ{gao$m*w4oIDI+KP{j$B8nTV_x?d4rkF#c_ato;gLSE#Jfx;Mk#|
z&CjaB-9i`tg{-3~khvQL`{we%9
z6hCW5K6BpD@c)?GDBYFA8Jruq^*J*&hxHEoUp0@vd*0E^|C-?+;&otZ&on*8{6p&V
zX6r?Xj+)Pyte`|k>#s7C(TR?(B$(Tm5*Qqo
zCY0Kx52X>AKxtN%QQDM8C>@FSUnDvTln9g(B;@Uhjt=TgV{4)#ulJd<4<nIBGcba}{Bp;Yk^GltUquu1wT<_0ok7NyjWnH`jBZkpR4$NWS0Ei;JH
zn9QKGDECpC|Abi{#e6}}f15ifEy-h)QpZdYN+F*#$tYz?0ZKPy52dPcv-2#*4;!B`
z{h!6$f&YxTatG@QlD=TFzKrz;!3)OgYd8
zDMhJTnow$&K9oje0;O5Wbr&4<$ij;+INFgM-wTe)e#`8=^n#;Ae^c>07aWxZm|B!t
zq!XonY5Ls@jw%C9LC^(9y)QQ{ufTI*Bg{NR>4}_#UvP9M!qmOyf};Vs5qZH;%+sb2
zrS@nu{@M$Uren;?*$a-Y#F`D1QsPW-`~^qj3FZz;)91|sN(XW^@q(kq3+6%Y1xML`
zYU)r5$umB0yx=HLuAt=iXJ)hDf}`;_ne0Nm4qTHiltTX8bpOQ#MXw+Th5U)tV(!BOa-@%#vm8={9z!pHGC&?-GB
zm44F1e(HjwtY^(CO1G!Y$qd#bJp6)*o4w$uTW04jIGX&jNnF6bfhy_y>IFxc_sj}P
zdlK~Z3yy{*^cy%1$X_u9-@^WZt5Snf&$<~x>EOGjdlO>=-z{^njX#IEADDn2UcleK
z;#hZ03rg31Y(gGloq^v^O(;q&(uq>P+(Kze=22P||NRS&uKu6tKq>FQw4u~;XhwgD
zbqa~UGQ%is$U~IwADLUv;rqkLv8ntu)+aPbD@r}$e}eHq(+iS*qwz&aj_%2=7boHG
z0+aA}Y{t_!$x+U4n?sZy`iUZC5%aR<`yuu8{CONuw-pr#kl4vd`
zCpqd&G0VS?aX><j@KFLu+
zwz=|#Bu6oSYNGOz9QC}>JVxm>-?SAZIXZlkDX2(tG}~xat|vK)>NP{}$JpSG?0q1~
z(W7DG{m~>x{v#&nW|E`&kDKc#4UHO~PbN8v8#m!!N^(>?Z_*c%9Ql96+*nLJ3U*EPL;N{({M5|vV?9CY&&|pq<{R>UVY(kDIV$_5
zY4}x=qjm8-!g>dPS$Pi62agwC{EeN6i;nI;W!j&<=;+B=b3OK=qri9*fl`8`qf{ad
zD78utN{_`e;i4md2}3DXQc)_BvOl=!s8cdtchS*gnVCarMbgSII?AswMU{9hsQGI%
zhti4+S6y`E^$rt&Qndb8YMMtR(CiA
zP}XOT`!723`;ck)FwQ3geAHx(Ty!+@F%$N2oImK2m0K7W)P2dcee0s5iT^c2TNm;7
z6&GFh_e~c{1LE_8i;f0&OxX`HF7W=5Nk=JH9-|cYz+6LVK+gR5qN7a7`3dF+4yAJM
zqNC=06Mlem59z-!LnviGHkrS~Ye9hoJ-O(p{#Rz_*Vs?c`@9MENOrX2X(GLn9UZ>N
zc)ldr(cu~6@1N|bF~B6fEZNb{%S}OWvZH3%LTOK`UXkqRuEd2TJ4%y!ly=4MmC24`
zq!6Vt=|pK&`XiDZWu7yG$;pla{?M$x9*>3fJabx5Mfa+ZvjZ??}eyJtw>4YUA@a$&P{~5~W0mZc26(-fSvRivCw~{awk9LR(GyyOSN2
z|C^~p>6(Oh;B~;`Ka3wrozmWk=R@v$%(X5&7n0v=BD*m@*pP=PJ(2qV#QA_jseT{k
z1@82kgZJb3;qnJe&W&V8xBko2d??vbq+h!J}^dFd9lp17VCmEmLfOGOg
zbNxryzcBy6`2HC415vVx(vhq`#JYgVM`i`3D?c?=C^gF99>xl#`=%PD*aLI*=eSac^$fgzVFFMJmpGKtBnPEpsX(b-uA|f~gD8#33`+N97p20-ru3H>H#AA*6RZzt
zl?N!5|H{;%G%5!uol3}2GVZsFxfj1*PJn|$R$UuA2ZW8FFBg~xJmoOCEUO3l8YHN
z3!l7%`&(UdPd;U4ZeMZ~`e{==amms6vt|jU(MePAnM;oLq-qMs0|B2kV<@Fen=+JY
zWeTMe@%^7mj-n(9r3}eOsZ^>_YLa%8`XqD##{o6pG|ed8logb=#Ao%Aqe#g^sZH9y
zjn@bN@0cQ#2Bi19mmGy}n0l0E144kC62j%vN`7GO
z{TS;FW*(aRDDBE2N*+Hkeki3JnDoO-j^-Ylq$A8XWJonixzCw9C?)^e?4i{CyvaJf
z