From c01d68aec83018035a15a462e1be224ef088ccb6 Mon Sep 17 00:00:00 2001 From: zzy Date: Mon, 20 Apr 2026 23:53:52 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=A7=9F=E6=88=B7=E4=BD=93?= =?UTF-8?q?=E7=B3=BB=E8=B0=83=E6=95=B4=EF=BC=8C=E7=94=A8=E6=88=B7=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E7=A7=9F=E6=88=B7=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/AuthTenantSwitchController.java | 59 +++++++++ .../admin/auth/vo/AuthLoginRespVO.java | 4 + .../admin/auth/vo/SwitchTenantReqVO.java | 15 +++ .../admin/auth/vo/TenantInfoVO.java | 24 ++++ .../usertenant/UserTenantRelController.java | 83 +++++++++++++ .../usertenant/vo/UserTenantAssignReqVO.java | 22 ++++ .../vo/UserTenantBatchAssignReqVO.java | 21 ++++ .../admin/usertenant/vo/UserTenantRespVO.java | 35 ++++++ .../dal/dataobject/user/UserTenantRelDO.java | 27 +++++ .../dal/mysql/user/UserTenantRelMapper.java | 28 +++++ .../system/enums/ErrorCodeConstants.java | 6 +- .../system/enums/logger/LoginResultEnum.java | 17 +-- .../service/auth/AdminAuthServiceImpl.java | 81 +++++++++---- .../service/user/AdminUserServiceImpl.java | 101 ++++------------ .../usertenant/UserTenantRelService.java | 21 ++++ .../usertenant/UserTenantRelServiceImpl.java | 114 ++++++++++++++++++ 16 files changed, 542 insertions(+), 116 deletions(-) create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/AuthTenantSwitchController.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/SwitchTenantReqVO.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/TenantInfoVO.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/UserTenantRelController.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantAssignReqVO.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantBatchAssignReqVO.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantRespVO.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/dal/dataobject/user/UserTenantRelDO.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/dal/mysql/user/UserTenantRelMapper.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/usertenant/UserTenantRelService.java create mode 100644 fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/usertenant/UserTenantRelServiceImpl.java diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/AuthTenantSwitchController.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/AuthTenantSwitchController.java new file mode 100644 index 0000000..6a9b0aa --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/AuthTenantSwitchController.java @@ -0,0 +1,59 @@ +package com.fjrcloud.community.module.system.controller.admin.auth; + +import com.fjrcloud.community.framework.common.enums.UserTypeEnum; +import com.fjrcloud.community.framework.common.pojo.CommonResult; +import com.fjrcloud.community.framework.tenant.core.util.TenantUtils; +import com.fjrcloud.community.module.system.controller.admin.auth.vo.SwitchTenantReqVO; +import com.fjrcloud.community.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; +import com.fjrcloud.community.module.system.dal.dataobject.user.UserTenantRelDO; +import com.fjrcloud.community.module.system.enums.ErrorCodeConstants; +import com.fjrcloud.community.module.system.enums.oauth2.OAuth2ClientConstants; +import com.fjrcloud.community.module.system.service.oauth2.OAuth2TokenService; +import com.fjrcloud.community.module.system.service.usertenant.UserTenantRelService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +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 javax.annotation.Resource; +import javax.validation.Valid; + +import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.fjrcloud.community.framework.common.pojo.CommonResult.success; +import static com.fjrcloud.community.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - 认证 - 租户切换") +@RestController +@RequestMapping("/system/auth") +@Validated +public class AuthTenantSwitchController { + + @Resource + private UserTenantRelService userTenantRelService; + + @Resource + private OAuth2TokenService oauth2TokenService; + + @PostMapping("/switch-tenant") + @Operation(summary = "切换租户") + public CommonResult switchTenant(@Valid @RequestBody SwitchTenantReqVO reqVO) { + Long userId = getLoginUserId(); + + UserTenantRelDO rel = userTenantRelService.getUserTenantRel(userId, reqVO.getTenantId()); + if (rel == null) { + throw exception(ErrorCodeConstants.USER_TENANT_REL_NOT_EXISTS); + } + + String newToken = TenantUtils.execute(reqVO.getTenantId(), () -> { + OAuth2AccessTokenDO newAccessToken = oauth2TokenService.createAccessToken( + userId, UserTypeEnum.ADMIN.getValue(), + OAuth2ClientConstants.CLIENT_ID_DEFAULT, null); + return newAccessToken.getAccessToken(); + }); + + return success(newToken); + } +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/AuthLoginRespVO.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/AuthLoginRespVO.java index a575aff..c3353d2 100644 --- a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/AuthLoginRespVO.java +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/AuthLoginRespVO.java @@ -7,6 +7,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.time.LocalDateTime; +import java.util.List; @Schema(description = "管理后台 - 登录 Response VO") @Data @@ -27,4 +28,7 @@ public class AuthLoginRespVO { @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime expiresTime; + @Schema(description = "用户可访问的租户列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List tenants; + } diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/SwitchTenantReqVO.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/SwitchTenantReqVO.java new file mode 100644 index 0000000..436be9c --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/SwitchTenantReqVO.java @@ -0,0 +1,15 @@ +package com.fjrcloud.community.module.system.controller.admin.auth.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 切换租户 Request VO") +@Data +public class SwitchTenantReqVO { + + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "租户ID不能为空") + private Long tenantId; +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/TenantInfoVO.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/TenantInfoVO.java new file mode 100644 index 0000000..a27832f --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/auth/vo/TenantInfoVO.java @@ -0,0 +1,24 @@ +package com.fjrcloud.community.module.system.controller.admin.auth.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "管理后台 - 租户信息 VO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TenantInfoVO { + + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long tenantId; + + @Schema(description = "租户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "XX小区") + private String tenantName; + + @Schema(description = "是否默认租户", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean isDefault; +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/UserTenantRelController.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/UserTenantRelController.java new file mode 100644 index 0000000..1c2e7a9 --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/UserTenantRelController.java @@ -0,0 +1,83 @@ +package com.fjrcloud.community.module.system.controller.admin.usertenant; + +import com.fjrcloud.community.framework.common.pojo.CommonResult; +import com.fjrcloud.community.module.system.controller.admin.auth.vo.TenantInfoVO; +import com.fjrcloud.community.module.system.controller.admin.usertenant.vo.UserTenantAssignReqVO; +import com.fjrcloud.community.module.system.controller.admin.usertenant.vo.UserTenantBatchAssignReqVO; +import com.fjrcloud.community.module.system.controller.admin.usertenant.vo.UserTenantRespVO; +import com.fjrcloud.community.module.system.dal.dataobject.user.UserTenantRelDO; +import com.fjrcloud.community.module.system.dal.mysql.tenant.TenantMapper; +import com.fjrcloud.community.module.system.service.usertenant.UserTenantRelService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; +import java.util.stream.Collectors; + +import static com.fjrcloud.community.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 用户租户关联") +@RestController +@RequestMapping("/system/user-tenant") +@Validated +public class UserTenantRelController { + + @Resource + private UserTenantRelService userTenantRelService; + + @Resource + private TenantMapper tenantMapper; + + @PostMapping("/assign") + @Operation(summary = "分配用户到租户") + @PreAuthorize("@ss.hasPermission('system:user-tenant:assign')") + public CommonResult assignUserToTenant(@Valid @RequestBody UserTenantAssignReqVO reqVO) { + userTenantRelService.assignUserToTenant(reqVO.getUserId(), reqVO.getTenantId(), reqVO.getIsDefault()); + return success(true); + } + + @DeleteMapping("/remove") + @Operation(summary = "移除用户租户关联") + @Parameter(name = "userId", description = "用户ID", required = true, example = "1") + @Parameter(name = "tenantId", description = "租户ID", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('system:user-tenant:remove')") + public CommonResult removeUserFromTenant(@RequestParam("userId") Long userId, + @RequestParam("tenantId") Long tenantId) { + userTenantRelService.removeUserFromTenant(userId, tenantId); + return success(true); + } + + @PostMapping("/batch-assign") + @Operation(summary = "批量分配用户到多个租户") + @PreAuthorize("@ss.hasPermission('system:user-tenant:assign')") + public CommonResult batchAssignUserToTenants(@Valid @RequestBody UserTenantBatchAssignReqVO reqVO) { + userTenantRelService.batchAssignUserToTenants(reqVO.getUserId(), reqVO.getTenantIds()); + return success(true); + } + + @GetMapping("/list-by-user") + @Operation(summary = "获取用户的租户列表") + @Parameter(name = "userId", description = "用户ID", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('system:user-tenant:query')") + public CommonResult> getUserTenants(@RequestParam("userId") Long userId) { + List tenantInfos = userTenantRelService.getUserTenants(userId); + List result = tenantInfos.stream().map(info -> { + UserTenantRelDO rel = userTenantRelService.getUserTenantRel(userId, info.getTenantId()); + return UserTenantRespVO.builder() + .id(rel != null ? rel.getId() : null) + .userId(userId) + .tenantId(info.getTenantId()) + .tenantName(info.getTenantName()) + .isDefault(info.getIsDefault()) + .createTime(rel != null ? rel.getCreateTime() : null) + .build(); + }).collect(Collectors.toList()); + return success(result); + } +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantAssignReqVO.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantAssignReqVO.java new file mode 100644 index 0000000..68a0c08 --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantAssignReqVO.java @@ -0,0 +1,22 @@ +package com.fjrcloud.community.module.system.controller.admin.usertenant.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 分配用户到租户 Request VO") +@Data +public class UserTenantAssignReqVO { + + @Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "用户ID不能为空") + private Long userId; + + @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "租户ID不能为空") + private Long tenantId; + + @Schema(description = "是否默认租户", example = "true") + private Boolean isDefault; +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantBatchAssignReqVO.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantBatchAssignReqVO.java new file mode 100644 index 0000000..cbe00c0 --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantBatchAssignReqVO.java @@ -0,0 +1,21 @@ +package com.fjrcloud.community.module.system.controller.admin.usertenant.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@Schema(description = "管理后台 - 批量分配用户到租户 Request VO") +@Data +public class UserTenantBatchAssignReqVO { + + @Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "用户ID不能为空") + private Long userId; + + @Schema(description = "租户ID列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,2,3]") + @NotEmpty(message = "租户ID列表不能为空") + private List tenantIds; +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantRespVO.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantRespVO.java new file mode 100644 index 0000000..62f0307 --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/controller/admin/usertenant/vo/UserTenantRespVO.java @@ -0,0 +1,35 @@ +package com.fjrcloud.community.module.system.controller.admin.usertenant.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 用户租户关联 Response VO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserTenantRespVO { + + @Schema(description = "关联ID", example = "1") + private Long id; + + @Schema(description = "用户ID", example = "1") + private Long userId; + + @Schema(description = "租户ID", example = "1") + private Long tenantId; + + @Schema(description = "租户名称", example = "XX小区") + private String tenantName; + + @Schema(description = "是否默认租户", example = "true") + private Boolean isDefault; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/dal/dataobject/user/UserTenantRelDO.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/dal/dataobject/user/UserTenantRelDO.java new file mode 100644 index 0000000..33b2745 --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/dal/dataobject/user/UserTenantRelDO.java @@ -0,0 +1,27 @@ +package com.fjrcloud.community.module.system.dal.dataobject.user; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fjrcloud.community.framework.mybatis.core.dataobject.BaseDO; +import lombok.*; + +@TableName("system_user_tenant_rel") +@KeySequence("system_user_tenant_rel_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserTenantRelDO extends BaseDO { + + @TableId + private Long id; + + private Long userId; + + private Long tenantId; + + private Boolean defaultTenant; +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/dal/mysql/user/UserTenantRelMapper.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/dal/mysql/user/UserTenantRelMapper.java new file mode 100644 index 0000000..9ebf0aa --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/dal/mysql/user/UserTenantRelMapper.java @@ -0,0 +1,28 @@ +package com.fjrcloud.community.module.system.dal.mysql.user; + +import com.fjrcloud.community.framework.mybatis.core.mapper.BaseMapperX; +import com.fjrcloud.community.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.fjrcloud.community.module.system.dal.dataobject.user.UserTenantRelDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface UserTenantRelMapper extends BaseMapperX { + + default List selectListByUserId(Long userId) { + return selectList(UserTenantRelDO::getUserId, userId); + } + + default UserTenantRelDO selectByUserIdAndTenantId(Long userId, Long tenantId) { + return selectOne(new LambdaQueryWrapperX() + .eq(UserTenantRelDO::getUserId, userId) + .eq(UserTenantRelDO::getTenantId, tenantId)); + } + + default UserTenantRelDO selectDefaultByUserId(Long userId) { + return selectOne(new LambdaQueryWrapperX() + .eq(UserTenantRelDO::getUserId, userId) + .eq(UserTenantRelDO::getDefaultTenant, true)); + } +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/enums/ErrorCodeConstants.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/enums/ErrorCodeConstants.java index c12ef94..9b0b76a 100644 --- a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/enums/ErrorCodeConstants.java +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/enums/ErrorCodeConstants.java @@ -44,7 +44,11 @@ public interface ErrorCodeConstants { ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用"); ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!"); ErrorCode USER_IMPORT_INIT_PASSWORD = new ErrorCode(1_002_003_009, "初始密码不能为空"); - ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_002_003_010, "该手机号尚未注册"); + ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_002_010, "手机号未注册用户"); + + ErrorCode USER_TENANT_REL_NOT_EXISTS = new ErrorCode(1_002_011, "用户没有该租户的访问权限"); + ErrorCode USER_TENANT_REL_EXISTS = new ErrorCode(1_002_012, "用户已拥有该租户的访问权限"); + ErrorCode USER_REGISTER_DISABLED = new ErrorCode(1_002_003_011, "注册功能已关闭"); // ========== 部门模块 1-002-004-000 ========== diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/enums/logger/LoginResultEnum.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/enums/logger/LoginResultEnum.java index 52232ac..586e2ec 100644 --- a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/enums/logger/LoginResultEnum.java +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/enums/logger/LoginResultEnum.java @@ -3,24 +3,19 @@ package com.fjrcloud.community.module.system.enums.logger; import lombok.AllArgsConstructor; import lombok.Getter; -/** - * 登录结果的枚举类 - */ @Getter @AllArgsConstructor public enum LoginResultEnum { - SUCCESS(0), // 成功 - BAD_CREDENTIALS(10), // 账号或密码不正确 - USER_DISABLED(20), // 用户被禁用 - CAPTCHA_NOT_FOUND(30), // 图片验证码不存在 - CAPTCHA_CODE_ERROR(31), // 图片验证码不正确 + SUCCESS(0), + BAD_CREDENTIALS(10), + USER_DISABLED(20), + CAPTCHA_NOT_FOUND(30), + CAPTCHA_CODE_ERROR(31), + TENANT_PERMISSION_DENIED(40), ; - /** - * 结果 - */ private final Integer result; } diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/auth/AdminAuthServiceImpl.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/auth/AdminAuthServiceImpl.java index a0f4370..ff8537c 100644 --- a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/auth/AdminAuthServiceImpl.java +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/auth/AdminAuthServiceImpl.java @@ -11,6 +11,8 @@ import com.fjrcloud.community.framework.common.util.object.BeanUtils; import com.fjrcloud.community.framework.common.util.servlet.ServletUtils; import com.fjrcloud.community.framework.common.util.validation.ValidationUtils; import com.fjrcloud.community.framework.datapermission.core.annotation.DataPermission; +import com.fjrcloud.community.framework.tenant.core.context.TenantContextHolder; +import com.fjrcloud.community.framework.tenant.core.util.TenantUtils; import com.fjrcloud.community.module.system.api.logger.dto.LoginLogCreateReqDTO; import com.fjrcloud.community.module.system.api.sms.SmsCodeApi; import com.fjrcloud.community.module.system.api.sms.dto.code.SmsCodeUseReqDTO; @@ -20,6 +22,7 @@ import com.fjrcloud.community.module.system.controller.admin.auth.vo.*; import com.fjrcloud.community.module.system.convert.auth.AuthConvert; import com.fjrcloud.community.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import com.fjrcloud.community.module.system.dal.dataobject.user.AdminUserDO; +import com.fjrcloud.community.module.system.dal.dataobject.user.UserTenantRelDO; import com.fjrcloud.community.module.system.enums.logger.LoginLogTypeEnum; import com.fjrcloud.community.module.system.enums.logger.LoginResultEnum; import com.fjrcloud.community.module.system.enums.oauth2.OAuth2ClientConstants; @@ -29,6 +32,7 @@ import com.fjrcloud.community.module.system.service.member.MemberService; import com.fjrcloud.community.module.system.service.oauth2.OAuth2TokenService; import com.fjrcloud.community.module.system.service.social.SocialUserService; import com.fjrcloud.community.module.system.service.user.AdminUserService; +import com.fjrcloud.community.module.system.service.usertenant.UserTenantRelService; import com.google.common.annotations.VisibleForTesting; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -38,17 +42,13 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import javax.validation.Validator; +import java.util.List; import java.util.Objects; import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.fjrcloud.community.framework.common.util.servlet.ServletUtils.getClientIP; import static com.fjrcloud.community.module.system.enums.ErrorCodeConstants.*; -/** - * Auth Service 实现类 - * - * @author 福建融云 - */ @Service @Slf4j public class AdminAuthServiceImpl implements AdminAuthService { @@ -69,12 +69,11 @@ public class AdminAuthServiceImpl implements AdminAuthService { private CaptchaService captchaService; @Resource private SmsCodeApi smsCodeApi; + @Resource + private UserTenantRelService userTenantRelService; - /** - * 验证码的开关,默认为 true - */ @Value("${fjrcloud.captcha.enable:true}") - @Setter // 为了单测:开启或者关闭验证码 + @Setter private Boolean captchaEnable; @Override @@ -112,13 +111,28 @@ public class AdminAuthServiceImpl implements AdminAuthService { socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())); } - // 创建 Token 令牌,记录登录日志 + + Long tenantId = TenantContextHolder.getTenantId(); + if (tenantId == null) { + createLoginLog(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS); + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + } + + validateUserTenantPermission(user.getId(), tenantId); + return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME); } + private void validateUserTenantPermission(Long userId, Long tenantId) { + UserTenantRelDO rel = userTenantRelService.getUserTenantRel(userId, tenantId); + if (rel == null) { + createLoginLog(userId, null, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.TENANT_PERMISSION_DENIED); + throw exception(USER_TENANT_REL_NOT_EXISTS); + } + } + @Override public void sendSmsCode(AuthSmsSendReqVO reqVO) { - // 如果是重置密码场景,需要校验图形验证码是否正确 if (Objects.equals(SmsSceneEnum.ADMIN_MEMBER_RESET_PASSWORD.getScene(), reqVO.getScene())) { ResponseModel response = doValidateCaptcha(reqVO); if (!response.isSuccess()) { @@ -145,7 +159,14 @@ public class AdminAuthServiceImpl implements AdminAuthService { throw exception(USER_NOT_EXISTS); } - // 创建 Token 令牌,记录登录日志 + Long tenantId = TenantContextHolder.getTenantId(); + if (tenantId == null) { + createLoginLog(user.getId(), reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE, LoginResultEnum.BAD_CREDENTIALS); + throw exception(AUTH_LOGIN_BAD_CREDENTIALS); + } + + validateUserTenantPermission(user.getId(), tenantId); + return createTokenAfterLoginSuccess(user.getId(), reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE); } @@ -183,7 +204,11 @@ public class AdminAuthServiceImpl implements AdminAuthService { throw exception(USER_NOT_EXISTS); } - // 创建 Token 令牌,记录登录日志 + Long tenantId = TenantContextHolder.getTenantId(); + if (tenantId != null) { + validateUserTenantPermission(user.getId(), tenantId); + } + return createTokenAfterLoginSuccess(user.getId(), user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL); } @@ -210,13 +235,25 @@ public class AdminAuthServiceImpl implements AdminAuthService { } private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) { - // 插入登陆日志 createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS); - // 创建访问令牌 - OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, getUserType().getValue(), - OAuth2ClientConstants.CLIENT_ID_DEFAULT, null); - // 构建返回结果 - return BeanUtils.toBean(accessTokenDO, AuthLoginRespVO.class); + + Long tenantId = TenantContextHolder.getTenantId(); + + OAuth2AccessTokenDO accessTokenDO; + if (tenantId != null) { + accessTokenDO = TenantUtils.execute(tenantId, () -> + oauth2TokenService.createAccessToken(userId, getUserType().getValue(), + OAuth2ClientConstants.CLIENT_ID_DEFAULT, null)); + } else { + accessTokenDO = oauth2TokenService.createAccessToken(userId, getUserType().getValue(), + OAuth2ClientConstants.CLIENT_ID_DEFAULT, null); + } + + List tenants = userTenantRelService.getUserTenants(userId); + + AuthLoginRespVO respVO = BeanUtils.toBean(accessTokenDO, AuthLoginRespVO.class); + respVO.setTenants(tenants); + return respVO; } @Override @@ -227,12 +264,10 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override public void logout(String token, Integer logType) { - // 删除访问令牌 OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.removeAccessToken(token); if (accessTokenDO == null) { return; } - // 删除成功,则记录登出日志 createLogoutLog(accessTokenDO.getUserId(), accessTokenDO.getUserType(), logType); } @@ -267,20 +302,16 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override public AuthLoginRespVO register(AuthRegisterReqVO registerReqVO) { - // 1. 校验验证码 validateCaptcha(registerReqVO); - // 2. 校验用户名是否已存在 Long userId = userService.registerUser(registerReqVO); - // 3. 创建 Token 令牌,记录登录日志 return createTokenAfterLoginSuccess(userId, registerReqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME); } @VisibleForTesting void validateCaptcha(AuthRegisterReqVO reqVO) { ResponseModel response = doValidateCaptcha(reqVO); - // 验证不通过 if (!response.isSuccess()) { throw exception(AUTH_REGISTER_CAPTCHA_CODE_ERROR, response.getRepMsg()); } diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/user/AdminUserServiceImpl.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/user/AdminUserServiceImpl.java index b82802a..83b94e6 100644 --- a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/user/AdminUserServiceImpl.java +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/user/AdminUserServiceImpl.java @@ -12,6 +12,7 @@ import com.fjrcloud.community.framework.common.util.collection.CollectionUtils; import com.fjrcloud.community.framework.common.util.object.BeanUtils; import com.fjrcloud.community.framework.common.util.validation.ValidationUtils; import com.fjrcloud.community.framework.datapermission.core.util.DataPermissionUtils; +import com.fjrcloud.community.framework.tenant.core.context.TenantContextHolder; import com.fjrcloud.community.module.infra.api.config.ConfigApi; import com.fjrcloud.community.module.system.controller.admin.auth.vo.AuthRegisterReqVO; import com.fjrcloud.community.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; @@ -30,6 +31,7 @@ import com.fjrcloud.community.module.system.service.dept.PostService; import com.fjrcloud.community.module.system.service.oauth2.OAuth2TokenService; import com.fjrcloud.community.module.system.service.permission.PermissionService; import com.fjrcloud.community.module.system.service.tenant.TenantService; +import com.fjrcloud.community.module.system.service.usertenant.UserTenantRelService; import com.google.common.annotations.VisibleForTesting; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; @@ -78,10 +80,14 @@ public class AdminUserServiceImpl implements AdminUserService { @Resource @Lazy // 延迟,避免循环依赖报错 private TenantService tenantService; + @Resource @Lazy // 懒加载,避免循环依赖 private OAuth2TokenService oauth2TokenService; + @Resource + private UserTenantRelService userTenantRelService; + @Resource private UserPostMapper userPostMapper; @@ -93,52 +99,50 @@ public class AdminUserServiceImpl implements AdminUserService { @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}", success = SYSTEM_USER_CREATE_SUCCESS) public Long createUser(UserSaveReqVO createReqVO) { - // 1.1 校验账户配合 tenantService.handleTenantInfo(tenant -> { long count = userMapper.selectCount(); if (count >= tenant.getAccountCount()) { throw exception(USER_COUNT_MAX, tenant.getAccountCount()); } }); - // 1.2 校验正确性 validateUserForCreateOrUpdate(null, createReqVO.getUsername(), createReqVO.getMobile(), createReqVO.getEmail(), createReqVO.getDeptId(), createReqVO.getPostIds()); - // 2.1 插入用户 + AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class); - user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 - user.setPassword(encodePassword(createReqVO.getPassword())); // 加密密码 + user.setStatus(CommonStatusEnum.ENABLE.getStatus()); + user.setPassword(encodePassword(createReqVO.getPassword())); userMapper.insert(user); - // 2.2 插入关联岗位 + if (CollectionUtil.isNotEmpty(user.getPostIds())) { userPostMapper.insertBatch(convertList(user.getPostIds(), postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId))); } - // 3. 记录操作日志上下文 + Long tenantId = TenantContextHolder.getTenantId(); + if (tenantId != null) { + userTenantRelService.assignUserToTenant(user.getId(), tenantId, true); + } + LogRecordContext.putVariable("user", user); return user.getId(); } @Override public Long registerUser(AuthRegisterReqVO registerReqVO) { - // 1.1 校验是否开启注册 if (ObjUtil.notEqual(configApi.getConfigValueByKey(USER_REGISTER_ENABLED_KEY), "true")) { throw exception(USER_REGISTER_DISABLED); } - // 1.2 校验账户配合 tenantService.handleTenantInfo(tenant -> { long count = userMapper.selectCount(); if (count >= tenant.getAccountCount()) { throw exception(USER_COUNT_MAX, tenant.getAccountCount()); } }); - // 1.3 校验正确性 validateUserForCreateOrUpdate(null, registerReqVO.getUsername(), null, null, null, null); - // 2. 插入用户 AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class); - user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 - user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码 + user.setStatus(CommonStatusEnum.ENABLE.getStatus()); + user.setPassword(encodePassword(registerReqVO.getPassword())); userMapper.insert(user); return user.getId(); } @@ -148,18 +152,14 @@ public class AdminUserServiceImpl implements AdminUserService { @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = SYSTEM_USER_UPDATE_SUCCESS) public void updateUser(UserSaveReqVO updateReqVO) { - updateReqVO.setPassword(null); // 特殊:此处不更新密码 - // 1. 校验正确性 + updateReqVO.setPassword(null); AdminUserDO oldUser = validateUserForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getUsername(), updateReqVO.getMobile(), updateReqVO.getEmail(), updateReqVO.getDeptId(), updateReqVO.getPostIds()); - // 2.1 更新用户 AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class); userMapper.updateById(updateObj); - // 2.2 更新岗位 updateUserPost(updateReqVO, updateObj); - // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldUser, UserSaveReqVO.class)); LogRecordContext.putVariable("user", oldUser); } @@ -167,11 +167,9 @@ public class AdminUserServiceImpl implements AdminUserService { private void updateUserPost(UserSaveReqVO reqVO, AdminUserDO updateObj) { Long userId = reqVO.getId(); Set dbPostIds = convertSet(userPostMapper.selectListByUserId(userId), UserPostDO::getPostId); - // 计算新增和删除的岗位编号 Set postIds = CollUtil.emptyIfNull(updateObj.getPostIds()); Collection createPostIds = CollUtil.subtract(postIds, dbPostIds); Collection deletePostIds = CollUtil.subtract(dbPostIds, postIds); - // 执行新增和删除。对于已经授权的岗位,不用做任何处理 if (!CollectionUtil.isEmpty(createPostIds)) { userPostMapper.insertBatch(convertList(createPostIds, postId -> new UserPostDO().setUserId(userId).setPostId(postId))); @@ -188,21 +186,17 @@ public class AdminUserServiceImpl implements AdminUserService { @Override public void updateUserProfile(Long id, UserProfileUpdateReqVO reqVO) { - // 校验正确性 validateUserExists(id); validateEmailUnique(id, reqVO.getEmail()); validateMobileUnique(id, reqVO.getMobile()); - // 执行更新 userMapper.updateById(BeanUtils.toBean(reqVO, AdminUserDO.class).setId(id)); } @Override public void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO) { - // 校验旧密码密码 validateOldPassword(id, reqVO.getOldPassword()); - // 执行更新 AdminUserDO updateObj = new AdminUserDO().setId(id); - updateObj.setPassword(encodePassword(reqVO.getNewPassword())); // 加密密码 + updateObj.setPassword(encodePassword(reqVO.getNewPassword())); userMapper.updateById(updateObj); } @@ -210,31 +204,25 @@ public class AdminUserServiceImpl implements AdminUserService { @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_PASSWORD_SUB_TYPE, bizNo = "{{#id}}", success = SYSTEM_USER_UPDATE_PASSWORD_SUCCESS) public void updateUserPassword(Long id, String password) { - // 1. 校验用户存在 AdminUserDO user = validateUserExists(id); - // 2. 更新密码 AdminUserDO updateObj = new AdminUserDO(); updateObj.setId(id); - updateObj.setPassword(encodePassword(password)); // 加密密码 + updateObj.setPassword(encodePassword(password)); userMapper.updateById(updateObj); - // 3. 记录操作日志上下文 LogRecordContext.putVariable("user", user); LogRecordContext.putVariable("newPassword", updateObj.getPassword()); } @Override public void updateUserStatus(Long id, Integer status) { - // 校验用户存在 validateUserExists(id); - // 更新状态 AdminUserDO updateObj = new AdminUserDO(); updateObj.setId(id); updateObj.setStatus(status); userMapper.updateById(updateObj); - // 如果是禁用用户,则删除其 Token 信息 if (CommonStatusEnum.isDisable(status)) { oauth2TokenService.removeAccessToken(id, UserTypeEnum.ADMIN.getValue()); } @@ -245,27 +233,20 @@ public class AdminUserServiceImpl implements AdminUserService { @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_DELETE_SUB_TYPE, bizNo = "{{#id}}", success = SYSTEM_USER_DELETE_SUCCESS) public void deleteUser(Long id) { - // 1. 校验用户存在 AdminUserDO user = validateUserExists(id); - // 2.1 删除用户 userMapper.deleteById(id); - // 2.2 删除用户关联数据 permissionService.processUserDeleted(id); - // 2.2 删除用户岗位 userPostMapper.deleteByUserId(id); - // 3. 记录操作日志上下文 LogRecordContext.putVariable("user", user); } @Override @Transactional(rollbackFor = Exception.class) public void deleteUserList(List ids) { - // 1. 批量删除用户 userMapper.deleteByIds(ids); - // 2. 批量删除用户关联数据 ids.forEach(id -> { permissionService.processUserDeleted(id); userPostMapper.deleteByUserId(id); @@ -284,7 +265,6 @@ public class AdminUserServiceImpl implements AdminUserService { @Override public PageResult getUserPage(UserPageReqVO reqVO) { - // 如果有角色编号,查询角色对应的用户编号 Set userIds = null; if (reqVO.getRoleId() != null) { userIds = permissionService.getUserRoleIdListByRoleId(singleton(reqVO.getRoleId())); @@ -293,7 +273,6 @@ public class AdminUserServiceImpl implements AdminUserService { } } - // 分页查询 return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()), userIds); } @@ -335,10 +314,8 @@ public class AdminUserServiceImpl implements AdminUserService { if (CollUtil.isEmpty(ids)) { return; } - // 获得岗位信息 List users = userMapper.selectByIds(ids); Map userMap = CollectionUtils.convertMap(users, AdminUserDO::getId); - // 校验 ids.forEach(id -> { AdminUserDO user = userMap.get(id); if (user == null) { @@ -355,36 +332,23 @@ public class AdminUserServiceImpl implements AdminUserService { return userMapper.selectListByNickname(nickname); } - /** - * 获得部门条件:查询指定部门的子部门编号们,包括自身 - * - * @param deptId 部门编号 - * @return 部门编号集合 - */ private Set getDeptCondition(Long deptId) { if (deptId == null) { return Collections.emptySet(); } Set deptIds = convertSet(deptService.getChildDeptList(deptId), DeptDO::getId); - deptIds.add(deptId); // 包括自身 + deptIds.add(deptId); return deptIds; } private AdminUserDO validateUserForCreateOrUpdate(Long id, String username, String mobile, String email, Long deptId, Set postIds) { - // 关闭数据权限,避免因为没有数据权限,查询不到数据,进而导致唯一校验不正确 return DataPermissionUtils.executeIgnore(() -> { - // 校验用户存在 AdminUserDO user = validateUserExists(id); - // 校验用户名唯一 validateUsernameUnique(id, username); - // 校验手机号唯一 validateMobileUnique(id, mobile); - // 校验邮箱唯一 validateEmailUnique(id, email); - // 校验部门处于开启状态 deptService.validateDeptList(CollectionUtils.singleton(deptId)); - // 校验岗位处于开启状态 postService.validatePostList(postIds); return user; }); @@ -411,7 +375,6 @@ public class AdminUserServiceImpl implements AdminUserService { if (user == null) { return; } - // 如果 id 为空,说明不用比较是否为相同 id 的用户 if (id == null) { throw exception(USER_USERNAME_EXISTS); } @@ -429,7 +392,6 @@ public class AdminUserServiceImpl implements AdminUserService { if (user == null) { return; } - // 如果 id 为空,说明不用比较是否为相同 id 的用户 if (id == null) { throw exception(USER_EMAIL_EXISTS); } @@ -447,7 +409,6 @@ public class AdminUserServiceImpl implements AdminUserService { if (user == null) { return; } - // 如果 id 为空,说明不用比较是否为相同 id 的用户 if (id == null) { throw exception(USER_MOBILE_EXISTS); } @@ -456,11 +417,6 @@ public class AdminUserServiceImpl implements AdminUserService { } } - /** - * 校验旧密码 - * @param id 用户 id - * @param oldPassword 旧密码 - */ @VisibleForTesting void validateOldPassword(Long id, String oldPassword) { AdminUserDO user = userMapper.selectById(id); @@ -473,25 +429,21 @@ public class AdminUserServiceImpl implements AdminUserService { } @Override - @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 + @Transactional(rollbackFor = Exception.class) public UserImportRespVO importUserList(List importUsers, boolean isUpdateSupport) { - // 1.1 参数校验 if (CollUtil.isEmpty(importUsers)) { throw exception(USER_IMPORT_LIST_IS_EMPTY); } - // 1.2 初始化密码不能为空 String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY); if (StrUtil.isEmpty(initPassword)) { throw exception(USER_IMPORT_INIT_PASSWORD); } - // 2. 遍历,逐个创建 or 更新 UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>()) .updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build(); AtomicInteger index = new AtomicInteger(1); importUsers.forEach(importUser -> { int currentIndex = index.getAndIncrement(); - // 2.1.1 校验字段是否符合要求 try { ValidationUtils.validate(BeanUtils.toBean(importUser, UserSaveReqVO.class).setPassword(initPassword)); } catch (ConstraintViolationException ex) { @@ -499,7 +451,6 @@ public class AdminUserServiceImpl implements AdminUserService { respVO.getFailureUsernames().put(key, ex.getMessage()); return; } - // 2.1.2 校验,判断是否有不符合的原因 try { validateUserForCreateOrUpdate(null, null, importUser.getMobile(), importUser.getEmail(), importUser.getDeptId(), null); @@ -508,7 +459,6 @@ public class AdminUserServiceImpl implements AdminUserService { return; } - // 2.2.1 判断如果不存在,在进行插入 AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername()); if (existUser == null) { userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class) @@ -516,7 +466,6 @@ public class AdminUserServiceImpl implements AdminUserService { respVO.getCreateUsernames().add(importUser.getUsername()); return; } - // 2.2.2 如果存在,判断是否允许更新 if (!isUpdateSupport) { respVO.getFailureUsernames().put(importUser.getUsername(), USER_USERNAME_EXISTS.getMsg()); return; @@ -539,12 +488,6 @@ public class AdminUserServiceImpl implements AdminUserService { return passwordEncoder.matches(rawPassword, encodedPassword); } - /** - * 对密码进行加密 - * - * @param password 密码 - * @return 加密后的密码 - */ private String encodePassword(String password) { return passwordEncoder.encode(password); } diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/usertenant/UserTenantRelService.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/usertenant/UserTenantRelService.java new file mode 100644 index 0000000..fd113ae --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/usertenant/UserTenantRelService.java @@ -0,0 +1,21 @@ +package com.fjrcloud.community.module.system.service.usertenant; + +import com.fjrcloud.community.module.system.controller.admin.auth.vo.TenantInfoVO; +import com.fjrcloud.community.module.system.dal.dataobject.user.UserTenantRelDO; + +import java.util.List; + +public interface UserTenantRelService { + + List getUserTenants(Long userId); + + UserTenantRelDO getUserTenantRel(Long userId, Long tenantId); + + UserTenantRelDO getDefaultTenant(Long userId); + + void assignUserToTenant(Long userId, Long tenantId, Boolean isDefault); + + void removeUserFromTenant(Long userId, Long tenantId); + + void batchAssignUserToTenants(Long userId, List tenantIds); +} diff --git a/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/usertenant/UserTenantRelServiceImpl.java b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/usertenant/UserTenantRelServiceImpl.java new file mode 100644 index 0000000..ffd36f6 --- /dev/null +++ b/fjrcloud-module-system/src/main/java/com/fjrcloud/community/module/system/service/usertenant/UserTenantRelServiceImpl.java @@ -0,0 +1,114 @@ +package com.fjrcloud.community.module.system.service.usertenant; + +import cn.hutool.core.collection.CollUtil; +import com.fjrcloud.community.framework.common.exception.ServiceException; +import com.fjrcloud.community.module.system.controller.admin.auth.vo.TenantInfoVO; +import com.fjrcloud.community.module.system.dal.dataobject.tenant.TenantDO; +import com.fjrcloud.community.module.system.dal.dataobject.user.UserTenantRelDO; +import com.fjrcloud.community.module.system.dal.mysql.tenant.TenantMapper; +import com.fjrcloud.community.module.system.dal.mysql.user.UserTenantRelMapper; +import com.fjrcloud.community.module.system.enums.ErrorCodeConstants; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception; + +@Service +public class UserTenantRelServiceImpl implements UserTenantRelService { + + @Resource + private UserTenantRelMapper userTenantRelMapper; + + @Resource + private TenantMapper tenantMapper; + + @Override + public List getUserTenants(Long userId) { + List rels = userTenantRelMapper.selectListByUserId(userId); + if (CollUtil.isEmpty(rels)) { + return Collections.emptyList(); + } + + return rels.stream().map(rel -> { + TenantDO tenant = tenantMapper.selectById(rel.getTenantId()); + return TenantInfoVO.builder() + .tenantId(rel.getTenantId()) + .tenantName(tenant != null ? tenant.getName() : "") + .isDefault(rel.getDefaultTenant()) + .build(); + }).collect(Collectors.toList()); + } + + @Override + public UserTenantRelDO getUserTenantRel(Long userId, Long tenantId) { + return userTenantRelMapper.selectByUserIdAndTenantId(userId, tenantId); + } + + @Override + public UserTenantRelDO getDefaultTenant(Long userId) { + return userTenantRelMapper.selectDefaultByUserId(userId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void assignUserToTenant(Long userId, Long tenantId, Boolean isDefault) { + TenantDO tenant = tenantMapper.selectById(tenantId); + if (tenant == null) { + throw exception(ErrorCodeConstants.TENANT_NOT_EXISTS); + } + + UserTenantRelDO existRel = userTenantRelMapper.selectByUserIdAndTenantId(userId, tenantId); + if (existRel != null) { + throw exception(ErrorCodeConstants.USER_TENANT_REL_EXISTS); + } + + if (Boolean.TRUE.equals(isDefault)) { + clearDefaultTenant(userId); + } + + UserTenantRelDO rel = new UserTenantRelDO(); + rel.setUserId(userId); + rel.setTenantId(tenantId); + rel.setDefaultTenant(isDefault != null ? isDefault : false); + userTenantRelMapper.insert(rel); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void removeUserFromTenant(Long userId, Long tenantId) { + UserTenantRelDO rel = userTenantRelMapper.selectByUserIdAndTenantId(userId, tenantId); + if (rel == null) { + return; + } + userTenantRelMapper.deleteById(rel.getId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void batchAssignUserToTenants(Long userId, List tenantIds) { + if (CollUtil.isEmpty(tenantIds)) { + return; + } + + for (Long tenantId : tenantIds) { + try { + assignUserToTenant(userId, tenantId, false); + } catch (ServiceException e) { + // 忽略已存在的关联 + } + } + } + + private void clearDefaultTenant(Long userId) { + UserTenantRelDO defaultRel = userTenantRelMapper.selectDefaultByUserId(userId); + if (defaultRel != null) { + defaultRel.setDefaultTenant(false); + userTenantRelMapper.updateById(defaultRel); + } + } +}