1. 调整 e 办相关用户组织同步报文接受逻辑

2. 新增针对 e 办的接口日志记录功能

(cherry picked from commit 28aae25bef)
This commit is contained in:
chenbowen
2025-08-28 15:47:49 +08:00
committed by chenbowen
parent a53105088d
commit 4559f7268f
26 changed files with 1420 additions and 119 deletions

View File

@@ -0,0 +1,83 @@
/*
Yudao Database Transfer Tool
Source Server Type : MySQL
Target Server Type : DM8
Date: 2025-08-28 14:12:23
*/
-- ----------------------------
-- Table structure for system_sync_log
-- ----------------------------
CREATE TABLE system_sync_log (
id bigint NOT NULL PRIMARY KEY,
bim_request_id varchar(64) DEFAULT '' NULL,
service_name varchar(100) NOT NULL,
request_method varchar(16) DEFAULT 'POST' NOT NULL,
request_url varchar(500) NOT NULL,
client_ip varchar(50) NOT NULL,
user_agent varchar(512) DEFAULT NULL NULL,
request_time datetime NOT NULL,
response_time datetime DEFAULT NULL NULL,
duration bigint DEFAULT NULL NULL,
encrypted_request text NOT NULL,
decrypted_request text NULL,
status smallint DEFAULT 0 NOT NULL,
error_code varchar(100) DEFAULT NULL NULL,
error_message varchar(1000) DEFAULT NULL NULL,
exception_stack text NULL,
response_data text NULL,
encrypted_response text NULL,
auth_user varchar(100) DEFAULT NULL NULL,
decrypt_status smallint DEFAULT 0 NOT NULL,
signature_verify_status smallint DEFAULT 0 NOT NULL,
auth_status smallint DEFAULT 0 NOT NULL,
business_result varchar(100) DEFAULT NULL NULL,
extra text NULL,
creator varchar(64) DEFAULT '' NULL,
create_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater varchar(64) DEFAULT '' NULL,
update_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
deleted bit DEFAULT '0' NOT NULL
);
CREATE INDEX idx_system_sync_log_01 ON system_sync_log (bim_request_id);
CREATE INDEX idx_system_sync_log_02 ON system_sync_log (service_name);
CREATE INDEX idx_system_sync_log_03 ON system_sync_log (request_time);
CREATE INDEX idx_system_sync_log_04 ON system_sync_log (status);
CREATE INDEX idx_system_sync_log_05 ON system_sync_log (client_ip);
CREATE INDEX idx_system_sync_log_06 ON system_sync_log (auth_user);
COMMENT ON COLUMN system_sync_log.id IS '日志主键';
COMMENT ON COLUMN system_sync_log.bim_request_id IS '外部请求ID';
COMMENT ON COLUMN system_sync_log.service_name IS '接口名称/服务名称';
COMMENT ON COLUMN system_sync_log.request_method IS '请求方法';
COMMENT ON COLUMN system_sync_log.request_url IS '请求URL';
COMMENT ON COLUMN system_sync_log.client_ip IS '客户端IP地址';
COMMENT ON COLUMN system_sync_log.user_agent IS '用户代理字符串';
COMMENT ON COLUMN system_sync_log.request_time IS '请求开始时间';
COMMENT ON COLUMN system_sync_log.response_time IS '请求结束时间';
COMMENT ON COLUMN system_sync_log.duration IS '请求处理耗时(毫秒)';
COMMENT ON COLUMN system_sync_log.encrypted_request IS '原始加密请求体';
COMMENT ON COLUMN system_sync_log.decrypted_request IS '解密后的请求体';
COMMENT ON COLUMN system_sync_log.status IS '响应状态 0-成功 1-解密失败 2-签名验证失败 3-认证失败 4-业务处理失败 5-系统异常';
COMMENT ON COLUMN system_sync_log.error_code IS '错误码';
COMMENT ON COLUMN system_sync_log.error_message IS '错误信息';
COMMENT ON COLUMN system_sync_log.exception_stack IS '异常堆栈';
COMMENT ON COLUMN system_sync_log.response_data IS '响应数据(加密前)';
COMMENT ON COLUMN system_sync_log.encrypted_response IS '加密后的响应数据';
COMMENT ON COLUMN system_sync_log.auth_user IS '认证用户';
COMMENT ON COLUMN system_sync_log.decrypt_status IS '解密状态 0-成功 1-失败';
COMMENT ON COLUMN system_sync_log.signature_verify_status IS '签名验证状态 0-成功 1-失败';
COMMENT ON COLUMN system_sync_log.auth_status IS '认证状态 0-成功 1-失败';
COMMENT ON COLUMN system_sync_log.business_result IS '业务处理结果';
COMMENT ON COLUMN system_sync_log.extra IS '额外信息';
COMMENT ON COLUMN system_sync_log.creator IS '创建者';
COMMENT ON COLUMN system_sync_log.create_time IS '创建时间';
COMMENT ON COLUMN system_sync_log.updater IS '更新者';
COMMENT ON COLUMN system_sync_log.update_time IS '更新时间';
COMMENT ON COLUMN system_sync_log.deleted IS '是否删除';
COMMENT ON TABLE system_sync_log IS '同步接口调用日志表';

View File

