401 lines
16 KiB
Markdown
401 lines
16 KiB
Markdown
# Salesforce 多系统配置设计
|
||
|
||
## 元数据
|
||
- 设计编号:2026-01-21-003-01
|
||
- 需求编号:2026-01-21-003-01
|
||
- 创建时间:2026-01-21
|
||
- 创建人:SSOT 架构师
|
||
- 状态:待开始
|
||
- 优先级:高
|
||
|
||
## 设计概述
|
||
本设计文档描述了 Salesforce 多系统配置功能的技术实现方案。该功能支持配置多个不同类型的 Salesforce 系统,支持用户自定义系统类型,支持区分源 org 和目标 org(支持同一系统既是源 org 又是目标 org),支持配置系统名称、自定义类型、登录方式等,支持启用/停用系统,系统配置变更无需审批流程,系统配置无权限限制,密码、安全令牌等敏感信息使用 EncryptUtils 加密存储。
|
||
|
||
## 设计目标
|
||
1. **多系统配置**:支持配置多个不同类型的 Salesforce 系统
|
||
2. **用户自定义类型**:支持用户自定义系统类型(不限于 production/sandbox/developer)
|
||
3. **源目标区分**:支持区分源 org 和目标 org,支持同一系统既是源 org 又是目标 org
|
||
4. **系统管理**:支持配置系统名称、自定义类型、登录方式等
|
||
5. **状态管理**:支持启用/停用系统
|
||
6. **无审批流程**:系统配置变更无需审批流程
|
||
7. **无权限限制**:系统配置无权限限制
|
||
8. **敏感信息加密**:密码、安全令牌等敏感信息使用 EncryptUtils 加密存储
|
||
|
||
## 架构设计
|
||
|
||
### 系统架构
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Controller 层 │
|
||
│ DataiSfSystemConfigController │
|
||
│ - 添加系统配置 │
|
||
│ - 编辑系统配置 │
|
||
│ - 删除系统配置 │
|
||
│ - 查询系统配置列表 │
|
||
│ - 查询系统配置详情 │
|
||
│ - 启用/停用系统 │
|
||
│ - 查询源 org 列表 │
|
||
│ - 查询目标 org 列表 │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Service 层 │
|
||
│ IDataiSfSystemConfigService │
|
||
│ DataiSfSystemConfigServiceImpl │
|
||
│ - 系统配置 CRUD 操作 │
|
||
│ - 敏感信息加密/解密 │
|
||
│ - 系统名称唯一性校验 │
|
||
│ - 源 org / 目标 org 筛选 │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Mapper 层 │
|
||
│ DataiSfSystemConfigMapper │
|
||
│ - 数据库 CRUD 操作 │
|
||
│ - 分页查询 │
|
||
│ - 条件筛选查询 │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 数据库层 │
|
||
│ datai_sf_system_config (Salesforce 系统配置表) │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 模块设计
|
||
```
|
||
datai-salesforce-auth
|
||
├─ controller
|
||
│ └─ DataiSfSystemConfigController (系统配置控制器)
|
||
├─ service
|
||
│ ├─ IDataiSfSystemConfigService (系统配置服务接口)
|
||
│ └─ impl
|
||
│ └─ DataiSfSystemConfigServiceImpl (系统配置服务实现)
|
||
├─ mapper
|
||
│ └─ DataiSfSystemConfigMapper (系统配置 Mapper)
|
||
├─ model
|
||
│ ├─ domain
|
||
│ │ └─ DataiSfSystemConfig (系统配置实体)
|
||
│ ├─ dto
|
||
│ │ └─ DataiSfSystemConfigDto (系统配置 DTO)
|
||
│ └─ vo
|
||
│ └─ DataiSfSystemConfigVo (系统配置 VO)
|
||
└─ resources
|
||
└─ mapper
|
||
└─ auth
|
||
└─ DataiSfSystemConfigMapper.xml (MyBatis XML)
|
||
```
|
||
|
||
## 数据库设计
|
||
|
||
### 表结构
|
||
|
||
#### datai_sf_system_config(Salesforce 系统配置表)
|
||
```sql
|
||
CREATE TABLE `datai_sf_system_config` (
|
||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`system_name` VARCHAR(100) NOT NULL COMMENT '系统名称(唯一)',
|
||
`system_type` VARCHAR(50) NOT NULL COMMENT '系统类型(用户自定义)',
|
||
`org_type` CHAR(1) NOT NULL COMMENT '组织类型(S=源 org T=目标 org,可同时选中)',
|
||
`login_type` VARCHAR(20) NOT NULL COMMENT '登录类型(oauth2/session_id/cli)',
|
||
`client_id` VARCHAR(255) NULL COMMENT 'OAuth 客户端 ID',
|
||
`client_secret` VARCHAR(500) NULL COMMENT 'OAuth 客户端密钥(使用 EncryptUtils 加密存储)',
|
||
`username` VARCHAR(100) NULL COMMENT '用户名',
|
||
`password` VARCHAR(500) NULL COMMENT '密码(使用 EncryptUtils 加密存储)',
|
||
`security_token` VARCHAR(500) NULL COMMENT '安全令牌(使用 EncryptUtils 加密存储)',
|
||
`session_id` VARCHAR(500) NULL COMMENT 'Session ID(Access Token,由 Salesforce 登录后返回)',
|
||
`server_url` VARCHAR(500) NULL COMMENT '服务器 URL(Instance URL)',
|
||
`access_token` VARCHAR(500) NULL COMMENT '访问令牌(Session ID)',
|
||
`refresh_token` VARCHAR(500) NULL COMMENT '刷新令牌',
|
||
`token_expires_at` DATETIME NULL COMMENT '令牌过期时间',
|
||
`sf_user_id` VARCHAR(100) NULL COMMENT 'Salesforce 用户 ID(用于缓存键)',
|
||
`user_id` VARCHAR(100) NULL COMMENT '用户 ID',
|
||
`org_id` VARCHAR(100) NULL COMMENT '组织 ID',
|
||
`org_name` VARCHAR(200) NULL COMMENT '组织名称',
|
||
`status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '状态(0正常 1停用)',
|
||
`sort_order` INT NULL COMMENT '排序',
|
||
`create_by` VARCHAR(64) NOT NULL COMMENT '创建者',
|
||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`update_by` VARCHAR(64) NOT NULL COMMENT '更新者',
|
||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
PRIMARY KEY (`id`) USING BTREE COMMENT '主键索引',
|
||
UNIQUE INDEX `uk_system_name` (`system_name`) USING BTREE COMMENT '唯一约束',
|
||
INDEX `idx_system_type` (`system_type`) USING BTREE COMMENT '普通索引',
|
||
INDEX `idx_org_type` (`org_type`) USING BTREE COMMENT '普通索引',
|
||
INDEX `idx_login_type` (`login_type`) USING BTREE COMMENT '普通索引',
|
||
INDEX `idx_status` (`status`) USING BTREE COMMENT '普通索引'
|
||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'Salesforce 系统配置表' ROW_FORMAT = DYNAMIC;
|
||
```
|
||
|
||
### 索引设计
|
||
- **主键索引**:`id` - 主键索引
|
||
- **唯一索引**:`uk_system_name` - 系统名称唯一约束
|
||
- **普通索引**:
|
||
- `idx_system_type` - 系统类型索引
|
||
- `idx_org_type` - 组织类型索引
|
||
- `idx_login_type` - 登录类型索引
|
||
- `idx_status` - 状态索引
|
||
|
||
## 接口设计
|
||
|
||
### Controller 层接口
|
||
|
||
#### DataiSfSystemConfigController
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/api/salesforce/system/config")
|
||
@Api(tags = "Salesforce 系统配置管理")
|
||
public class DataiSfSystemConfigController {
|
||
|
||
/**
|
||
* 添加系统配置
|
||
*/
|
||
@PostMapping
|
||
public AjaxResult add(@RequestBody DataiSfSystemConfigDto config);
|
||
|
||
/**
|
||
* 编辑系统配置
|
||
*/
|
||
@PutMapping("/{id}")
|
||
public AjaxResult edit(@PathVariable Long id, @RequestBody DataiSfSystemConfigDto config);
|
||
|
||
/**
|
||
* 删除系统配置
|
||
*/
|
||
@DeleteMapping("/{id}")
|
||
public AjaxResult remove(@PathVariable Long id);
|
||
|
||
/**
|
||
* 查询系统配置列表
|
||
*/
|
||
@GetMapping("/list")
|
||
public TableDataInfo list(DataiSfSystemConfigDto config);
|
||
|
||
/**
|
||
* 查询系统配置详情
|
||
*/
|
||
@GetMapping("/{id}")
|
||
public AjaxResult getInfo(@PathVariable Long id);
|
||
|
||
/**
|
||
* 启用系统
|
||
*/
|
||
@PutMapping("/{id}/enable")
|
||
public AjaxResult enable(@PathVariable Long id);
|
||
|
||
/**
|
||
* 停用系统
|
||
*/
|
||
@PutMapping("/{id}/disable")
|
||
public AjaxResult disable(@PathVariable Long id);
|
||
|
||
/**
|
||
* 查询源 org 列表
|
||
*/
|
||
@GetMapping("/source")
|
||
public TableDataInfo listSource();
|
||
|
||
/**
|
||
* 查询目标 org 列表
|
||
*/
|
||
@GetMapping("/target")
|
||
public TableDataInfo listTarget();
|
||
}
|
||
```
|
||
|
||
### Service 层接口
|
||
|
||
#### IDataiSfSystemConfigService
|
||
```java
|
||
public interface IDataiSfSystemConfigService {
|
||
|
||
/**
|
||
* 查询系统配置
|
||
*/
|
||
DataiSfSystemConfig selectDataiSfSystemConfigById(Long id);
|
||
|
||
/**
|
||
* 查询系统配置列表
|
||
*/
|
||
List<DataiSfSystemConfig> selectDataiSfSystemConfigList(DataiSfSystemConfig config);
|
||
|
||
/**
|
||
* 新增系统配置
|
||
*/
|
||
int insertDataiSfSystemConfig(DataiSfSystemConfig config);
|
||
|
||
/**
|
||
* 修改系统配置
|
||
*/
|
||
int updateDataiSfSystemConfig(DataiSfSystemConfig config);
|
||
|
||
/**
|
||
* 批量删除系统配置
|
||
*/
|
||
int deleteDataiSfSystemConfigByIds(Long[] ids);
|
||
|
||
/**
|
||
* 删除系统配置
|
||
*/
|
||
int deleteDataiSfSystemConfigById(Long id);
|
||
|
||
/**
|
||
* 校验系统名称是否唯一
|
||
*/
|
||
boolean checkSystemNameUnique(DataiSfSystemConfig config);
|
||
|
||
/**
|
||
* 查询源 org 列表
|
||
*/
|
||
List<DataiSfSystemConfig> selectSourceOrgList();
|
||
|
||
/**
|
||
* 查询目标 org 列表
|
||
*/
|
||
List<DataiSfSystemConfig> selectTargetOrgList();
|
||
}
|
||
```
|
||
|
||
## 核心逻辑设计
|
||
|
||
### 敏感信息加密/解密
|
||
```java
|
||
public class DataiSfSystemConfigServiceImpl implements IDataiSfSystemConfigService {
|
||
|
||
@Autowired
|
||
private EncryptUtils encryptUtils;
|
||
|
||
@Override
|
||
public int insertDataiSfSystemConfig(DataiSfSystemConfig config) {
|
||
encryptSensitiveFields(config);
|
||
return dataiSfSystemConfigMapper.insertDataiSfSystemConfig(config);
|
||
}
|
||
|
||
@Override
|
||
public int updateDataiSfSystemConfig(DataiSfSystemConfig config) {
|
||
encryptSensitiveFields(config);
|
||
return dataiSfSystemConfigMapper.updateDataiSfSystemConfig(config);
|
||
}
|
||
|
||
@Override
|
||
public DataiSfSystemConfig selectDataiSfSystemConfigById(Long id) {
|
||
DataiSfSystemConfig config = dataiSfSystemConfigMapper.selectDataiSfSystemConfigById(id);
|
||
if (config != null) {
|
||
decryptSensitiveFields(config);
|
||
}
|
||
return config;
|
||
}
|
||
|
||
private void encryptSensitiveFields(DataiSfSystemConfig config) {
|
||
if (StringUtils.isNotEmpty(config.getClientSecret())) {
|
||
config.setClientSecret(EncryptUtils.encrypt(config.getClientSecret()));
|
||
}
|
||
if (StringUtils.isNotEmpty(config.getPassword())) {
|
||
config.setPassword(EncryptUtils.encrypt(config.getPassword()));
|
||
}
|
||
if (StringUtils.isNotEmpty(config.getSecurityToken())) {
|
||
config.setSecurityToken(EncryptUtils.encrypt(config.getSecurityToken()));
|
||
}
|
||
}
|
||
|
||
private void decryptSensitiveFields(DataiSfSystemConfig config) {
|
||
if (StringUtils.isNotEmpty(config.getClientSecret())) {
|
||
config.setClientSecret(EncryptUtils.decrypt(config.getClientSecret()));
|
||
}
|
||
if (StringUtils.isNotEmpty(config.getPassword())) {
|
||
config.setPassword(EncryptUtils.decrypt(config.getPassword()));
|
||
}
|
||
if (StringUtils.isNotEmpty(config.getSecurityToken())) {
|
||
config.setSecurityToken(EncryptUtils.decrypt(config.getSecurityToken()));
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 系统名称唯一性校验
|
||
```java
|
||
@Override
|
||
public boolean checkSystemNameUnique(DataiSfSystemConfig config) {
|
||
Long configId = StringUtils.isNull(config.getId()) ? -1L : config.getId();
|
||
DataiSfSystemConfig info = dataiSfSystemConfigMapper.selectDataiSfSystemConfigBySystemName(config.getSystemName());
|
||
if (StringUtils.isNotNull(info) && !info.getId().equals(configId)) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
```
|
||
|
||
### 源 org / 目标 org 筛选
|
||
```java
|
||
@Override
|
||
public List<DataiSfSystemConfig> selectSourceOrgList() {
|
||
DataiSfSystemConfig query = new DataiSfSystemConfig();
|
||
query.setOrgType("S");
|
||
query.setStatus("0");
|
||
List<DataiSfSystemConfig> list = dataiSfSystemConfigMapper.selectDataiSfSystemConfigList(query);
|
||
list.forEach(this::decryptSensitiveFields);
|
||
return list;
|
||
}
|
||
|
||
@Override
|
||
public List<DataiSfSystemConfig> selectTargetOrgList() {
|
||
DataiSfSystemConfig query = new DataiSfSystemConfig();
|
||
query.setOrgType("T");
|
||
query.setStatus("0");
|
||
List<DataiSfSystemConfig> list = dataiSfSystemConfigMapper.selectDataiSfSystemConfigList(query);
|
||
list.forEach(this::decryptSensitiveFields);
|
||
return list;
|
||
}
|
||
```
|
||
|
||
## 业务规则设计
|
||
|
||
1. **系统名称唯一性**:系统名称(system_name)必须唯一
|
||
2. **用户自定义类型**:系统类型(system_type)由用户自定义,不限制为固定值
|
||
3. **源目标区分**:每个系统可以标记为源 org 或目标 org,支持同一系统既是源 org 又是目标 org
|
||
4. **敏感信息加密**:密码、安全令牌等敏感信息必须使用 EncryptUtils 加密存储
|
||
5. **无审批流程**:系统配置变更无需审批流程
|
||
6. **无权限限制**:系统配置无权限限制
|
||
7. **停用系统限制**:停用的系统不能用于登录
|
||
|
||
## 性能设计
|
||
|
||
1. **索引优化**:为系统名称、系统类型、org 类型、登录类型、状态等字段创建索引
|
||
2. **分页查询**:系统配置列表支持分页查询,避免一次性加载大量数据
|
||
3. **缓存策略**:系统配置数据可以缓存到 Redis,减少数据库查询次数
|
||
|
||
## 安全设计
|
||
|
||
1. **敏感信息加密**:密码、安全令牌等敏感信息使用 EncryptUtils 加密存储
|
||
2. **数据传输安全**:使用 HTTPS 协议传输数据
|
||
3. **SQL 注入防护**:使用 MyBatis 的参数化查询,防止 SQL 注入
|
||
4. **XSS 防护**:对用户输入进行 XSS 过滤
|
||
|
||
## 测试设计
|
||
|
||
### 单元测试
|
||
- 测试系统配置的 CRUD 操作
|
||
- 测试敏感信息的加密/解密
|
||
- 测试系统名称唯一性校验
|
||
- 测试源 org / 目标 org 筛选
|
||
|
||
### 集成测试
|
||
- 测试系统配置的完整流程
|
||
- 测试与登录功能的集成
|
||
- 测试与缓存功能的集成
|
||
|
||
## 依赖关系
|
||
- 依赖 `datai-common` 模块的 `EncryptUtils` 工具类
|
||
- 依赖 `datai-system` 模块的基础功能
|
||
- 依赖 `datai-salesforce-common` 模块的 Salesforce API 封装
|
||
|
||
## 后续扩展
|
||
- 支持系统配置的导入/导出功能
|
||
- 支持系统配置的批量操作
|
||
- 支持系统配置的版本管理
|
||
- 支持系统配置的审批流程(可选)
|
||
- 支持系统配置的权限管理(可选)
|