diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java index d9d8a9af..b0e86ab7 100644 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java @@ -12,6 +12,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.cloud.openfeign.FeignClientFactory; import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.jdbc.Sql; @@ -31,6 +32,9 @@ public class BaseDbUnitTest { @MockBean private SequenceCommonApi sequenceCommonApi; + @MockBean + private FeignClientFactory feignClientFactory; + @Import({ // DB 配置类 YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类 diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseRedisUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseRedisUnitTest.java index 7597b56d..7e62797d 100644 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseRedisUnitTest.java +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseRedisUnitTest.java @@ -8,6 +8,7 @@ import org.redisson.spring.starter.RedissonAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.cloud.openfeign.FeignClientFactory; import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; @@ -25,6 +26,9 @@ public class BaseRedisUnitTest { @MockBean private SequenceCommonApi sequenceCommonApi; + @MockBean + private FeignClientFactory feignClientFactory; + @Import({ // Redis 配置类 RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java index 6ba459fe..1cccfcbd 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java @@ -23,26 +23,18 @@ public class BannerApplicationRunner implements ApplicationRunner { "项目启动成功!\n\t" + "接口文档: \t{} \n\t" + "开发文档: \t{} \n\t" + - "视频教程: \t{} \n" + "----------------------------------------------------------", "http://172.16.46.63:30888/api-doc/", - "http://172.16.46.63:30888", - "https://t.zsxq.com/02Yf6M7Qn"); + "http://172.16.46.63:30888"); // 数据报表 System.out.println("[报表模块 yudao-module-report 教程][参考 http://172.16.46.63:30888/report/ 开启]"); // 工作流 System.out.println("[工作流模块 yudao-module-bpm 教程][参考 http://172.16.46.63:30888/bpm/ 开启]"); - // 商城系统 - System.out.println("[商城系统 yudao-module-mall 教程][参考 http://172.16.46.63:30888/mall/build/ 开启]"); - // ERP 系统 - System.out.println("[ERP 系统 yudao-module-erp - 教程][参考 http://172.16.46.63:30888/erp/build/ 开启]"); - // CRM 系统 - System.out.println("[CRM 系统 yudao-module-crm - 教程][参考 http://172.16.46.63:30888/crm/build/ 开启]"); + // 微信公众号 System.out.println("[微信公众号 yudao-module-mp 教程][参考 http://172.16.46.63:30888/mp/build/ 开启]"); - // 支付平台 - System.out.println("[支付系统 yudao-module-pay - 教程][参考 http://172.16.46.63:30888/pay/build/ 开启]"); + // AI 大模型 System.out.println("[AI 大模型 yudao-module-ai - 教程][参考 http://172.16.46.63:30888/ai/build/ 开启]"); }); diff --git a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/util/BannerApplicationRunner.java b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/util/BannerApplicationRunner.java index 32953dbb..8b2e8104 100644 --- a/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/util/BannerApplicationRunner.java +++ b/yudao-gateway/src/main/java/cn/iocoder/yudao/gateway/util/BannerApplicationRunner.java @@ -25,26 +25,18 @@ public class BannerApplicationRunner implements ApplicationRunner { "项目启动成功!\n\t" + "接口文档: \t{} \n\t" + "开发文档: \t{} \n\t" + - "视频教程: \t{} \n" + "----------------------------------------------------------", "http://172.16.46.63:30888/api-doc/", - "http://172.16.46.63:30888", - "https://t.zsxq.com/02Yf6M7Qn"); + "http://172.16.46.63:30888"); // 数据报表 System.out.println("[报表模块 yudao-module-report 教程][参考 http://172.16.46.63:30888/report/ 开启]"); // 工作流 System.out.println("[工作流模块 yudao-module-bpm 教程][参考 http://172.16.46.63:30888/bpm/ 开启]"); - // 商城系统 - System.out.println("[商城系统 yudao-module-mall 教程][参考 http://172.16.46.63:30888/mall/build/ 开启]"); - // ERP 系统 - System.out.println("[ERP 系统 yudao-module-erp - 教程][参考 http://172.16.46.63:30888/erp/build/ 开启]"); - // CRM 系统 - System.out.println("[CRM 系统 yudao-module-crm - 教程][参考 http://172.16.46.63:30888/crm/build/ 开启]"); + // 微信公众号 System.out.println("[微信公众号 yudao-module-mp 教程][参考 http://172.16.46.63:30888/mp/build/ 开启]"); - // 支付平台 - System.out.println("[支付系统 yudao-module-pay - 教程][参考 http://172.16.46.63:30888/pay/build/ 开启]"); + // AI 大模型 System.out.println("[AI 大模型 yudao-module-ai - 教程][参考 http://172.16.46.63:30888/ai/build/ 开启]"); // IOT 物联网 diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/resources/application-local.yaml b/yudao-module-ai/yudao-module-ai-server/src/main/resources/application-local.yaml index 98bb2ed4..2982981d 100644 --- a/yudao-module-ai/yudao-module-ai-server/src/main/resources/application-local.yaml +++ b/yudao-module-ai/yudao-module-ai-server/src/main/resources/application-local.yaml @@ -3,7 +3,7 @@ spring: cloud: nacos: - server-addr: 127.0.0.1:8848 # Nacos 服务器地址 + server-addr: 172.16.46.63:30848 # Nacos 服务器地址 username: # Nacos 账号 password: # Nacos 密码 discovery: # 【配置中心】配置项 @@ -58,29 +58,20 @@ spring: primary: master datasource: master: - url: jdbc:mysql://127.0.0.1:3306/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 # SQLServer 连接的示例 - # url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 - username: root - password: 123456 - # username: sa # SQL Server 连接的示例 - # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # SQL Server 连接的示例 - # username: SYSDBA # DM 连接的示例 - # password: SYSDBA # DM 连接的示例 + url: jdbc:dm://172.16.46.247:1050?schema=RUOYI-VUE-PRO + username: SYSDBA + password: pgbsci6ddJ6Sqj@e slave: # 模拟从库,可根据自己需要修改 lazy: true # 开启懒加载,保证启动速度 - url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true - username: root - password: 123456 + url: jdbc:dm://172.16.46.247:1050?schema=RUOYI-VUE-PRO + username: SYSDBA + password: pgbsci6ddJ6Sqj@e # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 data: redis: - host: 127.0.0.1 # 地址 - port: 6379 # 端口 + host: 172.16.46.63 # 地址 + port: 30379 # 端口 database: 0 # 数据库索引 # password: 123456 # 密码,建议生产环境开启 diff --git a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index 2c3bb85f..1d623ce0 100644 --- a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -165,4 +165,15 @@ public class FileController { return CommonResult.customize(fileRespVO, HttpStatus.OK.value(), e.getMessage()); } } + + @GetMapping("/verify-code") + @Operation(summary = "校验验证码") + public CommonResult verifyCode(@Valid @RequestParam Long fileId, @RequestParam String code) throws Exception { + Long userId = getLoginUserId(); + byte[] content = fileService.verifyCodeAndGetFile(fileId, userId, code); + if(content == null || content.length == 0){ + return CommonResult.customize(null, HttpStatus.INTERNAL_SERVER_ERROR.value(), "验证码校验失败"); + } + return CommonResult.customize(null, HttpStatus.OK.value(), "验证码校验通过"); + } } diff --git a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java index 3c7e4fff..a31a0775 100644 --- a/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java +++ b/yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileRespVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; +import cn.hutool.core.date.DateUtil; import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient; import cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClient; import cn.iocoder.yudao.module.infra.service.file.FileConfigService; @@ -11,6 +13,7 @@ import lombok.experimental.Accessors; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.Base64; +import java.util.Date; /** * @author chenbowen @@ -78,7 +81,9 @@ public class FileRespVO { } String base64PresignedUrl = Base64.getEncoder().encodeToString(presignedUrl.getBytes(StandardCharsets.UTF_8)); String timestamp = String.valueOf(System.currentTimeMillis()); - String watermark = SpringUtils.getProperty("aj.captcha.water-mark", "中国铜业"); + String loginUserNickname = SecurityFrameworkUtils.getLoginUserNickname(); + String format = DateUtil.format(new Date(), "yyyy-MM-dd"); + String watermark = SpringUtils.getProperty("aj.captcha.water-mark", loginUserNickname+" "+ format); return onlinePreview + base64PresignedUrl + "&t=" + timestamp + "&watermarkTxt=" + watermark; } @Schema(description = "是否加密", example = "false") diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index a9943e22..23ec0035 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -54,7 +54,7 @@ public interface ErrorCodeConstants { // ========== 部门模块 1-002-004-000 ========== ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门"); ErrorCode DEPT_PARENT_NOT_EXITS = new ErrorCode(1_002_004_001,"父级部门不存在"); - ErrorCode DEPT_NOT_FOUND = new ErrorCode(1_002_004_002, "当前部门不存在"); + ErrorCode DEPT_NOT_FOUND = new ErrorCode(1_002_004_002, "机构不存在或当前账号无权限修改"); ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1_002_004_003, "存在子部门,无法删除"); ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1_002_004_004, "不能设置自己为父部门"); ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1_002_004_006, "部门({})不处于开启状态,不允许选择"); @@ -153,6 +153,13 @@ public interface ErrorCodeConstants { ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1_002_022_000, "code 不存在"); ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1_002_022_001, "code 已过期"); + // ========== 同步验证工具 1-002-019-000 ========== + ErrorCode SYNC_DECRYPT_TYPE = new ErrorCode(1_002_019_000, "解密失败"); + ErrorCode SYNC_ENCRYPT_TYPE = new ErrorCode(1_002_019_001, "加密失败"); + ErrorCode SYNC_SIGNATURE_UNSUPPORTED_TYPE = new ErrorCode(1_002_019_002, "签名类型不存在"); + // 同步签名验证失败 + ErrorCode SYNC_SIGNATURE_VERIFY_FAILED = new ErrorCode(1_002_019_003, "签名验证失败"); + // ========== 邮箱账号 1-002-023-000 ========== ErrorCode MAIL_ACCOUNT_NOT_EXISTS = new ErrorCode(1_002_023_000, "邮箱账号不存在"); ErrorCode MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS = new ErrorCode(1_002_023_001, "无法删除,该邮箱账号还有邮件模板"); diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java index e84777e2..79ae089c 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java @@ -44,7 +44,6 @@ public class DeptSaveReqVO { private String email; @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "状态不能为空") @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") private Integer status; diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/SyncController.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/SyncController.java new file mode 100644 index 00000000..836f4947 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/SyncController.java @@ -0,0 +1,293 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync; + +import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi; +import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCheckRespDTO; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginReqVO; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO; +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.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.UserSyncService; +import cn.iocoder.yudao.module.system.util.sync.SyncVerifyUtil; +import com.alibaba.fastjson.JSON; +import jakarta.annotation.Resource; +import jakarta.annotation.security.PermitAll; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getRequest; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; + +/** + * 对中铝 e 办 BIM 接口 - 统一 Sync Controller + */ +@RestController +@RequestMapping("/system/sync") +public class SyncController { + + @Value("${sync.encrypt-key}") + private String encryptKey; + + @Resource + private SchemaSyncService schemaService; + @Resource + private OrgSyncService organizationService; + @Resource + private UserSyncService accountService; + @Resource + private AdminAuthService adminAuthService; + @Resource + private OAuth2TokenCommonApi oauth2TokenApi; + + + @PostMapping("/SchemaService") + @TenantIgnore + @PermitAll + public SchemaResponseVO getSchema(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + SchemaRequestVO req = decryptRequest(encryptedBody, SchemaRequestVO.class); + bimRequestId = req.getBimRequestId(); + return schemaService.getSchema(req); + } catch (Exception e) { + SchemaResponseVO errorResp = new SchemaResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/OrgCreateService") + @TenantIgnore + @PermitAll + public OrgCreateResponseVO createOrg(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + OrgCreateRequestVO req = decryptRequest(encryptedBody, OrgCreateRequestVO.class); + bimRequestId = req.getBimRequestId(); + return organizationService.createOrg(req); + } catch (Exception e) { + OrgCreateResponseVO errorResp = new OrgCreateResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/OrgDeleteService") + @TenantIgnore + @PermitAll + public OrgDeleteResponseVO deleteOrg(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + OrgDeleteRequestVO req = decryptRequest(encryptedBody, OrgDeleteRequestVO.class); + bimRequestId = req.getBimRequestId(); + return organizationService.deleteOrg(req); + } catch (Exception e) { + OrgDeleteResponseVO errorResp = new OrgDeleteResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/OrgUpdateService") + @TenantIgnore + @PermitAll + public OrgUpdateResponseVO updateOrg(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + OrgUpdateRequestVO req = decryptRequest(encryptedBody, OrgUpdateRequestVO.class); + bimRequestId = req.getBimRequestId(); + return organizationService.updateOrg(req); + } catch (Exception e) { + OrgUpdateResponseVO errorResp = new OrgUpdateResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/QueryAllOrgIdsService") + @TenantIgnore + @PermitAll + public OrgListResponseVO listOrg(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + OrgListRequestVO req = decryptRequest(encryptedBody, OrgListRequestVO.class); + bimRequestId = req.getBimRequestId(); + return organizationService.listOrgIds(req); + } catch (Exception e) { + OrgListResponseVO errorResp = new OrgListResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/QueryOrgByIdService") + @TenantIgnore + @PermitAll + public OrgGetResponseVO getOrg(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + OrgGetRequestVO req = decryptRequest(encryptedBody, OrgGetRequestVO.class); + bimRequestId = req.getBimRequestId(); + return organizationService.getOrgById(req); + } catch (Exception e) { + OrgGetResponseVO errorResp = new OrgGetResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/UserCreateService") + @TenantIgnore + @PermitAll + public UserCreateResponseVO createUser(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + UserCreateRequestVO req = decryptRequest(encryptedBody, UserCreateRequestVO.class); + bimRequestId = req.getBimRequestId(); + return accountService.createUser(req); + } catch (Exception e) { + UserCreateResponseVO errorResp = new UserCreateResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/UserDeleteService") + @TenantIgnore + @PermitAll + public UserDeleteResponseVO deleteUser(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + UserDeleteRequestVO req = decryptRequest(encryptedBody, UserDeleteRequestVO.class); + bimRequestId = req.getBimRequestId(); + return accountService.deleteUser(req); + } catch (Exception e) { + UserDeleteResponseVO errorResp = new UserDeleteResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/UserUpdateService") + @TenantIgnore + @PermitAll + public UserUpdateResponseVO updateUser(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + UserUpdateRequestVO req = decryptRequest(encryptedBody, UserUpdateRequestVO.class); + bimRequestId = req.getBimRequestId(); + return accountService.updateUser(req); + } catch (Exception e) { + UserUpdateResponseVO errorResp = new UserUpdateResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/QueryAllUserIdsService") + @TenantIgnore + @PermitAll + public UserListResponseVO listUser(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + UserListRequestVO req = decryptRequest(encryptedBody, UserListRequestVO.class); + bimRequestId = req.getBimRequestId(); + return accountService.listUserIds(req); + } catch (Exception e) { + UserListResponseVO errorResp = new UserListResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + + @PostMapping("/QueryUserByIdService") + @TenantIgnore + @PermitAll + public UserGetResponseVO getUser(@RequestBody String encryptedBody) { + String bimRequestId = null; + try { + UserGetRequestVO req = decryptRequest(encryptedBody, UserGetRequestVO.class); + bimRequestId = req.getBimRequestId(); + return accountService.getUserById(req); + } catch (Exception e) { + UserGetResponseVO errorResp = new UserGetResponseVO(); + errorResp.setBimRequestId(bimRequestId); + errorResp.setResultCode("500"); + errorResp.setMessage(e.getMessage()); + return errorResp; + } + } + + private T decryptRequest(String encryptedBody, Class clazz) { + String bodyJson; + try { + bodyJson = SyncVerifyUtil.decrypt(encryptedBody, encryptKey, "AES"); + } catch (Exception e) { + throw exception(SYNC_DECRYPT_TYPE); + } + Map map = JSON.parseObject(bodyJson, Map.class); + if (!SyncVerifyUtil.verifySignature(map, "MD5")) { + throw exception(SYNC_SIGNATURE_VERIFY_FAILED); + } + AuthLoginReqVO authLoginReqVO = new AuthLoginReqVO(); + authLoginReqVO.setUsername((String) map.getOrDefault("bimRemoteUser", "")); + authLoginReqVO.setPassword((String) map.getOrDefault("bimRemotePwd", "")); + AuthLoginRespVO login = adminAuthService.login(authLoginReqVO); + // 校验访问令牌 + + OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(login.getAccessToken()).getCheckedData(); + if (accessToken == null) { + throw exception(AUTH_LOGIN_USER_DISABLED); + } + 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()); + return JSON.parseObject(bodyJson, clazz); + } +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/SyncBaseResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/SyncBaseResponseVO.java new file mode 100644 index 00000000..1e8102b7 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/SyncBaseResponseVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo; + +import lombok.Data; + +/** + * @author chenbowen + */ +@Data +public class SyncBaseResponseVO { + private String bimRequestId; + private String resultCode; + private String message; + + public SyncBaseResponseVO() {} + public SyncBaseResponseVO(String bimRequestId, String resultCode, String message) { + this.bimRequestId = bimRequestId; + this.resultCode = resultCode; + this.message = message; + } + +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgCreateRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgCreateRequestVO.java new file mode 100644 index 00000000..013c4491 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgCreateRequestVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "对外接口 - 机构创建 请求 VO") +@Data +public class OrgCreateRequestVO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求ID", required = true) + private String bimRequestId; + @Schema(description = "机构 名称", required = true) + private String name; + @Schema(description = "机构 父Id", required = true) + private Long parentId; + @Schema(description = "机构 负责人Id") + private Long leaderUserId; + @Schema(description = "机构 电话") + private String phone; + @Schema(description = "机构 邮件") + private String email; + @Schema(description = "机构 状态", required = true) + private Integer status; + @Schema(description = "机构 是否公司") + private Boolean isCompany; + @Schema(description = "机构 是否集团") + private Boolean isGroup; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgCreateResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgCreateResponseVO.java new file mode 100644 index 00000000..96be9ed1 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgCreateResponseVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 对外接口机构创建响应 VO + */ +@Data +@Schema(description = "对外接口机构创建响应 VO") +@JsonPropertyOrder({"bimRequestId", "uid"}) +public class OrgCreateResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "机构ID", required = true) + private String uid; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgDeleteRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgDeleteRequestVO.java new file mode 100644 index 00000000..6395560a --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgDeleteRequestVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "对外接口 - 机构删除 请求 VO") +@Data +public class OrgDeleteRequestVO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求 ID", required = true) + private String bimRequestId; + @Schema(description = "组织 ID", required = true) + private Long bimOrgId; + +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgDeleteResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgDeleteResponseVO.java new file mode 100644 index 00000000..96173cf6 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgDeleteResponseVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 对外接口机构删除响应 VO + */ +@Data +@Schema(description = "对外接口机构删除响应 VO") +@JsonPropertyOrder({"bimRequestId", "resultCode", "message"}) +public class OrgDeleteResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "结果编码", required = true) + private String resultCode; + + @Schema(description = "描述信息", required = true) + private String message; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgGetRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgGetRequestVO.java new file mode 100644 index 00000000..64408fa5 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgGetRequestVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * @author chenbowen + */ +@Schema(description = "对外接口 - 根据 ID 查询机构 请求 VO") +@Data +public class OrgGetRequestVO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求 ID", required = true) + private String bimRequestId; + @Schema(description = "组织 UID", required = true) + private String bimOrgId; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgGetResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgGetResponseVO.java new file mode 100644 index 00000000..24ea2c1f --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgGetResponseVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Map; + +/** + * 对外接口根据 ID 查询机构 响应 VO + */ +@Data +@Schema(description = "对外接口根据 ID 查询机构 响应 VO") +@JsonPropertyOrder({"bimRequestId", "resultCode", "organization", "message"}) +public class OrgGetResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "结果编码", required = true) + private String resultCode; + + @Schema(description = "机构信息 Map", required = true) + private Map organization; + + @Schema(description = "描述信息", required = true) + private String message; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgListRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgListRequestVO.java new file mode 100644 index 00000000..1cf9c90b --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgListRequestVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "对外接口 - 查询所有机构 ID 请求 VO") +@Data +public class OrgListRequestVO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求 ID", required = true) + private String bimRequestId; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgListResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgListResponseVO.java new file mode 100644 index 00000000..3e22e2bd --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgListResponseVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * 对外接口查询所有机构 ID 响应 VO + */ +@Data +@Schema(description = "对外接口查询所有机构 ID 响应 VO") +@JsonPropertyOrder({"bimRequestId", "resultCode", "orgIdList", "message"}) +public class OrgListResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "结果编码", required = true) + private String resultCode; + + @Schema(description = "机构ID 列表", required = true) + private List orgIdList; + + @Schema(description = "描述信息", required = true) + private String message; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgUpdateRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgUpdateRequestVO.java new file mode 100644 index 00000000..e8ff5170 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgUpdateRequestVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * @author chenbowen + */ +@Schema(description = "对外接口 - 机构更新 请求 VO") +@Data +public class OrgUpdateRequestVO extends DeptDO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求 ID", required = true) + private String bimRequestId; + @Schema(description = "请求 ID", required = true) + private Long bimOrgId; + @Schema(description = "机构 名称", required = true) + private String name; + @Schema(description = "机构 父Id", required = true) + private Long parentId; + @Schema(description = "机构 负责人Id") + private Long leaderUserId; + @Schema(description = "机构 电话") + private String phone; + @Schema(description = "机构 邮件") + private String email; + @Schema(description = "机构 状态", required = true) + private Integer status; + @Schema(description = "机构 是否公司") + private Boolean isCompany; + @Schema(description = "机构 是否集团") + private Boolean isGroup; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgUpdateResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgUpdateResponseVO.java new file mode 100644 index 00000000..fec05554 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/org/OrgUpdateResponseVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.org; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 对外接口机构更新响应 VO + */ +@Data +@Schema(description = "对外接口机构更新响应 VO") +@JsonPropertyOrder({"bimRequestId", "resultCode", "message"}) +public class OrgUpdateResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "结果编码", required = true) + private String resultCode; + + @Schema(description = "描述信息", required = true) + private String message; + + @Schema(description = "是否启用", required = true) + private Boolean __ENABLE__; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/schema/SchemaAttributeVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/schema/SchemaAttributeVO.java new file mode 100644 index 00000000..02eb9405 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/schema/SchemaAttributeVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.schema; + +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 对外接口 Schema 属性 VO + */ +@Data +@Schema(description = "对外接口 Schema 属性 VO") +@JsonPropertyOrder({"name", "type", "required", "multivalued"}) +public class SchemaAttributeVO implements Serializable { + + @Schema(description = "属性名", required = true) + private String name; + + @Schema(description = "属性类型", required = true) + private String type; + + @Schema(description = "是否必需", required = true) + private Boolean required; + + @Schema(description = "是否多值", required = true) + private Boolean multivalued; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/schema/SchemaRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/schema/SchemaRequestVO.java new file mode 100644 index 00000000..734b47f3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/schema/SchemaRequestVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.schema; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "对外接口 - Schema 请求 VO") +@Data +public class SchemaRequestVO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求 ID", required = true) + private String bimRequestId; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/schema/SchemaResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/schema/SchemaResponseVO.java new file mode 100644 index 00000000..8eb509b2 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/schema/SchemaResponseVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.schema; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 对外接口 Schema 响应 VO + */ +@Data +@Schema(description = "对外接口 Schema 响应 VO") +@JsonPropertyOrder({"bimRequestId", "account", "organization"}) +public class SchemaResponseVO extends SyncBaseResponseVO implements Serializable { + + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "账户属性列表", required = true) + private List account; + + @Schema(description = "组织属性列表", required = true) + private List organization; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserCreateRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserCreateRequestVO.java new file mode 100644 index 00000000..f5a1ccb6 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserCreateRequestVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * @author chenbowen + */ +@Schema(description = "对外接口账号创建请求 VO") +@Data +public class UserCreateRequestVO extends AdminUserDO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求ID", required = true) + private String bimRequestId; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserCreateResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserCreateResponseVO.java new file mode 100644 index 00000000..7f68a0eb --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserCreateResponseVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 对外接口账号创建响应 VO + */ +@Data +@Schema(description = "对外接口账号创建响应 VO") +@JsonPropertyOrder({"bimRequestId", "uid"}) +public class UserCreateResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + @Schema(description = "用户ID", required = true) + private String uid; + @Schema(description = "结果编码", required = true) + private String resultCode; + @Schema(description = "描述信息", required = true) + private String message; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserDeleteRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserDeleteRequestVO.java new file mode 100644 index 00000000..a300d1cd --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserDeleteRequestVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "对外接口 - 删除用户 请求 VO") +@Data +public class UserDeleteRequestVO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求 ID", required = true) + private String bimRequestId; + @Schema(description = "用户 ID", required = true) + private Long bimUid; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserDeleteResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserDeleteResponseVO.java new file mode 100644 index 00000000..1bc1e235 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserDeleteResponseVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 对外接口用户删除响应 VO + */ +@Data +@Schema(description = "对外接口用户删除响应 VO") +@JsonPropertyOrder({"bimRequestId", "resultCode", "message"}) +public class UserDeleteResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "结果编码", required = true) + private String resultCode; + + @Schema(description = "描述信息", required = true) + private String message; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserGetRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserGetRequestVO.java new file mode 100644 index 00000000..d083b715 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserGetRequestVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Schema(description = "对外接口 - 根据 ID 查询用户 请求 VO") +@Data +public class UserGetRequestVO { + @Schema(description = "用户名", required = true) + @NotBlank + private String bimRemoteUser; + @Schema(description = "密码", required = true) + @NotBlank + private String bimRemotePwd; + @Schema(description = "请求 ID", required = true) + @NotBlank + private String bimRequestId; + @Schema(description = "用户 UID", required = true) + @NotBlank + private String bimUid; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserGetResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserGetResponseVO.java new file mode 100644 index 00000000..925163e8 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserGetResponseVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Map; + +/** + * 对外接口根据 ID 查询用户 响应 VO + */ +@Data +@Schema(description = "对外接口根据 ID 查询用户 响应 VO") +@JsonPropertyOrder({"bimRequestId", "resultCode", "account", "message"}) +public class UserGetResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "结果编码", required = true) + private String resultCode; + + @Schema(description = "用户信息 Map", required = true) + private Map account; + + @Schema(description = "描述信息", required = true) + private String message; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserListRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserListRequestVO.java new file mode 100644 index 00000000..f8950428 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserListRequestVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "对外接口 - 查询所有用户 ID 请求 VO") +@Data +public class UserListRequestVO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求 ID", required = true) + private String bimRequestId; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserListResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserListResponseVO.java new file mode 100644 index 00000000..a35bfbc0 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserListResponseVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * 对外接口查询所有用户 ID 响应 VO + */ +@Data +@Schema(description = "对外接口查询所有用户 ID 响应 VO") +@JsonPropertyOrder({"bimRequestId", "resultCode", "userIdList", "message"}) +public class UserListResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "结果编码", required = true) + private String resultCode; + + @Schema(description = "用户ID 列表", required = true) + private List userIdList; + + @Schema(description = "描述信息", required = true) + private String message; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserUpdateRequestVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserUpdateRequestVO.java new file mode 100644 index 00000000..c99825f1 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserUpdateRequestVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Set; + +@Schema(description = "对外接口 - 更新用户 请求 VO") +@Data +public class UserUpdateRequestVO { + @Schema(description = "用户名", required = true) + private String bimRemoteUser; + @Schema(description = "密码", required = true) + private String bimRemotePwd; + @Schema(description = "请求 ID", required = true) + private String bimRequestId; + @Schema(description = "用户 ID", required = true) + private Long bimUid; + @Schema(description = "用户账号") + private String username; + @Schema(description = "用户密码") + private String password; + @Schema(description = "昵称") + private String nickname; + @Schema(description = "备注") + private String remark; + @Schema(description = "归属部门Id列表") + private Set deptIds; + @Schema(description = "邮箱") + private String email; + @Schema(description = "移动电话") + private String mobile; + @Schema(description = "性别") + private Integer sex; + @Schema(description = "头像 URL") + private String avatar; + @Schema(description = "账号状态") + private Integer status; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserUpdateResponseVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserUpdateResponseVO.java new file mode 100644 index 00000000..7a3358a5 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sync/vo/user/UserUpdateResponseVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.system.controller.admin.sync.vo.user; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.SyncBaseResponseVO; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 对外接口用户更新响应 VO + */ +@Data +@Schema(description = "对外接口用户更新响应 VO") +@JsonPropertyOrder({"bimRequestId", "resultCode", "message"}) +public class UserUpdateResponseVO extends SyncBaseResponseVO { + @Schema(description = "请求ID", required = true) + private String bimRequestId; + + @Schema(description = "结果编码", required = true) + private String resultCode; + + @Schema(description = "描述信息", required = true) + private String message; + + @Schema(description = "是否启用", required = true) + private Boolean __ENABLE__; +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java index 9a7d6ed1..6d8e7132 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java @@ -63,6 +63,9 @@ public class UserSaveReqVO { @DiffLogField(name = "用户性别", function = SexParseFunction.NAME) private Integer sex; + @Schema(description = "用户状态", example = "1") + private Integer status; + @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") @DiffLogField(name = "用户头像") private String avatar; diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java index 5dd81269..3256a646 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java @@ -7,6 +7,8 @@ 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 jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; @@ -31,12 +33,14 @@ public class DeptDO extends TenantBaseDO { /** * 部门名称 */ + @NotEmpty private String name; /** * 父部门ID * * 关联 {@link #id} */ + @NotNull private Long parentId; /** * 显示顺序 diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java index ba510511..0b716297 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/user/AdminUserDO.java @@ -6,6 +6,8 @@ import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import cn.iocoder.yudao.module.system.enums.common.SexEnum; import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import lombok.*; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -34,16 +36,19 @@ public class AdminUserDO extends TenantBaseDO { /** * 用户账号 */ + @NotEmpty private String username; /** * 加密后的密码 * * 因为目前使用 {@link BCryptPasswordEncoder} 加密器,所以无需自己处理 salt 盐 */ + @NotEmpty private String password; /** * 用户昵称 */ + @NotEmpty private String nickname; /** * 备注 @@ -53,6 +58,7 @@ public class AdminUserDO extends TenantBaseDO { * 部门 ID 列表 */ @TableField(exist = false, typeHandler = JacksonTypeHandler.class ) + @NotEmpty private Set deptIds; /** * 公司 ID 列表 @@ -76,12 +82,14 @@ public class AdminUserDO extends TenantBaseDO { /** * 手机号码 */ + @NotEmpty private String mobile; /** * 用户性别 * * 枚举类 {@link SexEnum} */ + @NotNull private Integer sex; /** * 用户头像 diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java index b0087060..0f33cc92 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java @@ -52,6 +52,8 @@ public class DeptServiceImpl implements DeptService { if (createReqVO.getParentId() == null) { createReqVO.setParentId(DeptDO.PARENT_ID_ROOT); } + // 创建时默认有效 + createReqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 校验父部门的有效性 validateParentDept(null, createReqVO.getParentId()); // 校验部门名的唯一性 diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/OrgSyncService.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/OrgSyncService.java new file mode 100644 index 00000000..f8165b9d --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/OrgSyncService.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.system.service.sync; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.org.*; + +/** + * 统一机构相关 Service 接口 + */ +public interface OrgSyncService { + /** + * 机构创建 + */ + OrgCreateResponseVO createOrg(OrgCreateRequestVO requestVO); + + /** + * 机构删除 + */ + OrgDeleteResponseVO deleteOrg(OrgDeleteRequestVO requestVO); + + /** + * 机构更新 + */ + OrgUpdateResponseVO updateOrg(OrgUpdateRequestVO requestVO); + + /** + * 根据 ID 查询机构 + */ + OrgGetResponseVO getOrgById(OrgGetRequestVO requestVO); + + /** + * 查询所有机构 ID + */ + OrgListResponseVO listOrgIds(OrgListRequestVO requestVO); +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/OrgSyncServiceImpl.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/OrgSyncServiceImpl.java new file mode 100644 index 00000000..de9a0002 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/OrgSyncServiceImpl.java @@ -0,0 +1,144 @@ +package cn.iocoder.yudao.module.system.service.sync; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +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.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; + +/** + * 统一机构相关 Service 实现 + * @author chenbowen + */ +@Service +public class OrgSyncServiceImpl implements OrgSyncService { + @Resource + private DeptService deptService; + + @Override + public OrgCreateResponseVO createOrg(OrgCreateRequestVO requestVO) { + DeptSaveReqVO bean = BeanUtils.toBean(requestVO, DeptSaveReqVO.class); + Long deptId = deptService.createDept(bean); + OrgCreateResponseVO resp = new OrgCreateResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + resp.setUid(String.valueOf(deptId)); + resp.setResultCode("0"); + resp.setMessage("success"); + return resp; + } + + @Override + public OrgDeleteResponseVO deleteOrg(OrgDeleteRequestVO requestVO) { + Long deptId = requestVO.getBimOrgId(); + deptService.deleteDept(deptId); + OrgDeleteResponseVO resp = new OrgDeleteResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + resp.setResultCode("0"); + resp.setMessage("success"); + return resp; + } + + @Override + public OrgUpdateResponseVO updateOrg(OrgUpdateRequestVO requestVO) { + OrgUpdateResponseVO resp = new OrgUpdateResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + DeptSaveReqVO updateReqVO = new DeptSaveReqVO(); + Long orgId = requestVO.getBimOrgId() != null ? requestVO.getBimOrgId() : null; + DeptDO originDept = (orgId != null && deptService != null) ? deptService.getDept(orgId) : null; + if (originDept == null) { + resp.setResultCode("500"); + resp.setMessage("机构不存在或当前账号无权限修改"); + resp.set__ENABLE__(false); + return resp; + } + updateReqVO.setId(orgId); + resp.set__ENABLE__(originDept.getStatus() != null && originDept.getStatus() == 0); + if (requestVO.getName() != null && !requestVO.getName().isEmpty()) { + updateReqVO.setName(requestVO.getName()); + } + if (requestVO.getParentId() != null) { + updateReqVO.setParentId(requestVO.getParentId()); + } + if (requestVO.getLeaderUserId() != null) { + updateReqVO.setLeaderUserId(requestVO.getLeaderUserId()); + } + if (requestVO.getPhone() != null && !requestVO.getPhone().isEmpty()) { + updateReqVO.setPhone(requestVO.getPhone()); + } + if (requestVO.getEmail() != null && !requestVO.getEmail().isEmpty()) { + updateReqVO.setEmail(requestVO.getEmail()); + } + if (requestVO.getStatus() != null) { + updateReqVO.setStatus(requestVO.getStatus()); + } + if (requestVO.getIsCompany() != null) { + updateReqVO.setIsCompany(requestVO.getIsCompany()); + } + if (requestVO.getIsGroup() != null) { + updateReqVO.setIsGroup(requestVO.getIsGroup()); + } + deptService.updateDept(updateReqVO); + resp.setResultCode("0"); + resp.setMessage("success"); + return resp; + } + + @Override + public OrgGetResponseVO getOrgById(OrgGetRequestVO requestVO) { + OrgGetResponseVO resp = new OrgGetResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + try { + Long deptId = Long.valueOf(requestVO.getBimOrgId()); + DeptDO dept = deptService.getDept(deptId); + if (dept != null) { + Map organization = new HashMap<>(); + PropertyDescriptor[] pds = org.springframework.beans.BeanUtils.getPropertyDescriptors(DeptDO.class); + for (PropertyDescriptor pd : pds) { + String name = pd.getName(); + if ("class".equals(name) || "id".equals(name)) { + continue; + } + try { + Object value = pd.getReadMethod().invoke(dept); + organization.put(name, value); + } catch (Exception ignore) {} + } + organization.put("uid", dept.getId()); + resp.setResultCode("0"); + resp.setOrganization(organization); + resp.setMessage("success"); + } else { + resp.setResultCode("500"); + resp.setMessage("机构不存在或当前账号无权限修改"); + } + } catch (Exception e) { + resp.setResultCode("500"); + resp.setMessage("参数错误"); + } + return resp; + } + + @Override + public OrgListResponseVO listOrgIds(OrgListRequestVO requestVO) { + List deptList = deptService.getDeptList(new DeptListReqVO()); + List list = new ArrayList<>(); + for (DeptDO dept : deptList) { + list.add(String.valueOf(dept.getId())); + } + OrgListResponseVO resp = new OrgListResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + resp.setResultCode("0"); + resp.setOrgIdList(list); + resp.setMessage("success"); + return resp; + } +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/SchemaSyncService.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/SchemaSyncService.java new file mode 100644 index 00000000..65d31744 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/SchemaSyncService.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.system.service.sync; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.schema.SchemaRequestVO; +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.schema.SchemaResponseVO; + +/** + * 对外接口 - Schema 服务 + */ +public interface SchemaSyncService { + + /** + * 获取 Schema 配置 + * + * @param requestVO 请求 VO + * @return 响应 VO + */ + SchemaResponseVO getSchema(SchemaRequestVO requestVO); +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/SchemaSyncServiceImpl.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/SchemaSyncServiceImpl.java new file mode 100644 index 00000000..62bf2583 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/SchemaSyncServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.system.service.sync; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.schema.SchemaAttributeVO; +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.dal.dataobject.dept.DeptDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import org.springframework.stereotype.Service; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Service + +public class SchemaSyncServiceImpl implements SchemaSyncService { + // Service method now accepts decrypted RequestVO + @Override + public SchemaResponseVO getSchema(SchemaRequestVO requestVO) { + SchemaResponseVO resp = new SchemaResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + resp.setAccount(buildSchemaAttributes(AdminUserDO.class)); + resp.setOrganization(buildSchemaAttributes(DeptDO.class)); + return resp; + } + + /** + * 使用 ReflectUtil 构建 SchemaAttributeVO 列表 + */ + private List buildSchemaAttributes(Class clazz) { + List list = new ArrayList<>(); + // 使用 Spring ReflectionUtils 遍历字段 + // 遍历类及其父类字段,过滤静态、常量、以及不返回的字段 + // 优化排除逻辑:支持批量、可扩展、忽略大小写和前缀 + final String[] excludeFields = {"companyDeptInfos", "postIds", "tenantId", "createTime", "updateTime", "creator", "updater", "companyIds", "avatar"}; + final String[] excludePrefixes = {"internal", "_"}; + ReflectionUtils.doWithFields(clazz, field -> { + field.setAccessible(true); + SchemaAttributeVO vo = new SchemaAttributeVO(); + vo.setName(field.getName()); + vo.setType(field.getType().getSimpleName()); + // 如果字段上标注 @NotNull 或 @NotEmpty 注解,则认为是必需的 + boolean required = field.isAnnotationPresent(NotNull.class) || field.isAnnotationPresent(NotEmpty.class); + vo.setRequired(required); + boolean multivalued = Collection.class.isAssignableFrom(field.getType()) || field.getType().isArray(); + vo.setMultivalued(multivalued); + list.add(vo); + }, field -> { + int mod = field.getModifiers(); + if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) { + return false; + } + String name = field.getName(); + // 排除指定字段(忽略大小写) + for (String exclude : excludeFields) { + if (exclude.equalsIgnoreCase(name)) { + return false; + } + } + // 排除指定前缀字段 + for (String prefix : excludePrefixes) { + if (name.startsWith(prefix)) { + return false; + } + } + return true; + }); + return list; + } +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/UserSyncService.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/UserSyncService.java new file mode 100644 index 00000000..9cb2f496 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/UserSyncService.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.system.service.sync; + +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.user.*; +import org.springframework.validation.annotation.Validated; + +/** + * 统一账号相关 Service 接口 + */ +@Validated +public interface UserSyncService { + /** + * 账号创建 + */ + UserCreateResponseVO createUser(UserCreateRequestVO requestVO); + + /** + * 账号删除 + */ + UserDeleteResponseVO deleteUser(UserDeleteRequestVO requestVO); + + /** + * 账号更新 + */ + UserUpdateResponseVO updateUser(UserUpdateRequestVO requestVO); + + /** + * 根据 ID 查询账号 + */ + UserGetResponseVO getUserById(UserGetRequestVO requestVO); + + /** + * 查询所有账号 ID + */ + UserListResponseVO listUserIds(UserListRequestVO requestVO); +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/UserSyncServiceImpl.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/UserSyncServiceImpl.java new file mode 100644 index 00000000..2562d6dc --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sync/UserSyncServiceImpl.java @@ -0,0 +1,159 @@ +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 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; + +@Service +public class UserSyncServiceImpl implements UserSyncService { + @Resource + private AdminUserService adminUserService; + @Resource + private UserDeptService userDeptService; + + @Override + public UserCreateResponseVO createUser(UserCreateRequestVO requestVO) { + TenantContextHolder.setTenantId(Objects.requireNonNull(getLoginUser()).getTenantId()); + UserSaveReqVO saveReqVO = BeanUtils.toBean(requestVO, UserSaveReqVO.class); + Long userId = adminUserService.createUser(saveReqVO); + UserCreateResponseVO resp = new UserCreateResponseVO(); + resp.setUid(String.valueOf(userId)); + resp.setBimRequestId(requestVO.getBimRequestId()); + resp.setResultCode("0"); + resp.setMessage("success"); + return resp; + } + + @Override + public UserDeleteResponseVO deleteUser(UserDeleteRequestVO requestVO) { + AdminUserDO user = adminUserService.getUserByUsername(requestVO.getBimRemoteUser()); + UserDeleteResponseVO resp = new UserDeleteResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + if (user != null) { + adminUserService.deleteUser(requestVO.getBimUid()); + resp.setResultCode("0"); + resp.setMessage("success"); + } else { + resp.setResultCode("500"); + resp.setMessage("用户不存在"); + } + return resp; + } + + @Override + public UserUpdateResponseVO updateUser(UserUpdateRequestVO requestVO) { + AdminUserDO user = adminUserService.getUser(requestVO.getBimUid()); + UserUpdateResponseVO resp = new UserUpdateResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + if (user != null) { + resp.set__ENABLE__(user.getStatus() != null && user.getStatus() == 0); + UserSaveReqVO updateReqVO = new UserSaveReqVO(); + updateReqVO.setId(requestVO.getBimUid()); + if (requestVO.getUsername() != null && !requestVO.getUsername().isEmpty()) { + updateReqVO.setUsername(requestVO.getUsername()); + } + if (requestVO.getNickname() != null && !requestVO.getNickname().isEmpty()) { + updateReqVO.setNickname(requestVO.getNickname()); + } + if (requestVO.getRemark() != null && !requestVO.getRemark().isEmpty()) { + updateReqVO.setRemark(requestVO.getRemark()); + } + // 部门更新逻辑修复:先删除原有部门关系,再插入新部门关系 + if (requestVO.getDeptIds() != null && !requestVO.getDeptIds().isEmpty()) { + // 删除原有部门关系 + userDeptService.deleteUserDeptByUserId(user.getId()); + // 插入新部门关系 + java.util.List deptList = new java.util.ArrayList<>(); + for (Long deptId : requestVO.getDeptIds()) { + UserDeptDO deptDO = new UserDeptDO(); + deptDO.setUserId(user.getId()); + deptDO.setDeptId(deptId); + deptList.add(deptDO); + } + userDeptService.batchCreateUserDept(deptList); + } + if (requestVO.getEmail() != null && !requestVO.getEmail().isEmpty()) { + updateReqVO.setEmail(requestVO.getEmail()); + } + if (requestVO.getMobile() != null && !requestVO.getMobile().isEmpty()) { + updateReqVO.setMobile(requestVO.getMobile()); + } + if (requestVO.getSex() != null) { + updateReqVO.setSex(requestVO.getSex()); + } + if (requestVO.getAvatar() != null && !requestVO.getAvatar().isEmpty()) { + updateReqVO.setAvatar(requestVO.getAvatar()); + } + adminUserService.updateUser(updateReqVO); + resp.setResultCode("0"); + resp.setMessage("success"); + } else { + resp.setResultCode("500"); + resp.setMessage("用户不存在"); + resp.set__ENABLE__(false); + } + return resp; + } + + @Override + public UserGetResponseVO getUserById(UserGetRequestVO requestVO) { + UserGetResponseVO resp = new UserGetResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + try { + Long userId = Long.valueOf(requestVO.getBimUid()); + AdminUserDO user = adminUserService.getUser(userId); + if (user != null) { + Map account = new HashMap<>(); + PropertyDescriptor[] pds = org.springframework.beans.BeanUtils.getPropertyDescriptors(AdminUserDO.class); + for (PropertyDescriptor pd : pds) { + String name = pd.getName(); + if ("class".equals(name) || "id".equals(name)) { + continue; + } + try { + Object value = pd.getReadMethod().invoke(user); + account.put(name, value); + } catch (Exception ignore) {} + } + account.put("uid", user.getId()); + resp.setResultCode("0"); + resp.setAccount(account); + resp.setMessage("success"); + } else { + resp.setResultCode("500"); + resp.setMessage("用户不存在"); + } + } catch (Exception e) { + resp.setResultCode("500"); + resp.setMessage("参数错误"); + } + return resp; + } + + @Override + public UserListResponseVO listUserIds(UserListRequestVO requestVO) { + List users = adminUserService.getUserListByStatus(0); + List userIdList = new ArrayList<>(); + for (AdminUserDO user : users) { + userIdList.add(String.valueOf(user.getId())); + } + UserListResponseVO resp = new UserListResponseVO(); + resp.setBimRequestId(requestVO.getBimRequestId()); + resp.setResultCode("0"); + resp.setUserIdList(userIdList); + resp.setMessage("success"); + return resp; + } +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index 845a1f89..4b619690 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -153,14 +153,43 @@ public class AdminUserServiceImpl implements AdminUserService { AdminUserDO oldUser = validateUserForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getUsername(), updateReqVO.getMobile(), updateReqVO.getEmail(), updateReqVO.getDeptIds(), updateReqVO.getPostIds()); - // 2.1 更新用户 - AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class); + // 2.1 只更新非空字段 + AdminUserDO updateObj = new AdminUserDO(); + updateObj.setId(updateReqVO.getId()); + if (StrUtil.isNotBlank(updateReqVO.getUsername())) { + updateObj.setUsername(updateReqVO.getUsername()); + } + if (StrUtil.isNotBlank(updateReqVO.getNickname())) { + updateObj.setNickname(updateReqVO.getNickname()); + } + if (StrUtil.isNotBlank(updateReqVO.getMobile())) { + updateObj.setMobile(updateReqVO.getMobile()); + } + if (StrUtil.isNotBlank(updateReqVO.getEmail())) { + updateObj.setEmail(updateReqVO.getEmail()); + } + if (updateReqVO.getSex() != null) { + updateObj.setSex(updateReqVO.getSex()); + } + if (updateReqVO.getStatus() != null) { + updateObj.setStatus(updateReqVO.getStatus()); + } + if (CollectionUtil.isNotEmpty(updateReqVO.getDeptIds())) { + updateObj.setDeptIds(updateReqVO.getDeptIds()); + } + if (CollectionUtil.isNotEmpty(updateReqVO.getPostIds())) { + updateObj.setPostIds(updateReqVO.getPostIds()); + } + if (StrUtil.isNotBlank(updateReqVO.getRemark())) { + updateObj.setRemark(updateReqVO.getRemark()); + } userMapper.updateById(updateObj); // 2.2 更新部门 if (CollectionUtil.isNotEmpty(updateObj.getDeptIds())) { // 删除原有的部门 userDeptService.deleteUserDeptByUserId(updateObj.getId()); + userDeptService.deleteUserDeptByUserId(updateObj.getId()); // 插入新的部门 userDeptService.batchCreateUserDept(convertList(updateObj.getDeptIds(), deptId -> new UserDeptDO().setUserId(updateObj.getId()).setDeptId(deptId))); diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/util/sync/SyncVerifyUtil.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/util/sync/SyncVerifyUtil.java new file mode 100644 index 00000000..7057fc0d --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/util/sync/SyncVerifyUtil.java @@ -0,0 +1,90 @@ +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 java.nio.charset.StandardCharsets; +import java.util.Map; +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; + +/** + * @author chenbowen + */ +public class SyncVerifyUtil { + + public static String decrypt(String ciphertext, String key, String type) { + byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); + if ("AES".equalsIgnoreCase(type)) { + byte[] aesKey = new byte[16]; + System.arraycopy(keyBytes, 0, aesKey, 0, Math.min(keyBytes.length, aesKey.length)); + AES aes = SecureUtil.aes(aesKey); + return aes.decryptStr(ciphertext); + } else if ("DES".equalsIgnoreCase(type)) { + byte[] desKey = new byte[8]; + System.arraycopy(keyBytes, 0, desKey, 0, Math.min(keyBytes.length, desKey.length)); + DES des = SecureUtil.des(desKey); + return des.decryptStr(ciphertext); + } else { + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + } + } + + /** + * 对称加密 + * @param plaintext 明文内容 + * @param key 密钥 + * @param type 加密类型,支持 AES、DES + * @return 密文(Hex 格式) + */ + public static String encrypt(String plaintext, String key, String type) { + byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); + if ("AES".equalsIgnoreCase(type)) { + byte[] aesKey = new byte[16]; + System.arraycopy(keyBytes, 0, aesKey, 0, Math.min(keyBytes.length, aesKey.length)); + AES aes = SecureUtil.aes(aesKey); + return aes.encryptHex(plaintext); + } else if ("DES".equalsIgnoreCase(type)) { + byte[] desKey = new byte[8]; + System.arraycopy(keyBytes, 0, desKey, 0, Math.min(keyBytes.length, desKey.length)); + DES des = SecureUtil.des(desKey); + return des.encryptHex(plaintext); + } else { + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + } + } + + public static boolean verifySignature(Map reqMap, String type) { + // 排序并拼接参数,忽略 signature 字段 + Map sortedMap = new TreeMap<>(reqMap); + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : sortedMap.entrySet()) { + String key = entry.getKey(); + if ("signature".equals(key) || entry.getValue() == null) { + continue; + } + sb.append(key).append("=").append(entry.getValue()).append("&"); + } + if (!sb.isEmpty()) { + sb.deleteCharAt(sb.length() - 1); + } + // 取出请求中的 signature + String provided = (String) reqMap.get("signature"); + if (provided == null) { + return false; + } + // 计算签名 + String computed; + if ("MD5".equalsIgnoreCase(type)) { + computed = SecureUtil.md5(sb.toString()); + } else if ("SHA256".equalsIgnoreCase(type)) { + computed = SecureUtil.sha256(sb.toString()); + } else { + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + } + return provided.equalsIgnoreCase(computed); + } +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/resources/application.yaml b/yudao-module-system/yudao-module-system-server/src/main/resources/application.yaml index 2c4db115..13e96058 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/resources/application.yaml +++ b/yudao-module-system/yudao-module-system-server/src/main/resources/application.yaml @@ -189,3 +189,6 @@ yudao: end-code: 9999 # 这里配置 9999 的原因是,测试方便。 debug: false + +sync: + encrypt-key: 25@jygk # 中铝 加密 key diff --git a/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/sync/OrgSyncServiceImplTest.java b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/sync/OrgSyncServiceImplTest.java new file mode 100644 index 00000000..0c448fe8 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/sync/OrgSyncServiceImplTest.java @@ -0,0 +1,209 @@ +package cn.iocoder.yudao.module.system.service.sync; + +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +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.service.dept.DeptService; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +public class OrgSyncServiceImplTest extends BaseMockitoUnitTest { + + @InjectMocks + private OrgSyncServiceImpl orgSyncService; + + @Mock + private DeptService deptService; + + @Test + void testCreateOrg() { + // Arrange + OrgCreateRequestVO requestVO = randomPojo(OrgCreateRequestVO.class); + Long newDeptId = randomLongId(); + when(deptService.createDept(any(DeptSaveReqVO.class))).thenReturn(newDeptId); + + // Act + OrgCreateResponseVO response = orgSyncService.createOrg(requestVO); + + // Assert + assertNotNull(response); + assertEquals(requestVO.getBimRequestId(), response.getBimRequestId()); + assertEquals(String.valueOf(newDeptId), response.getUid()); + + ArgumentCaptor captor = ArgumentCaptor.forClass(DeptSaveReqVO.class); + verify(deptService).createDept(captor.capture()); + DeptSaveReqVO capturedVO = captor.getValue(); + assertEquals(requestVO.getName(), capturedVO.getName()); + assertEquals(requestVO.getParentId(), capturedVO.getParentId()); + } + + @Test + void testDeleteOrg() { + // Arrange + OrgDeleteRequestVO requestVO = new OrgDeleteRequestVO(); + requestVO.setBimOrgId(123L); + requestVO.setBimRequestId("req-456"); + + // Act + OrgDeleteResponseVO response = orgSyncService.deleteOrg(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + assertEquals(requestVO.getBimRequestId(), response.getBimRequestId()); + verify(deptService).deleteDept(123L); + } + + @Test + void testUpdateOrg_Success() { + // Arrange + OrgUpdateRequestVO requestVO = randomPojo(OrgUpdateRequestVO.class); + requestVO.setBimOrgId(randomLongId()); + + DeptDO existingDept = randomPojo(DeptDO.class); + existingDept.setStatus(0); // Active + when(deptService.getDept(requestVO.getBimOrgId())).thenReturn(existingDept); + + // Act + OrgUpdateResponseVO response = orgSyncService.updateOrg(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + assertTrue(response.get__ENABLE__()); + + ArgumentCaptor captor = ArgumentCaptor.forClass(DeptSaveReqVO.class); + verify(deptService).updateDept(captor.capture()); + DeptSaveReqVO capturedVO = captor.getValue(); + assertEquals(requestVO.getBimOrgId(), capturedVO.getId()); + assertEquals(requestVO.getName(), capturedVO.getName()); + assertEquals(requestVO.getParentId(), capturedVO.getParentId()); + } + + @Test + void testUpdateOrg_NotFound() { + // Arrange + OrgUpdateRequestVO requestVO = randomPojo(OrgUpdateRequestVO.class); + requestVO.setBimOrgId(randomLongId()); + when(deptService.getDept(requestVO.getBimOrgId())).thenReturn(null); + + // Act + OrgUpdateResponseVO response = orgSyncService.updateOrg(requestVO); + + // Assert + assertNotNull(response); + assertEquals("500", response.getResultCode()); + assertEquals("机构不存在或当前账号无权限修改", response.getMessage()); + assertFalse(response.get__ENABLE__()); + verify(deptService, never()).updateDept(any()); + } + + @Test + void testGetOrgById_Success() { + // Arrange + OrgGetRequestVO requestVO = new OrgGetRequestVO(); + Long deptId = randomLongId(); + requestVO.setBimOrgId(String.valueOf(deptId)); + requestVO.setBimRequestId("req-789"); + + DeptDO dept = randomPojo(DeptDO.class); + dept.setId(deptId); + when(deptService.getDept(deptId)).thenReturn(dept); + + // Act + OrgGetResponseVO response = orgSyncService.getOrgById(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + assertNotNull(response.getOrganization()); + assertEquals(dept.getId(), response.getOrganization().get("uid")); + assertEquals(dept.getName(), response.getOrganization().get("name")); + } + + @Test + void testGetOrgById_NotFound() { + // Arrange + OrgGetRequestVO requestVO = new OrgGetRequestVO(); + Long deptId = randomLongId(); + requestVO.setBimOrgId(String.valueOf(deptId)); + when(deptService.getDept(deptId)).thenReturn(null); + + // Act + OrgGetResponseVO response = orgSyncService.getOrgById(requestVO); + + // Assert + assertNotNull(response); + assertEquals("500", response.getResultCode()); + assertEquals("机构不存在或当前账号无权限修改", response.getMessage()); + assertNull(response.getOrganization()); + } + + @Test + void testGetOrgById_InvalidId() { + // Arrange + OrgGetRequestVO requestVO = new OrgGetRequestVO(); + requestVO.setBimOrgId("invalid-id"); + + // Act + OrgGetResponseVO response = orgSyncService.getOrgById(requestVO); + + // Assert + assertNotNull(response); + assertEquals("500", response.getResultCode()); + assertEquals("参数错误", response.getMessage()); + assertNull(response.getOrganization()); + } + + @Test + void testListOrgIds() { + // Arrange + OrgListRequestVO requestVO = randomPojo(OrgListRequestVO.class); + DeptDO dept1 = randomPojo(DeptDO.class); + DeptDO dept2 = randomPojo(DeptDO.class); + List deptList = List.of(dept1, dept2); + when(deptService.getDeptList(any(DeptListReqVO.class))).thenReturn(deptList); + + // Act + OrgListResponseVO response = orgSyncService.listOrgIds(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + assertEquals(2, response.getOrgIdList().size()); + assertTrue(response.getOrgIdList().contains(String.valueOf(dept1.getId()))); + assertTrue(response.getOrgIdList().contains(String.valueOf(dept2.getId()))); + } + + @Test + void testListOrgIds_Empty() { + // Arrange + OrgListRequestVO requestVO = randomPojo(OrgListRequestVO.class); + when(deptService.getDeptList(any(DeptListReqVO.class))).thenReturn(Collections.emptyList()); + + // Act + OrgListResponseVO response = orgSyncService.listOrgIds(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + assertTrue(response.getOrgIdList().isEmpty()); + } +} diff --git a/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/sync/SchemaSyncServiceImplTest.java b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/sync/SchemaSyncServiceImplTest.java new file mode 100644 index 00000000..ee00f5f4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/sync/SchemaSyncServiceImplTest.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.system.service.sync; + +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.system.controller.admin.sync.vo.schema.SchemaAttributeVO; +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 org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; + +import java.util.List; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.*; + +public class SchemaSyncServiceImplTest extends BaseMockitoUnitTest { + + @InjectMocks + private SchemaSyncServiceImpl schemaSyncService; + + @Test + void testGetSchema() { + // Arrange + SchemaRequestVO requestVO = randomPojo(SchemaRequestVO.class); + + // Act + SchemaResponseVO response = schemaSyncService.getSchema(requestVO); + + // Assert + assertNotNull(response); + assertEquals(requestVO.getBimRequestId(), response.getBimRequestId()); + + // Validate Account Schema + List accountSchema = response.getAccount(); + assertNotNull(accountSchema); + assertFalse(accountSchema.isEmpty()); + // Check for a few expected fields in AdminUserDO + assertTrue(accountSchema.stream().anyMatch(a -> "username".equals(a.getName()) && "String".equals(a.getType()))); + assertTrue(accountSchema.stream().anyMatch(a -> "nickname".equals(a.getName()) && "String".equals(a.getType()))); + assertTrue(accountSchema.stream().anyMatch(a -> "deptIds".equals(a.getName()) && "Set".equals(a.getType()) && a.getMultivalued())); + // Check that excluded fields are not present + assertTrue(accountSchema.stream().noneMatch(a -> "tenantId".equals(a.getName()))); + assertTrue(accountSchema.stream().noneMatch(a -> "avatar".equals(a.getName()))); + + + // Validate Organization Schema + List orgSchema = response.getOrganization(); + assertNotNull(orgSchema); + assertFalse(orgSchema.isEmpty()); + // Check for a few expected fields in DeptDO + assertTrue(orgSchema.stream().anyMatch(a -> "name".equals(a.getName()) && "String".equals(a.getType()))); + assertTrue(orgSchema.stream().anyMatch(a -> "parentId".equals(a.getName()) && "Long".equals(a.getType()))); + assertTrue(orgSchema.stream().anyMatch(a -> "leaderUserId".equals(a.getName()) && "Long".equals(a.getType()))); + // Check that excluded fields are not present + assertTrue(orgSchema.stream().noneMatch(a -> "creator".equals(a.getName()))); + assertTrue(orgSchema.stream().noneMatch(a -> "updateTime".equals(a.getName()))); + } +} diff --git a/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/sync/UserSyncServiceImplTest.java b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/sync/UserSyncServiceImplTest.java new file mode 100644 index 00000000..0381fc9f --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/sync/UserSyncServiceImplTest.java @@ -0,0 +1,221 @@ +package cn.iocoder.yudao.module.system.service.sync; + +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +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.service.user.AdminUserService; +import cn.iocoder.yudao.module.system.service.userdept.UserDeptService; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +public class UserSyncServiceImplTest extends BaseMockitoUnitTest { + + @InjectMocks + private UserSyncServiceImpl userSyncService; + + @Mock + private AdminUserService adminUserService; + + @Mock + private UserDeptService userDeptService; + + private MockedStatic securityFrameworkUtilsMock; + + @BeforeEach + void setUp() { + securityFrameworkUtilsMock = Mockito.mockStatic(SecurityFrameworkUtils.class); + LoginUser mockLoginUser = new LoginUser(); + mockLoginUser.setTenantId(1L); + securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(mockLoginUser); + } + + @AfterEach + void tearDown() { + securityFrameworkUtilsMock.close(); + } + + @Test + void testCreateUser() { + // Arrange + UserCreateRequestVO requestVO = randomPojo(UserCreateRequestVO.class); + Long newUserId = randomLongId(); + when(adminUserService.createUser(any(UserSaveReqVO.class))).thenReturn(newUserId); + + // Act + UserCreateResponseVO response = userSyncService.createUser(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + assertEquals(String.valueOf(newUserId), response.getUid()); + assertEquals(requestVO.getBimRequestId(), response.getBimRequestId()); + + verify(adminUserService).createUser(any(UserSaveReqVO.class)); + } + + @Test + void testDeleteUser_Success() { + // Arrange + UserDeleteRequestVO requestVO = randomPojo(UserDeleteRequestVO.class); + AdminUserDO existingUser = randomPojo(AdminUserDO.class); + when(adminUserService.getUserByUsername(requestVO.getBimRemoteUser())).thenReturn(existingUser); + + // Act + UserDeleteResponseVO response = userSyncService.deleteUser(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + verify(adminUserService).deleteUser(requestVO.getBimUid()); + } + + @Test + void testDeleteUser_NotFound() { + // Arrange + UserDeleteRequestVO requestVO = randomPojo(UserDeleteRequestVO.class); + when(adminUserService.getUserByUsername(requestVO.getBimRemoteUser())).thenReturn(null); + + // Act + UserDeleteResponseVO response = userSyncService.deleteUser(requestVO); + + // Assert + assertNotNull(response); + assertEquals("500", response.getResultCode()); + assertEquals("用户不存在", response.getMessage()); + verify(adminUserService, never()).deleteUser(any()); + } + + @Test + void testUpdateUser_Success() { + // Arrange + UserUpdateRequestVO requestVO = randomPojo(UserUpdateRequestVO.class, o -> o.setDeptIds(Set.of(randomLongId(), randomLongId()))); + AdminUserDO existingUser = randomPojo(AdminUserDO.class); + existingUser.setStatus(0); // Active + when(adminUserService.getUser(requestVO.getBimUid())).thenReturn(existingUser); + + // Act + UserUpdateResponseVO response = userSyncService.updateUser(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + assertTrue(response.get__ENABLE__()); + + verify(userDeptService).deleteUserDeptByUserId(existingUser.getId()); + verify(userDeptService).batchCreateUserDept(anyList()); + verify(adminUserService).updateUser(any(UserSaveReqVO.class)); + } + + @Test + void testUpdateUser_NotFound() { + // Arrange + UserUpdateRequestVO requestVO = randomPojo(UserUpdateRequestVO.class); + when(adminUserService.getUser(requestVO.getBimUid())).thenReturn(null); + + // Act + UserUpdateResponseVO response = userSyncService.updateUser(requestVO); + + // Assert + assertNotNull(response); + assertEquals("500", response.getResultCode()); + assertEquals("用户不存在", response.getMessage()); + assertFalse(response.get__ENABLE__()); + verify(adminUserService, never()).updateUser(any()); + } + + @Test + void testGetUserById_Success() { + // Arrange + UserGetRequestVO requestVO = new UserGetRequestVO(); + Long userId = randomLongId(); + requestVO.setBimUid(String.valueOf(userId)); + AdminUserDO user = randomPojo(AdminUserDO.class); + user.setId(userId); + when(adminUserService.getUser(userId)).thenReturn(user); + + // Act + UserGetResponseVO response = userSyncService.getUserById(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + assertNotNull(response.getAccount()); + assertEquals(user.getId(), response.getAccount().get("uid")); + assertEquals(user.getUsername(), response.getAccount().get("username")); + } + + @Test + void testGetUserById_NotFound() { + // Arrange + UserGetRequestVO requestVO = new UserGetRequestVO(); + Long userId = randomLongId(); + requestVO.setBimUid(String.valueOf(userId)); + when(adminUserService.getUser(userId)).thenReturn(null); + + // Act + UserGetResponseVO response = userSyncService.getUserById(requestVO); + + // Assert + assertNotNull(response); + assertEquals("500", response.getResultCode()); + assertEquals("用户不存在", response.getMessage()); + assertNull(response.getAccount()); + } + + @Test + void testGetUserById_InvalidId() { + // Arrange + UserGetRequestVO requestVO = new UserGetRequestVO(); + requestVO.setBimUid("invalid-id"); + + // Act + UserGetResponseVO response = userSyncService.getUserById(requestVO); + + // Assert + assertNotNull(response); + assertEquals("500", response.getResultCode()); + assertEquals("参数错误", response.getMessage()); + assertNull(response.getAccount()); + } + + @Test + void testListUserIds() { + // Arrange + UserListRequestVO requestVO = randomPojo(UserListRequestVO.class); + AdminUserDO user1 = randomPojo(AdminUserDO.class); + AdminUserDO user2 = randomPojo(AdminUserDO.class); + when(adminUserService.getUserListByStatus(0)).thenReturn(List.of(user1, user2)); + + // Act + UserListResponseVO response = userSyncService.listUserIds(requestVO); + + // Assert + assertNotNull(response); + assertEquals("0", response.getResultCode()); + assertEquals("success", response.getMessage()); + assertEquals(2, response.getUserIdList().size()); + assertTrue(response.getUserIdList().contains(String.valueOf(user1.getId()))); + assertTrue(response.getUserIdList().contains(String.valueOf(user2.getId()))); + } +} diff --git a/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java index 00550698..d416fed1 100644 --- a/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java @@ -127,7 +127,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { Long userId = userService.createUser(reqVO); // 断言 AdminUserDO user = userMapper.selectById(userId); - assertPojoEquals(reqVO, user, "password", "id","deptIds"); + assertPojoEquals(reqVO, user, "password", "id","deptIds","status"); assertEquals("yudaoyuanma", user.getPassword()); assertEquals(CommonStatusEnum.ENABLE.getStatus(), user.getStatus()); // 断言关联岗位 @@ -181,7 +181,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { userService.updateUser(reqVO); // 断言 AdminUserDO user = userMapper.selectById(reqVO.getId()); - assertPojoEquals(reqVO, user, "password","deptIds"); + assertPojoEquals(reqVO, user, "avatar","password","deptIds"); // 断言关联岗位 List userPosts = userPostMapper.selectListByUserId(user.getId()); assertEquals(2L, userPosts.get(0).getPostId());