@@ -0,0 +1,11 @@
-- 同步日志状态字典数据
INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES
(999, '同步日志状态', 'sync_log_status', 0, '同步接口调用日志状态', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', b'0');
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted) VALUES
(9990, 1, '成功', '0', 'sync_log_status', 0, 'success', '', '同步接口调用成功', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', b'0'),
(9991, 2, '解密失败', '1', 'sync_log_status', 0, 'danger', '', '请求解密失败', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', b'0'),
(9992, 3, '签名验证失败', '2', 'sync_log_status', 0, 'warning', '', '签名验证失败', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', b'0'),
(9993, 4, '认证失败', '3', 'sync_log_status', 0, 'warning', '', '用户认证失败', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', b'0'),
(9994, 5, '业务处理失败', '4', 'sync_log_status', 0, 'danger', '', '业务逻辑处理失败', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', b'0'),
(9995, 6, '系统异常', '5', 'sync_log_status', 0, 'danger', '', '系统内部异常', 'admin', '2024-01-01 00:00:00', 'admin', '2024-01-01 00:00:00', b'0');

View File

@@ -0,0 +1,17 @@
-- 同步接口日志菜单权限 SQL 脚本
-- 为同步接口日志查询界面创建相应的菜单和权限
-- 在审计日志(108)下新增同步日志菜单
INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES (502, '同步日志', '', 2, 3, 108, 'sync-log', 'ep:data-line', 'system/synclog/index', 'SystemSyncLog', 0, '1', '1', '1', 'admin', '2024-08-28 00:00:00', 'admin', '2024-08-28 00:00:00', '0');
-- 同步日志查询权限按钮
INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted)
VALUES (5020, '同步日志查询', 'system:sync-log:query', 3, 1, 502, '', '', '', '', 0, '1', '1', '1', 'admin', '2024-08-28 00:00:00', 'admin', '2024-08-28 00:00:00', '0');
-- 为超级管理员角色分配菜单权限
INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted)
VALUES (NULL, 1, 502, 'admin', '2024-08-28 00:00:00', 'admin', '2024-08-28 00:00:00', '0');
INSERT INTO system_role_menu (id, role_id, menu_id, creator, create_time, updater, update_time, deleted)
VALUES (NULL, 1, 5020, 'admin', '2024-08-28 00:00:00', 'admin', '2024-08-28 00:00:00', '0');

View File

@@ -0,0 +1,41 @@
-- Table structure for system_sync_log
-- ----------------------------
DROP TABLE IF EXISTS `system_sync_log`;
CREATE TABLE `system_sync_log` (
`id` bigint NOT NULL COMMENT '日志主键',
`bim_request_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '外部请求ID',
`service_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '接口名称/服务名称',
`request_method` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'POST' COMMENT '请求方法',
`request_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '请求URL',
`client_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户端IP地址',
`user_agent` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户代理字符串',
`request_time` datetime NOT NULL COMMENT '请求开始时间',
`response_time` datetime NULL DEFAULT NULL COMMENT '请求结束时间',
`duration` bigint NULL DEFAULT NULL COMMENT '请求处理耗时(毫秒)',
`encrypted_request` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '原始加密请求体',
`decrypted_request` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '解密后的请求体',
`status` tinyint NOT NULL DEFAULT 0 COMMENT '响应状态 0-成功 1-解密失败 2-签名验证失败 3-认证失败 4-业务处理失败 5-系统异常',
`error_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '错误码',
`error_message` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '错误信息',
`exception_stack` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '异常堆栈',
`response_data` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '响应数据(加密前)',
`encrypted_response` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '加密后的响应数据',
`auth_user` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '认证用户',
`decrypt_status` tinyint NOT NULL DEFAULT 0 COMMENT '解密状态 0-成功 1-失败',
`signature_verify_status` tinyint NOT NULL DEFAULT 0 COMMENT '签名验证状态 0-成功 1-失败',
`auth_status` tinyint NOT NULL DEFAULT 0 COMMENT '认证状态 0-成功 1-失败',
`business_result` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '业务处理结果',
`extra` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '额外信息',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_bim_request_id` (`bim_request_id`) USING BTREE COMMENT '外部请求ID索引',
INDEX `idx_service_name` (`service_name`) USING BTREE COMMENT '服务名称索引',
INDEX `idx_request_time` (`request_time`) USING BTREE COMMENT '请求时间索引',
INDEX `idx_status` (`status`) USING BTREE COMMENT '状态索引',
INDEX `idx_client_ip` (`client_ip`) USING BTREE COMMENT '客户端IP索引',
INDEX `idx_auth_user` (`auth_user`) USING BTREE COMMENT '认证用户索引'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '同步接口调用日志表';

View File

@@ -0,0 +1,63 @@
package cn.iocoder.yudao.module.system.enums.dept;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 机构类型枚举
*
* @author chenbowen
*/
@Getter
@AllArgsConstructor
public enum DeptTypeEnum {
/**
* 单位/公司
*/
COMPANY(28, "单位"),
/**
* 部门
*/
DEPARTMENT(26, "部门");
/**
* 类型编码
*/
private final Integer code;
/**
* 类型名称
*/
private final String name;
/**
* 根据编码获取枚举
*/
public static DeptTypeEnum getByCode(Integer code) {
if (code == null) {
return null;
}
for (DeptTypeEnum value : DeptTypeEnum.values()) {
if (value.getCode().equals(code)) {
return value;
}
}
return null;
}
/**
* 判断是否为公司
*/
public static boolean isCompany(Integer code) {
return COMPANY.getCode().equals(code);
}
/**
* 判断是否为部门
*/
public static boolean isDepartment(Integer code) {
return DEPARTMENT.getCode().equals(code);
}
}

View File

@@ -24,7 +24,7 @@ public class DeptSaveReqVO {
@Size(max = 30, message = "部门名称长度不能超过 30 个字符")
private String name;
@Schema(description = "父部门 ID", example = "1024")
@Schema(description = "父部门 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024(顶级部门父级 Id 为 0)")
private Long parentId;
@Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@@ -43,7 +43,7 @@ public class DeptSaveReqVO {
@Size(max = 50, message = "邮箱长度不能超过 50 个字符")
private String email;
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@Schema(description = "状态,见 CommonStatusEnum 枚举0 开启 1 关闭", requiredMode = Schema.RequiredMode.REQUIRED, example = "0 开启 1 关闭")
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;

View File

@@ -11,9 +11,11 @@ import cn.iocoder.yudao.module.system.controller.admin.sync.vo.org.*;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.schema.SchemaRequestVO;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.schema.SchemaResponseVO;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.user.*;
import cn.iocoder.yudao.module.system.enums.sync.SyncLogStatusEnum;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import cn.iocoder.yudao.module.system.service.sync.OrgSyncService;
import cn.iocoder.yudao.module.system.service.sync.SchemaSyncService;
import cn.iocoder.yudao.module.system.service.sync.SyncLogService;
import cn.iocoder.yudao.module.system.service.sync.UserSyncService;
import cn.iocoder.yudao.module.system.util.sync.SyncVerifyUtil;
import com.alibaba.fastjson.JSON;
@@ -25,6 +27,8 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -51,23 +55,50 @@ public class SyncController {
private AdminAuthService adminAuthService;
@Resource
private OAuth2TokenCommonApi oauth2TokenApi;
@Resource
private SyncLogService syncLogService;
@PostMapping("/SchemaService")
@TenantIgnore
@PermitAll
public String getSchema(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("SchemaService",
"/system/sync/SchemaService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
SchemaRequestVO req = decryptRequest(encryptedBody, SchemaRequestVO.class);
SchemaRequestVO req = decryptRequest(encryptedBody, SchemaRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(schemaService.getSchema(req));
// 业务处理
SchemaResponseVO response = schemaService.getSchema(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
SchemaResponseVO errorResp = new SchemaResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -76,17 +107,42 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String createOrg(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("OrgCreateService",
"/system/sync/OrgCreateService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
OrgCreateRequestVO req = decryptRequest(encryptedBody, OrgCreateRequestVO.class);
OrgCreateRequestVO req = decryptRequest(encryptedBody, OrgCreateRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(organizationService.createOrg(req));
// 业务处理
OrgCreateResponseVO response = organizationService.createOrg(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
OrgCreateResponseVO errorResp = new OrgCreateResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -95,17 +151,42 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String deleteOrg(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("OrgDeleteService",
"/system/sync/OrgDeleteService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
OrgDeleteRequestVO req = decryptRequest(encryptedBody, OrgDeleteRequestVO.class);
OrgDeleteRequestVO req = decryptRequest(encryptedBody, OrgDeleteRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(organizationService.deleteOrg(req));
// 业务处理
OrgDeleteResponseVO response = organizationService.deleteOrg(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
OrgDeleteResponseVO errorResp = new OrgDeleteResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -114,17 +195,42 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String updateOrg(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("OrgUpdateService",
"/system/sync/OrgUpdateService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
OrgUpdateRequestVO req = decryptRequest(encryptedBody, OrgUpdateRequestVO.class);
OrgUpdateRequestVO req = decryptRequest(encryptedBody, OrgUpdateRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(organizationService.updateOrg(req));
// 业务处理
OrgUpdateResponseVO response = organizationService.updateOrg(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
OrgUpdateResponseVO errorResp = new OrgUpdateResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -133,17 +239,42 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String listOrg(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("QueryAllOrgIdsService",
"/system/sync/QueryAllOrgIdsService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
OrgListRequestVO req = decryptRequest(encryptedBody, OrgListRequestVO.class);
OrgListRequestVO req = decryptRequest(encryptedBody, OrgListRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(organizationService.listOrgIds(req));
// 业务处理
OrgListResponseVO response = organizationService.listOrgIds(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
OrgListResponseVO errorResp = new OrgListResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -152,17 +283,42 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String getOrg(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("QueryOrgByIdService",
"/system/sync/QueryOrgByIdService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
OrgGetRequestVO req = decryptRequest(encryptedBody, OrgGetRequestVO.class);
OrgGetRequestVO req = decryptRequest(encryptedBody, OrgGetRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(organizationService.getOrgById(req));
// 业务处理
OrgGetResponseVO response = organizationService.getOrgById(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
OrgGetResponseVO errorResp = new OrgGetResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -171,17 +327,42 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String createUser(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("UserCreateService",
"/system/sync/UserCreateService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
UserCreateRequestVO req = decryptRequest(encryptedBody, UserCreateRequestVO.class);
UserCreateRequestVO req = decryptRequest(encryptedBody, UserCreateRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(accountService.createUser(req));
// 业务处理
UserCreateResponseVO response = accountService.createUser(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
UserCreateResponseVO errorResp = new UserCreateResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -190,17 +371,42 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String deleteUser(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("UserDeleteService",
"/system/sync/UserDeleteService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
UserDeleteRequestVO req = decryptRequest(encryptedBody, UserDeleteRequestVO.class);
UserDeleteRequestVO req = decryptRequest(encryptedBody, UserDeleteRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(accountService.deleteUser(req));
// 业务处理
UserDeleteResponseVO response = accountService.deleteUser(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
UserDeleteResponseVO errorResp = new UserDeleteResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -209,17 +415,42 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String updateUser(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("UserUpdateService",
"/system/sync/UserUpdateService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
UserUpdateRequestVO req = decryptRequest(encryptedBody, UserUpdateRequestVO.class);
UserUpdateRequestVO req = decryptRequest(encryptedBody, UserUpdateRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(accountService.updateUser(req));
// 业务处理
UserUpdateResponseVO response = accountService.updateUser(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
UserUpdateResponseVO errorResp = new UserUpdateResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -228,17 +459,42 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String listUser(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("QueryAllUserIdsService",
"/system/sync/QueryAllUserIdsService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
UserListRequestVO req = decryptRequest(encryptedBody, UserListRequestVO.class);
UserListRequestVO req = decryptRequest(encryptedBody, UserListRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(accountService.listUserIds(req));
// 业务处理
UserListResponseVO response = accountService.listUserIds(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
UserListResponseVO errorResp = new UserListResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
@@ -247,49 +503,105 @@ public class SyncController {
@TenantIgnore
@PermitAll
public String getUser(@RequestBody String encryptedBody) {
// 记录请求开始
Long logId = syncLogService.logRequestStart("QueryUserByIdService",
"/system/sync/QueryUserByIdService",
getClientIp(),
getRequest().getHeader("User-Agent"),
encryptedBody);
String bimRequestId = null;
try {
UserGetRequestVO req = decryptRequest(encryptedBody, UserGetRequestVO.class);
UserGetRequestVO req = decryptRequest(encryptedBody, UserGetRequestVO.class, logId);
bimRequestId = req.getBimRequestId();
return encrypt(accountService.getUserById(req));
// 业务处理
UserGetResponseVO response = accountService.getUserById(req);
String responseJson = JSON.toJSONString(response);
String encryptedResponse = encrypt(response);
// 记录成功完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SUCCESS.getStatus(),
null, null, null, responseJson, encryptedResponse, response.getResultCode());
return encryptedResponse;
} catch (Exception e) {
UserGetResponseVO errorResp = new UserGetResponseVO();
errorResp.setBimRequestId(bimRequestId);
errorResp.setResultCode("500");
errorResp.setMessage(e.getMessage());
return encrypt(errorResp);
String responseJson = JSON.toJSONString(errorResp);
String encryptedResponse = encrypt(errorResp);
// 记录异常完成
syncLogService.logRequestComplete(logId, SyncLogStatusEnum.SYSTEM_ERROR.getStatus(),
"SYSTEM_ERROR", e.getMessage(), getStackTrace(e), responseJson, encryptedResponse, "500");
return encryptedResponse;
}
}
private <T> T decryptRequest(String encryptedBody, Class<T> clazz) {
String bodyJson;
private <T> T decryptRequest(String encryptedBody, Class<T> clazz, Long logId) {
String bodyJson = "";
String bimRequestId = null;
String authUser = null;
try {
// 解密
bodyJson = SyncVerifyUtil.decrypt(encryptedBody, encryptKey, "AES");
} catch (Exception e) {
throw exception(SYNC_DECRYPT_TYPE);
}
Map<String, Object> map = JSON.parseObject(bodyJson, Map.class);
if (!SyncVerifyUtil.verifySignature(map, "MD5")) {
bimRequestId = (String) map.get("bimRequestId");
authUser = (String) map.getOrDefault("bimRemoteUser", "");
// 记录解密成功
syncLogService.logDecryptResult(logId, bimRequestId, bodyJson, authUser, true);
// 签名验证
boolean signatureValid = SyncVerifyUtil.verifySignature(map, "MD5");
syncLogService.logSignatureVerifyResult(logId, signatureValid);
if (!signatureValid) {
throw exception(SYNC_SIGNATURE_VERIFY_FAILED);
}
// 用户认证
AuthLoginReqVO authLoginReqVO = new AuthLoginReqVO();
authLoginReqVO.setUsername((String) map.getOrDefault("bimRemoteUser", ""));
authLoginReqVO.setUsername(authUser);
authLoginReqVO.setPassword((String) map.getOrDefault("bimRemotePwd", ""));
authLoginReqVO.setCaptchaVerification(encryptKey);
AuthLoginRespVO login = adminAuthService.login(authLoginReqVO);
// 校验访问令牌
try {
AuthLoginRespVO login = adminAuthService.login(authLoginReqVO);
OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(login.getAccessToken()).getCheckedData();
if (accessToken == null) {
syncLogService.logAuthResult(logId, false);
throw exception(AUTH_LOGIN_USER_DISABLED);
}
// 记录认证成功
syncLogService.logAuthResult(logId, true);
LoginUser loginUser = new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
.setInfo(accessToken.getUserInfo())
.setTenantId(accessToken.getTenantId())
.setScopes(accessToken.getScopes())
.setExpiresTime(accessToken.getExpiresTime());
SecurityFrameworkUtils.setLoginUser(loginUser, getRequest());
} catch (Exception e) {
syncLogService.logAuthResult(logId, false);
throw e;
}
return JSON.parseObject(bodyJson, clazz);
} catch (Exception e) {
// 如果是解密失败,记录解密失败
if (bodyJson == null) {
syncLogService.logDecryptResult(logId, bimRequestId, null, authUser, false);
}
throw e;
}
}
private <T> String encrypt(T object) {
@@ -302,4 +614,24 @@ public class SyncController {
}
return bodyJson;
}
/**
* 获取客户端IP地址
*/
private String getClientIp() {
return getRequest().getRemoteAddr();
}
/**
* 获取异常堆栈信息
*/
private String getStackTrace(Throwable throwable) {
if (throwable == null) {
return null;
}
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
return sw.toString();
}
}

View File

@@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.system.controller.admin.sync;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncLogPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncLogRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sync.SyncLogDO;
import cn.iocoder.yudao.module.system.service.sync.SyncLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/**
* 同步接口日志 Controller
*
* @author 芋道源码
*/
@Tag(name = "管理后台 - 同步接口日志")
@RestController
@RequestMapping("/system/sync-log")
@Validated
public class SyncLogController {
@Resource
private SyncLogService syncLogService;
@GetMapping("/get")
@Operation(summary = "获得同步接口日志")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:sync-log:query')")
public CommonResult<SyncLogRespVO> getSyncLog(@RequestParam("id") Long id) {
SyncLogDO syncLog = syncLogService.getSyncLog(id);
return success(BeanUtils.toBean(syncLog, SyncLogRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得同步接口日志分页")
@PreAuthorize("@ss.hasPermission('system:sync-log:query')")
public CommonResult<PageResult<SyncLogRespVO>> getSyncLogPage(@Valid SyncLogPageReqVO pageReqVO) {
PageResult<SyncLogDO> pageResult = syncLogService.getSyncLogPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, SyncLogRespVO.class));
}
}

View File

@@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.system.controller.admin.sync.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 同步接口日志分页 Request VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - 同步接口日志分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SyncLogPageReqVO extends PageParam {
@Schema(description = "外部请求ID", example = "REQ_12345")
private String bimRequestId;
@Schema(description = "服务名称", example = "SchemaService")
private String serviceName;
@Schema(description = "响应状态", example = "0")
private Integer status;
@Schema(description = "客户端IP", example = "192.168.1.100")
private String clientIp;
@Schema(description = "认证用户", example = "admin")
private String authUser;
@Schema(description = "请求时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] requestTime;
}

View File

@@ -0,0 +1,92 @@
package cn.iocoder.yudao.module.system.controller.admin.sync.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 同步接口日志 Response VO
*
* @author 芋道源码
*/
@Schema(description = "管理后台 - 同步接口日志 Response VO")
@Data
public class SyncLogRespVO {
@Schema(description = "日志主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "外部请求ID", example = "REQ_12345")
private String bimRequestId;
@Schema(description = "服务名称", example = "SchemaService")
private String serviceName;
@Schema(description = "请求方法", example = "POST")
private String requestMethod;
@Schema(description = "请求URL", example = "/system/sync/SchemaService")
private String requestUrl;
@Schema(description = "客户端IP地址", example = "192.168.1.100")
private String clientIp;
@Schema(description = "用户代理字符串")
private String userAgent;
@Schema(description = "请求开始时间", example = "2024-01-01 12:00:00")
private LocalDateTime requestTime;
@Schema(description = "请求结束时间", example = "2024-01-01 12:00:01")
private LocalDateTime responseTime;
@Schema(description = "请求处理耗时(毫秒)", example = "1000")
private Long duration;
@Schema(description = "原始加密请求体")
private String encryptedRequest;
@Schema(description = "解密后的请求体")
private String decryptedRequest;
@Schema(description = "响应状态", example = "0")
private Integer status;
@Schema(description = "错误码", example = "SYNC_001")
private String errorCode;
@Schema(description = "错误信息", example = "解密失败")
private String errorMessage;
@Schema(description = "异常堆栈")
private String exceptionStack;
@Schema(description = "响应数据(加密前)")
private String responseData;
@Schema(description = "加密后的响应数据")
private String encryptedResponse;
@Schema(description = "认证用户", example = "admin")
private String authUser;
@Schema(description = "解密状态", example = "0")
private Integer decryptStatus;
@Schema(description = "签名验证状态", example = "0")
private Integer signatureVerifyStatus;
@Schema(description = "认证状态", example = "0")
private Integer authStatus;
@Schema(description = "业务处理结果", example = "200")
private String businessResult;
@Schema(description = "额外信息")
private String extra;
@Schema(description = "创建时间", example = "2024-01-01 12:00:00")
private LocalDateTime createTime;
}

View File

@@ -24,8 +24,6 @@ public class OrgCreateRequestVO {
private String email;
@Schema(description = "机构 状态", required = true)
private Integer status;
@Schema(description = "机构 是否公司")
private Boolean isCompany;
@Schema(description = "机构 是否集团")
private Boolean isGroup;
@Schema(description = "机构类型", required = true, example = "28=单位、26=部门")
private Integer deptType;
}

View File

@@ -30,8 +30,8 @@ public class OrgUpdateRequestVO extends DeptDO {
private String email;
@Schema(description = "机构 状态", required = true)
private Integer status;
@Schema(description = "机构 是否公司")
private Boolean isCompany;
@Schema(description = "机构类型", required = true, example = "28=单位、26=部门")
private Integer deptType;
@Schema(description = "机构 是否集团")
private Boolean isGroup;
}

View File

@@ -40,7 +40,7 @@ public class UserSaveReqVO {
@DiffLogField(name = "备注")
private String remark;
@Schema(description = "部门编号", example = "我是一个用户")
@Schema(description = "部门编号数组",requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@DiffLogField(name = "部门", function = DeptParseFunction.NAME)
private Set<Long> deptIds;

View File

@@ -0,0 +1,166 @@
package cn.iocoder.yudao.module.system.dal.dataobject.sync;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
/**
* 同步接口调用日志表
*
* 用于记录外部系统调用同步接口的详细信息,包括加密和解密的过程
*
* @author 芋道源码
*/
@TableName("system_sync_log")
@KeySequence("system_sync_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SyncLogDO extends BaseDO {
/**
* 日志主键
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 外部请求ID
* 从请求参数中的 bimRequestId 获取
*/
private String bimRequestId;
/**
* 接口名称/服务名称
* 如SchemaService、OrgCreateService、UserCreateService 等
*/
private String serviceName;
/**
* 请求方法
* 固定为 POST
*/
private String requestMethod;
/**
* 请求URL
*/
private String requestUrl;
/**
* 客户端IP地址
*/
private String clientIp;
/**
* 用户代理字符串
*/
private String userAgent;
/**
* 请求开始时间
*/
private LocalDateTime requestTime;
/**
* 请求结束时间
*/
private LocalDateTime responseTime;
/**
* 请求处理耗时(毫秒)
*/
private Long duration;
/**
* 原始加密请求体
* 存储完整的加密数据
*/
private String encryptedRequest;
/**
* 解密后的请求体
* JSON 格式,如果解密失败则为空
*/
private String decryptedRequest;
/**
* 响应状态
* 0-成功, 1-解密失败, 2-签名验证失败, 3-认证失败, 4-业务处理失败, 5-系统异常
*/
private Integer status;
/**
* 错误码
* 成功时为空,失败时记录具体错误码
*/
private String errorCode;
/**
* 错误信息
* 成功时为空,失败时记录具体错误信息
*/
private String errorMessage;
/**
* 异常堆栈
* 发生异常时记录完整的堆栈信息
*/
private String exceptionStack;
/**
* 响应数据(加密前)
* JSON 格式的响应数据
*/
private String responseData;
/**
* 加密后的响应数据
* 返回给客户端的加密数据
*/
private String encryptedResponse;
/**
* 认证用户
* 从请求中解析的 bimRemoteUser
*/
private String authUser;
/**
* 解密状态
* 0-成功, 1-失败
*/
private Integer decryptStatus;
/**
* 签名验证状态
* 0-成功, 1-失败
*/
private Integer signatureVerifyStatus;
/**
* 认证状态
* 0-成功, 1-失败
*/
private Integer authStatus;
/**
* 业务处理结果
* 从业务响应中的 resultCode 获取
*/
private String businessResult;
/**
* 额外信息
* JSON格式存储一些额外的业务信息
*/
private String extra;
}

View File

@@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.system.dal.mysql.sync;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.dal.dataobject.sync.SyncLogDO;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncLogPageReqVO;
import org.apache.ibatis.annotations.Mapper;
/**
* 同步接口日志 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface SyncLogMapper extends BaseMapperX<SyncLogDO> {
default PageResult<SyncLogDO> selectPage(SyncLogPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<SyncLogDO>()
.eqIfPresent(SyncLogDO::getBimRequestId, reqVO.getBimRequestId())
.eqIfPresent(SyncLogDO::getServiceName, reqVO.getServiceName())
.eqIfPresent(SyncLogDO::getStatus, reqVO.getStatus())
.eqIfPresent(SyncLogDO::getClientIp, reqVO.getClientIp())
.eqIfPresent(SyncLogDO::getAuthUser, reqVO.getAuthUser())
.betweenIfPresent(SyncLogDO::getRequestTime, reqVO.getRequestTime())
.orderByDesc(SyncLogDO::getId));
}
}

View File

@@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.system.enums.sync;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 同步接口日志状态枚举
*
* @author 芋道源码
*/
@AllArgsConstructor
@Getter
public enum SyncLogStatusEnum {
SUCCESS(0, "成功"),
DECRYPT_FAILED(1, "解密失败"),
SIGNATURE_VERIFY_FAILED(2, "签名验证失败"),
AUTH_FAILED(3, "认证失败"),
BUSINESS_FAILED(4, "业务处理失败"),
SYSTEM_ERROR(5, "系统异常");
/**
* 状态码
*/
private final Integer status;
/**
* 状态描述
*/
private final String description;
}

View File

@@ -1,19 +1,20 @@
package cn.iocoder.yudao.module.system.service.sync;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.org.*;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.enums.dept.DeptTypeEnum;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
/**
* 统一机构相关 Service 实现
@@ -27,6 +28,12 @@ public class OrgSyncServiceImpl implements OrgSyncService {
@Override
public OrgCreateResponseVO createOrg(OrgCreateRequestVO requestVO) {
DeptSaveReqVO bean = BeanUtils.toBean(requestVO, DeptSaveReqVO.class);
// 根据机构类型设置isCompany字段
if (requestVO.getDeptType() != null) {
bean.setIsCompany(DeptTypeEnum.isCompany(requestVO.getDeptType()));
}
LoginUser loginUser = getLoginUser();
bean.setTenantId(Optional.ofNullable(loginUser).orElse(new LoginUser()).getTenantId());
Long deptId = deptService.createDept(bean);
OrgCreateResponseVO resp = new OrgCreateResponseVO();
resp.setBimRequestId(requestVO.getBimRequestId());
@@ -80,8 +87,8 @@ public class OrgSyncServiceImpl implements OrgSyncService {
if (requestVO.getStatus() != null) {
updateReqVO.setStatus(requestVO.getStatus());
}
if (requestVO.getIsCompany() != null) {
updateReqVO.setIsCompany(requestVO.getIsCompany());
if (requestVO.getDeptType() != null) {
updateReqVO.setIsCompany(DeptTypeEnum.isCompany(requestVO.getDeptType()));
}
if (requestVO.getIsGroup() != null) {
updateReqVO.setIsGroup(requestVO.getIsGroup());

View File

@@ -0,0 +1,102 @@
package cn.iocoder.yudao.module.system.service.sync;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncLogPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sync.SyncLogDO;
/**
* 同步接口日志 Service 接口
*
* @author 芋道源码
*/
public interface SyncLogService {
/**
* 创建同步接口日志
*
* @param syncLog 同步日志信息
* @return 日志编号
*/
Long createSyncLog(SyncLogDO syncLog);
/**
* 更新同步接口日志
*
* @param syncLog 同步日志信息
*/
void updateSyncLog(SyncLogDO syncLog);
/**
* 获得同步接口日志
*
* @param id 编号
* @return 同步接口日志
*/
SyncLogDO getSyncLog(Long id);
/**
* 获得同步接口日志分页
*
* @param pageReqVO 分页查询
* @return 同步接口日志分页
*/
PageResult<SyncLogDO> getSyncLogPage(SyncLogPageReqVO pageReqVO);
/**
* 记录请求开始
*
* @param serviceName 服务名称
* @param requestUrl 请求URL
* @param clientIp 客户端IP
* @param userAgent 用户代理
* @param encryptedRequest 加密请求体
* @return 日志ID
*/
Long logRequestStart(String serviceName, String requestUrl, String clientIp,
String userAgent, String encryptedRequest);
/**
* 记录解密结果
*
* @param logId 日志ID
* @param bimRequestId 外部请求ID
* @param decryptedRequest 解密后的请求体
* @param authUser 认证用户
* @param success 解密是否成功
*/
void logDecryptResult(Long logId, String bimRequestId, String decryptedRequest,
String authUser, boolean success);
/**
* 记录签名验证结果
*
* @param logId 日志ID
* @param success 验证是否成功
*/
void logSignatureVerifyResult(Long logId, boolean success);
/**
* 记录认证结果
*
* @param logId 日志ID
* @param success 认证是否成功
*/
void logAuthResult(Long logId, boolean success);
/**
* 记录请求完成
*
* @param logId 日志ID
* @param status 最终状态
* @param errorCode 错误码
* @param errorMessage 错误信息
* @param exceptionStack 异常堆栈
* @param responseData 响应数据
* @param encryptedResponse 加密响应
* @param businessResult 业务结果
*/
void logRequestComplete(Long logId, Integer status, String errorCode, String errorMessage,
String exceptionStack, String responseData, String encryptedResponse,
String businessResult);
}

View File

@@ -0,0 +1,148 @@
package cn.iocoder.yudao.module.system.service.sync;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncLogPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sync.SyncLogDO;
import cn.iocoder.yudao.module.system.dal.mysql.sync.SyncLogMapper;
import cn.iocoder.yudao.module.system.enums.sync.SyncLogStatusEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
/**
* 同步接口日志 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
@Slf4j
public class SyncLogServiceImpl implements SyncLogService {
@Resource
private SyncLogMapper syncLogMapper;
@Override
public Long createSyncLog(SyncLogDO syncLog) {
syncLogMapper.insert(syncLog);
return syncLog.getId();
}
@Override
public void updateSyncLog(SyncLogDO syncLog) {
syncLogMapper.updateById(syncLog);
}
@Override
public SyncLogDO getSyncLog(Long id) {
return syncLogMapper.selectById(id);
}
@Override
public PageResult<SyncLogDO> getSyncLogPage(SyncLogPageReqVO pageReqVO) {
return syncLogMapper.selectPage(pageReqVO);
}
@Override
public Long logRequestStart(String serviceName, String requestUrl, String clientIp,
String userAgent, String encryptedRequest) {
SyncLogDO syncLog = new SyncLogDO();
syncLog.setServiceName(serviceName);
syncLog.setRequestMethod("POST");
syncLog.setRequestUrl(requestUrl);
syncLog.setClientIp(clientIp);
syncLog.setUserAgent(userAgent);
syncLog.setRequestTime(LocalDateTime.now());
syncLog.setEncryptedRequest(encryptedRequest);
syncLog.setStatus(SyncLogStatusEnum.SUCCESS.getStatus()); // 初始状态设为成功
syncLog.setDecryptStatus(0);
syncLog.setSignatureVerifyStatus(0);
syncLog.setAuthStatus(0);
return createSyncLog(syncLog);
}
@Override
public void logDecryptResult(Long logId, String bimRequestId, String decryptedRequest,
String authUser, boolean success) {
SyncLogDO syncLog = new SyncLogDO();
syncLog.setId(logId);
syncLog.setBimRequestId(bimRequestId);
syncLog.setDecryptedRequest(decryptedRequest);
syncLog.setAuthUser(authUser);
syncLog.setDecryptStatus(success ? 0 : 1);
if (!success) {
syncLog.setStatus(SyncLogStatusEnum.DECRYPT_FAILED.getStatus());
syncLog.setErrorCode("DECRYPT_ERROR");
syncLog.setErrorMessage("请求解密失败");
}
updateSyncLog(syncLog);
}
@Override
public void logSignatureVerifyResult(Long logId, boolean success) {
SyncLogDO syncLog = new SyncLogDO();
syncLog.setId(logId);
syncLog.setSignatureVerifyStatus(success ? 0 : 1);
if (!success) {
syncLog.setStatus(SyncLogStatusEnum.SIGNATURE_VERIFY_FAILED.getStatus());
syncLog.setErrorCode("SIGNATURE_ERROR");
syncLog.setErrorMessage("签名验证失败");
}
updateSyncLog(syncLog);
}
@Override
public void logAuthResult(Long logId, boolean success) {
SyncLogDO syncLog = new SyncLogDO();
syncLog.setId(logId);
syncLog.setAuthStatus(success ? 0 : 1);
if (!success) {
syncLog.setStatus(SyncLogStatusEnum.AUTH_FAILED.getStatus());
syncLog.setErrorCode("AUTH_ERROR");
syncLog.setErrorMessage("用户认证失败");
}
updateSyncLog(syncLog);
}
@Override
public void logRequestComplete(Long logId, Integer status, String errorCode, String errorMessage,
String exceptionStack, String responseData, String encryptedResponse,
String businessResult) {
SyncLogDO originalLog = getSyncLog(logId);
if (originalLog == null) {
log.warn("同步日志不存在logId: {}", logId);
return;
}
SyncLogDO syncLog = new SyncLogDO();
syncLog.setId(logId);
syncLog.setResponseTime(LocalDateTime.now());
// 计算耗时
if (originalLog.getRequestTime() != null) {
long duration = java.time.Duration.between(originalLog.getRequestTime(), syncLog.getResponseTime()).toMillis();
syncLog.setDuration(duration);
}
syncLog.setStatus(status);
syncLog.setErrorCode(errorCode);
syncLog.setErrorMessage(errorMessage);
syncLog.setExceptionStack(exceptionStack);
syncLog.setResponseData(responseData);
syncLog.setEncryptedResponse(encryptedResponse);
syncLog.setBusinessResult(businessResult);
updateSyncLog(syncLog);
}
}

View File

@@ -1,20 +1,21 @@
package cn.iocoder.yudao.module.system.service.sync;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.sync.vo.user.*;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.userdept.UserDeptDO;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import cn.iocoder.yudao.module.system.service.userdept.UserDeptService;
import cn.iocoder.yudao.module.system.util.sync.SyncVerifyUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.beans.PropertyDescriptor;
import java.util.*;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class UserSyncServiceImpl implements UserSyncService {
@@ -25,8 +26,11 @@ public class UserSyncServiceImpl implements UserSyncService {
@Override
public UserCreateResponseVO createUser(UserCreateRequestVO requestVO) {
TenantContextHolder.setTenantId(Objects.requireNonNull(getLoginUser()).getTenantId());
UserSaveReqVO saveReqVO = BeanUtils.toBean(requestVO, UserSaveReqVO.class);
// 转换外部性别编码为内部性别编码
if (requestVO.getSex() != null) {
saveReqVO.setSex(SyncVerifyUtil.convertExternalToInternal(requestVO.getSex()));
}
Long userId = adminUserService.createUser(saveReqVO);
UserCreateResponseVO resp = new UserCreateResponseVO();
resp.setUid(String.valueOf(userId));
@@ -91,7 +95,8 @@ public class UserSyncServiceImpl implements UserSyncService {
updateReqVO.setMobile(requestVO.getMobile());
}
if (requestVO.getSex() != null) {
updateReqVO.setSex(requestVO.getSex());
// 转换外部性别编码为内部性别编码
updateReqVO.setSex(SyncVerifyUtil.convertExternalToInternal(requestVO.getSex()));
}
if (requestVO.getAvatar() != null && !requestVO.getAvatar().isEmpty()) {
updateReqVO.setAvatar(requestVO.getAvatar());
@@ -124,6 +129,10 @@ public class UserSyncServiceImpl implements UserSyncService {
}
try {
Object value = pd.getReadMethod().invoke(user);
// 如果是性别字段,需要转换为外部编码
if ("sex".equals(name) && value instanceof Integer) {
value = SyncVerifyUtil.convertInternalToExternal((Integer) value);
}
account.put(name, value);
} catch (Exception ignore) {}
}

View File

@@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
@@ -44,6 +45,7 @@ import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;
@@ -101,6 +103,11 @@ public class AdminUserServiceImpl implements AdminUserService {
// 2.1 插入用户
AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class);
user.setStatus(CommonStatusEnum.ENABLE.getStatus());
// 如果 tenantId 为空,则从上下文中获取
if (user.getTenantId() == null) {
LoginUser loginUser = getLoginUser();
user.setTenantId(Optional.ofNullable(loginUser).orElse(new LoginUser()).getTenantId());
}
user.setPassword(encodePassword(createReqVO.getPassword()));
userMapper.insert(user);
// 2.2 插入关联部门

View File

@@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.system.util.sync;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.crypto.symmetric.DES;
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
@@ -17,6 +17,7 @@ import java.util.TreeMap;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SYNC_DECRYPT_TYPE;
/**
* @author chenbowen
@@ -31,7 +32,7 @@ public class SyncVerifyUtil {
byte[] result = cipher.doFinal(Base64.getDecoder().decode(ciphertext.getBytes()));
return new String(result, StandardCharsets.UTF_8);
} catch (Exception e) {
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
throw exception(SYNC_DECRYPT_TYPE);
}
} else if ("DES".equalsIgnoreCase(type)) {
byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
@@ -42,7 +43,7 @@ public class SyncVerifyUtil {
byte[] encryptedBytes = Base64.getDecoder().decode(ciphertext);
return new String(des.decrypt(encryptedBytes), StandardCharsets.UTF_8);
} else {
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
throw exception(SYNC_DECRYPT_TYPE);
}
}
@@ -122,4 +123,42 @@ public class SyncVerifyUtil {
}
return provided.equalsIgnoreCase(computed);
}
/**
* e 办性别编码转换为内部性别编码
* 外部:女=0男=1
* 内部:未知=0男=1女=2
*/
public static Integer convertExternalToInternal(Integer externalSex) {
if (externalSex == null) {
return null;
}
switch (externalSex) {
case 0: // 外部:女
return SexEnum.FEMALE.getSex(); // 内部:女=2
case 1: // 外部:男
return SexEnum.MALE.getSex(); // 内部:男=1
default:
return SexEnum.UNKNOWN.getSex(); // 内部:未知=0
}
}
/**
* 内部性别编码转换为外部性别编码
* 内部:未知=0男=1女=2
* 外部:女=0男=1
*/
public static Integer convertInternalToExternal(Integer internalSex) {
if (internalSex == null) {
return null;
}
if (SexEnum.MALE.getSex().equals(internalSex)) { // 内部:男=1
return 1; // 外部:男=1
} else if (SexEnum.FEMALE.getSex().equals(internalSex)) { // 内部:女=2
return 0; // 外部:女=0
} else {
// 内部:未知=0默认转换为外部女=0
return 0;
}
}
}

View File

@@ -187,6 +187,7 @@ yudao:
- system_seq
- system_seq_dtl
- system_seq_rcd
- system_sync_log
ignore-caches:
- user_role_ids
- permission_menu_ids

View File

@@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.system.util.sync;
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
/**
* {@link SyncVerifyUtil} 的单元测试类
*
* @author chenbowen
*/
public class SyncVerifyUtilTest {
@Test
public void testConvertExternalToInternal() {
// 外部女=0 -> 内部女=2
assertEquals(SexEnum.FEMALE.getSex(), SyncVerifyUtil.convertExternalToInternal(0));
// 外部男=1 -> 内部男=1
assertEquals(SexEnum.MALE.getSex(), SyncVerifyUtil.convertExternalToInternal(1));
// 其他值 -> 内部未知=0
assertEquals(SexEnum.UNKNOWN.getSex(), SyncVerifyUtil.convertExternalToInternal(2));
assertEquals(SexEnum.UNKNOWN.getSex(), SyncVerifyUtil.convertExternalToInternal(99));
// null值处理
assertNull(SyncVerifyUtil.convertExternalToInternal(null));
}
@Test
public void testConvertInternalToExternal() {
// 内部男=1 -> 外部男=1
assertEquals(1, SyncVerifyUtil.convertInternalToExternal(SexEnum.MALE.getSex()));
// 内部女=2 -> 外部女=0
assertEquals(0, SyncVerifyUtil.convertInternalToExternal(SexEnum.FEMALE.getSex()));
// 内部未知=0 -> 外部女=0
assertEquals(0, SyncVerifyUtil.convertInternalToExternal(SexEnum.UNKNOWN.getSex()));
// null值处理
assertNull(SyncVerifyUtil.convertInternalToExternal(null));
}
}

View File

@@ -48,40 +48,20 @@ spring:
primary: master
datasource:
master:
url: jdbc:mysql://172.16.46.247:4787/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
# url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例
# url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
# url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例
# url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例
# url: jdbc:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例
# url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例
username: jygk-test
password: Zgty@0527
# username: sa # SQL Server 连接的示例
# password: Yudao@2024 # SQL Server 连接的示例
# username: SYSDBA # DM 连接的示例
# password: SYSDBA001 # DM 连接的示例
# username: root # OpenGauss 连接的示例
# password: Yudao@2024 # OpenGauss 连接的示例
slave: # 模拟从库,可根据自己需要修改
url: jdbc:dm://localhost:5233?schema=RUOYI-VUE-PRO
username: SYSDBA
password: P@ssword25
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
lazy: true # 开启懒加载,保证启动速度
url: jdbc:mysql://172.16.46.247:4787/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
username: jygk-test
password: Zgty@0527
# tdengine: # IoT 数据库(需要 IoT 物联网再开启噢!)
# url: jdbc:TAOS-RS://127.0.0.1:6041/ruoyi_vue_pro
# driver-class-name: com.taosdata.jdbc.rs.RestfulDriver
# username: root
# password: taosdata
# druid:
# validation-query: SELECT SERVER_STATUS() # TDengine 数据源的有效性检查 SQL
url: jdbc:dm://localhost:5233?schema=RUOYI-VUE-PRO
username: SYSDBA
password: P@ssword25
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
data:
redis:
host: 172.16.46.63 # 地址
port: 30379 # 端口
host: localhost # 地址
port: 6379 # 端口
database: 0 # 数据库索引
# password: dev # 密码,建议生产环境开启
@@ -91,13 +71,13 @@ xxl:
job:
enabled: false # 是否开启调度中心,默认为 true 开启
admin:
addresses: http://172.16.46.63:30082/xxl-job-admin # 调度中心部署跟地址
addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址
--- #################### 消息队列相关 ####################
# rocketmq 配置项,对应 RocketMQProperties 配置类
rocketmq:
name-server: 172.16.46.63:30876 # RocketMQ Namesrv
name-server: localhost:9876 # RocketMQ Namesrv
spring:
# RabbitMQ 配置项,对应 RabbitProperties 配置类
@@ -221,10 +201,6 @@ yudao:
wxa-subscribe-message:
miniprogram-state: developer # 跳转小程序类型:开发版为 “developer”体验版为 “trial”为正式版为 “formal”
tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
AES:
key: "0123456789abcdef0123456789abcdef"
verify-code: 666666
justauth:
enabled: true

View File

@@ -268,6 +268,7 @@ yudao:
security:
permit-all_urls:
- /admin-api/mp/open/** # 微信公众号开放平台,微信回调接口,不需要登录
- /admin-api/infra/onlyoffice/**
websocket:
enable: true # websocket的开关
path: /infra/ws # 路径
@@ -304,6 +305,12 @@ yudao:
- /admin-api/system/user/profile/**
- /admin-api/system/auth/**
ignore-tables:
- system_seq
- system_seq_dtl
- system_seq_rcd
- system_sync_log
- infra_doc_file
- infra_doc_file_version
ignore-caches:
- user_role_ids
- permission_menu_ids