--- name: ADR-007 description: 查询不同类型ORG登录历史及自动登录功能 --- # 查询不同类型ORG登录历史及自动登录功能 ## 元数据 (Metadata) - **决策编号**: ADR-007 - **决策标题**: 查询不同类型ORG登录历史及自动登录功能 - **状态**: Accepted - **日期**: 2026-01-16 - **最后更新**: 2026-01-18 - **决策者**: SSOT Architect - **相关需求**: [REQ-007](../../requirements/REQ-007.md) ## 背景 (Context) ### 问题描述 当前系统支持通过 `DataISfLoginController` 进行 Salesforce 登录操作,包括源ORG和目标ORG的登录。系统已经实现了基本的登录、登出、获取当前登录信息和自动登录功能。但是,当前的 `getCurrentLoginInfo` 接口只能获取当前登录信息,无法查询历史登录记录。而 `autoLogin` 接口虽然支持自动登录,但只能使用最新的登录历史记录。 用户需要: 1. 查询不同类型ORG(如Source、Target、Sandbox、Production等)的成功登录历史记录 2. 基于指定的登录历史记录自动登录到对应的ORG环境 ### 当前状态 - `DataISfLoginController` 已存在,包含以下接口: - `POST /salesforce/login/doLogin` - 执行登录操作 - `POST /salesforce/login/logout` - 执行登出操作 - `GET /salesforce/login/current` - 获取当前登录信息 - `POST /salesforce/login/autoLogin` - 自动登录(使用最新历史) - `IDataiSfLoginHistoryService` 已存在,包含查询登录历史的方法 - `DataiSfLoginHistory` 实体已存在,包含登录历史的所有字段 ### 问题影响 1. 开发人员和测试人员无法快速查询特定类型的登录历史 2. 无法基于指定的历史记录自动登录到不同的ORG环境 3. 需要在多个环境间切换时,需要重复输入登录凭证,效率较低 ### 约束条件 - 必须保持与现有代码风格的一致性 - 必须复用现有的 Service 层代码 - 必须确保接口的安全性和性能 - 必须支持多种ORG类型(Source、Target、Sandbox、Production等) ## 决策 (Decision) ### 决策内容 采用方案 A:在现有的 `DataISfLoginController` 和 `DataiSfLoginHistoryController` 中新增三个接口: 1. `GET /salesforce/login/history/success/{orgType}` - 查询不同类型org成功登录历史 2. `POST /salesforce/login/autoLoginByHistory` - 根据对应登录成功历史登录不同的org 3. `GET /auth/history/latest-success-grouped` - 查询所有登录成功历史,按username和instanceUrl分组,每组返回最新一条数据 ### 技术方案 #### 接口1: 查询不同类型org成功登录历史 **接口路径**: `GET /salesforce/login/history/success/{orgType}` **功能描述**: 查询指定类型的成功登录历史记录 **实现方式**: ```java @Operation(summary = "查询不同类型ORG成功登录历史") @GetMapping("/history/success/{orgType}") public AjaxResult getSuccessLoginHistoryByOrgType(@PathVariable String orgType) { logger.info("接收到查询登录历史请求,ORG类型: {}", orgType); try { List historyList = loginHistoryService.selectSuccessLoginHistoryByOrgType(orgType); return AjaxResult.success("查询成功", historyList); } catch (Exception e) { logger.error("查询登录历史请求处理失败: {}", e.getMessage(), e); return AjaxResult.error("查询失败: " + e.getMessage()); } } ``` **Service 层方法**: ```java List selectSuccessLoginHistoryByOrgType(String orgType); ``` #### 接口2: 根据对应登录成功历史登录不同的org **接口路径**: `POST /salesforce/login/autoLoginByHistory` **功能描述**: 根据指定的登录历史记录自动登录到对应ORG **实现方式**: ```java @Operation(summary = "根据登录历史自动登录") @PostMapping("/autoLoginByHistory") public AjaxResult autoLoginByHistory(@RequestBody Map request) { Long historyId = request.get("historyId"); logger.info("接收到根据历史自动登录请求,历史ID: {}", historyId); try { DataiSfLoginHistory loginHistory = loginHistoryService.selectDataiSfLoginHistoryById(historyId); if (loginHistory == null) { logger.warn("未找到ID为 {} 的登录历史记录", historyId); return AjaxResult.error("未找到登录历史记录"); } SalesforceLoginResult result = salesforceLoginService.autoLogin(historyHistory.getId()); if (result.isSuccess()) { logger.info("自动登录成功,用户ID: {}, 组织ID: {}, ORG类型: {}", result.getUserId(), result.getOrganizationId(), result.getOrgType()); return AjaxResult.success("自动登录成功", result); } else { logger.warn("自动登录失败,错误码: {}, 错误信息: {}", result.getErrorCode(), result.getErrorMessage()); return AjaxResult.error(result.getErrorCode(), result.getErrorMessage()); } } catch (Exception e) { logger.error("自动登录请求处理失败: {}", e.getMessage(), e); return AjaxResult.error("自动登录失败: " + e.getMessage()); } } ``` **Service 层方法**: ```java DataiSfLoginHistory selectDataiSfLoginHistoryById(Long id); ``` #### 接口3: 查询所有登录成功历史分组数据 **接口路径**: `GET /auth/history/latest-success-grouped` **功能描述**: 查询所有登录成功的历史记录,按username和instanceUrl分组,每组返回最新一条数据 **实现方式**: ```java @Operation(summary = "查询所有登录成功的历史记录,按username和instanceUrl分组,每组返回最新一条") @PreAuthorize("@ss.hasPermi('auth:history:list')") @GetMapping("/latest-success-grouped") public TableDataInfo listLatestSuccessGrouped() { List list = dataiSfLoginHistoryService.selectLatestSuccessLoginHistoryGroupedByUserAndInstance(); List voList = list.stream().map(DataiSfLoginHistoryVo::objToVo).collect(Collectors.toList()); return getDataTableByPage(voList, voList.size()); } ``` **Service 层方法**: ```java List selectLatestSuccessLoginHistoryGroupedByUserAndInstance(); ``` **SQL 实现**: ```sql select * from ( select , ROW_NUMBER() OVER (PARTITION BY dslh.username, dslh.instance_url ORDER BY dslh.create_time DESC) as rn from datai_sf_login_history dslh where dslh.login_status = 'success' ) t where t.rn = 1 ``` ### 实施计划 1. 在 `IDataiSfLoginHistoryService` 中添加新方法: - `selectSuccessLoginHistoryByOrgType(String orgType)` - `selectDataiSfLoginHistoryById(Long id)` - `selectLatestSuccessLoginHistoryGroupedByUserAndInstance()` 2. 在 `DataiSfLoginHistoryServiceImpl` 中实现新方法 3. 在 `DataISfLoginController` 中添加两个新接口: - `GET /salesforce/login/history/success/{orgType}` - `POST /salesforce/login/autoLoginByHistory` 4. 在 `DataiSfLoginHistoryController` 中添加新接口: - `GET /auth/history/latest-success-grouped` 5. 在 `DataiSfLoginHistoryMapper.xml` 中添加新的 SQL 查询语句 6. 编写单元测试和集成测试 7. 更新 API 文档 ### 回滚策略 如果决策失败,可以: 1. 删除新增的两个接口 2. 删除 Service 层新增的方法 3. 回退到之前的代码版本 ## 后果 (Consequences) ### 正面影响 1. **提高效率**: 用户可以快速查询登录历史,无需手动记录 2. **多环境支持**: 支持多种ORG类型的快速切换 3. **代码一致性**: 保持与现有代码风格的一致性 4. **开发成本低**: 复用现有代码,开发成本较低 ### 负面影响 1. **Controller 膨胀**: Controller 可能会变得过于庞大 2. **维护复杂度**: 需要确保新增接口与现有接口的兼容性 ### 风险评估 | 风险 | 概率 | 影响 | 缓解措施 | |------|------|------|----------| | 接口性能问题 | 低 | 中 | 添加索引,优化查询语句 | | 安全性问题 | 低 | 高 | 确保登录历史中的敏感信息加密存储 | | 兼容性问题 | 低 | 中 | 充分测试,确保与现有功能兼容 | | 数据库查询性能 | 中 | 中 | 添加 orgType 字段索引 | ### 权衡分析 采用方案 A 的主要权衡是: - **优点**: 开发成本低,代码一致性好,快速交付 - **缺点**: Controller 可能会变得过于庞大 - **结论**: 考虑到开发成本和代码一致性,以及现有架构的支持,选择方案 A 是合理的 ## 合规性验证 (Compliance) ### 验证标准 1. 两个新接口已添加到 `DataISfLoginController` 2. Service 层新方法已实现 3. 接口功能符合需求文档中的验收标准 4. 接口性能满足非功能需求(响应时间 < 500ms) 5. 接口安全性得到保证(敏感信息加密) 6. API 文档已更新 ### 验证方法 1. 单元测试:测试 Service 层新方法 2. 集成测试:测试 Controller 层新接口 3. 性能测试:测试接口响应时间 4. 安全测试:测试敏感信息加密 5. 文档审查:检查 API 文档是否完整 ### 验证结果 待实施后填写 ### 成功指标 | 指标 | 目标值 | 实际值 | 状态 | |------|--------|--------|------| | 接口数量 | 2 | 待验证 | 待验证 | | 接口响应时间 | < 500ms | 待验证 | 待验证 | | 接口可用性 | > 99.9% | 待验证 | 待验证 | | 测试覆盖率 | > 80% | 待验证 | 待验证 | ## 相关文档 (Related Documents) - [需求文档](../../requirements/REQ-007.md) - [设计文档](../../design/0001-salesforce-cdc-realtime-sync.md) - [其他 ADR](./0001-salesforce-cdc-sync.md) - [DataISfLoginController](../../api-docs/auth/DataISfLoginController/) - Salesforce登录控制器接口文档 ## 变更历史 (Change History) | 日期 | 版本 | 变更内容 | 变更人 | |------|------|----------|--------| | 2026-01-16 | 1.0.0 | 初始版本 | SSOT Architect |