会员管理优化
parent
3acdbeeb37
commit
d88a9ca74a
|
|
@ -1,17 +1,18 @@
|
|||
package com.fjrcloud.community.module.member.dal.dataobject.user;
|
||||
|
||||
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
|
||||
import com.fjrcloud.community.framework.common.enums.TerminalEnum;
|
||||
import com.fjrcloud.community.framework.ip.core.Area;
|
||||
import com.fjrcloud.community.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import com.fjrcloud.community.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.fjrcloud.community.module.member.dal.dataobject.group.MemberGroupDO;
|
||||
import com.fjrcloud.community.module.member.dal.dataobject.level.MemberLevelDO;
|
||||
import com.fjrcloud.community.module.system.enums.common.SexEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
|
||||
import com.fjrcloud.community.framework.common.enums.TerminalEnum;
|
||||
import com.fjrcloud.community.framework.ip.core.Area;
|
||||
import com.fjrcloud.community.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import com.fjrcloud.community.framework.tenant.core.aop.TenantIgnore;
|
||||
import com.fjrcloud.community.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.fjrcloud.community.module.member.dal.dataobject.group.MemberGroupDO;
|
||||
import com.fjrcloud.community.module.member.dal.dataobject.level.MemberLevelDO;
|
||||
import com.fjrcloud.community.module.system.enums.common.SexEnum;
|
||||
import lombok.*;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
|
|
@ -26,12 +27,13 @@ import java.util.List;
|
|||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "member_user", autoResultMap = true)
|
||||
@KeySequence("member_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@KeySequence("member_user_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TenantIgnore
|
||||
public class MemberUserDO extends TenantBaseDO {
|
||||
|
||||
// ========== 账号信息 ==========
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
package com.fjrcloud.community.module.member.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.*;
|
||||
|
||||
/**
|
||||
* 会员用户与租户关联表
|
||||
*
|
||||
* @author 福建融云
|
||||
*/
|
||||
@TableName("member_user_tenant_rel")
|
||||
@KeySequence("member_user_tenant_rel_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MemberUserTenantRelDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会员用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 是否为默认租户
|
||||
*/
|
||||
private Boolean defaultTenant;
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package com.fjrcloud.community.module.member.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.member.dal.dataobject.user.MemberUserTenantRelDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会员用户与租户关联 Mapper
|
||||
*
|
||||
* @author 福建融云
|
||||
*/
|
||||
@Mapper
|
||||
public interface MemberUserTenantRelMapper extends BaseMapperX<MemberUserTenantRelDO> {
|
||||
|
||||
/**
|
||||
* 根据用户ID查询关联列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 关联列表
|
||||
*/
|
||||
default List<MemberUserTenantRelDO> selectListByUserId(Long userId) {
|
||||
return selectList(MemberUserTenantRelDO::getUserId, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID和租户ID查询关联关系
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param tenantId 租户ID
|
||||
* @return 关联关系
|
||||
*/
|
||||
default MemberUserTenantRelDO selectByUserIdAndTenantId(Long userId, Long tenantId) {
|
||||
return selectOne(new LambdaQueryWrapperX<MemberUserTenantRelDO>()
|
||||
.eq(MemberUserTenantRelDO::getUserId, userId)
|
||||
.eq(MemberUserTenantRelDO::getTenantId, tenantId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID删除所有关联关系
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 删除数量
|
||||
*/
|
||||
default int deleteByUserId(Long userId) {
|
||||
return delete(new LambdaQueryWrapperX<MemberUserTenantRelDO>()
|
||||
.eq(MemberUserTenantRelDO::getUserId, userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户ID和租户ID删除关联关系
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param tenantId 租户ID
|
||||
* @return 删除数量
|
||||
*/
|
||||
default int deleteByUserIdAndTenantId(Long userId, Long tenantId) {
|
||||
return delete(new LambdaQueryWrapperX<MemberUserTenantRelDO>()
|
||||
.eq(MemberUserTenantRelDO::getUserId, userId)
|
||||
.eq(MemberUserTenantRelDO::getTenantId, tenantId));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,23 @@
|
|||
package com.fjrcloud.community.module.member.service.auth;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.fjrcloud.community.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
||||
import com.fjrcloud.community.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
|
||||
import com.fjrcloud.community.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenRespDTO;
|
||||
import com.fjrcloud.community.framework.common.enums.CommonStatusEnum;
|
||||
import com.fjrcloud.community.framework.common.enums.TerminalEnum;
|
||||
import com.fjrcloud.community.framework.common.enums.UserTypeEnum;
|
||||
import com.fjrcloud.community.framework.common.util.monitor.TracerUtils;
|
||||
import com.fjrcloud.community.framework.common.util.servlet.ServletUtils;
|
||||
import com.fjrcloud.community.framework.tenant.core.context.TenantContextHolder;
|
||||
import com.fjrcloud.community.module.member.controller.app.auth.vo.*;
|
||||
import com.fjrcloud.community.module.member.convert.auth.AuthConvert;
|
||||
import com.fjrcloud.community.module.member.dal.dataobject.user.MemberUserDO;
|
||||
import com.fjrcloud.community.module.member.dal.dataobject.user.MemberUserTenantRelDO;
|
||||
import com.fjrcloud.community.module.member.service.user.MemberUserService;
|
||||
import com.fjrcloud.community.module.member.service.user.MemberUserTenantRelService;
|
||||
import com.fjrcloud.community.module.system.api.logger.LoginLogApi;
|
||||
import com.fjrcloud.community.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
||||
import com.fjrcloud.community.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
||||
import com.fjrcloud.community.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
|
||||
import com.fjrcloud.community.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenRespDTO;
|
||||
import com.fjrcloud.community.module.system.api.sms.SmsCodeApi;
|
||||
import com.fjrcloud.community.module.system.api.social.SocialClientApi;
|
||||
import com.fjrcloud.community.module.system.api.social.SocialUserApi;
|
||||
|
|
@ -39,7 +42,7 @@ import static com.fjrcloud.community.framework.web.core.util.WebFrameworkUtils.g
|
|||
import static com.fjrcloud.community.module.member.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 会员的认证 Service 接口
|
||||
* 会员的认证 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
|
|
@ -49,22 +52,33 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
|
||||
@Resource
|
||||
private MemberUserService userService;
|
||||
|
||||
@Resource
|
||||
private MemberUserTenantRelService userTenantRelService;
|
||||
|
||||
@Resource
|
||||
private SmsCodeApi smsCodeApi;
|
||||
|
||||
@Resource
|
||||
private LoginLogApi loginLogApi;
|
||||
|
||||
@Resource
|
||||
private SocialUserApi socialUserApi;
|
||||
|
||||
@Resource
|
||||
private SocialClientApi socialClientApi;
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenCommonApi oauth2TokenApi;
|
||||
|
||||
@Override
|
||||
public AppAuthLoginRespVO login(AppAuthLoginReqVO reqVO) {
|
||||
// 使用手机 + 密码,进行登录。
|
||||
// 使用手机 + 密码进行登录
|
||||
MemberUserDO user = login0(reqVO.getMobile(), reqVO.getPassword());
|
||||
|
||||
// 确保用户与当前租户有关联关系
|
||||
ensureUserTenantRelation(user.getId());
|
||||
|
||||
// 如果 socialType 非空,说明需要绑定社交用户
|
||||
String openid = null;
|
||||
if (reqVO.getSocialType() != null) {
|
||||
|
|
@ -79,7 +93,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
@Override
|
||||
@Transactional
|
||||
public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO) {
|
||||
// 校验验证码
|
||||
// 获得或创建注册用户
|
||||
String userIp = getClientIP();
|
||||
// smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp));
|
||||
|
||||
|
|
@ -93,6 +107,9 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
throw exception(AUTH_LOGIN_USER_DISABLED);
|
||||
}
|
||||
|
||||
// 确保用户与当前租户有关联关系
|
||||
ensureUserTenantRelation(user.getId());
|
||||
|
||||
// 如果 socialType 非空,说明需要绑定社交用户
|
||||
String openid = null;
|
||||
if (reqVO.getSocialType() != null) {
|
||||
|
|
@ -107,7 +124,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
@Override
|
||||
@Transactional
|
||||
public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) {
|
||||
// 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
|
||||
// 使用 code 授权码进行登录,获得绑定的用户编号
|
||||
SocialUserRespDTO socialUser = socialUserApi.getSocialUserByCode(UserTypeEnum.MEMBER.getValue(), reqVO.getType(),
|
||||
reqVO.getCode(), reqVO.getState());
|
||||
if (socialUser == null) {
|
||||
|
|
@ -115,10 +132,10 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
}
|
||||
|
||||
// 情况一:已绑定,直接读取用户信息
|
||||
// 情况二:未绑定,注册用户 + 绑定用户
|
||||
MemberUserDO user;
|
||||
if (socialUser.getUserId() != null) {
|
||||
user = userService.getUser(socialUser.getUserId());
|
||||
// 情况二:未绑定,注册用户 + 绑定用户
|
||||
} else {
|
||||
user = userService.createUser(socialUser.getNickname(), socialUser.getAvatar(), getClientIP(), getTerminal());
|
||||
socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||
|
|
@ -128,6 +145,9 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
throw exception(USER_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 确保用户与当前租户有关联关系
|
||||
ensureUserTenantRelation(user.getId());
|
||||
|
||||
// 创建 Token 令牌,记录登录日志
|
||||
return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, socialUser.getOpenid());
|
||||
}
|
||||
|
|
@ -139,11 +159,14 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
UserTypeEnum.MEMBER.getValue(), reqVO.getPhoneCode());
|
||||
Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空");
|
||||
|
||||
// 获得获得注册用户
|
||||
// 获得或创建注册用户
|
||||
MemberUserDO user = userService.createUserIfAbsent(phoneNumberInfo.getPurePhoneNumber(),
|
||||
getClientIP(), TerminalEnum.WECHAT_MINI_PROGRAM.getTerminal());
|
||||
Assert.notNull(user, "获取用户失败,结果为空");
|
||||
|
||||
// 确保用户与当前租户有关联关系
|
||||
ensureUserTenantRelation(user.getId());
|
||||
|
||||
// 绑定社交用户
|
||||
String openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
|
||||
SocialTypeEnum.WECHAT_MINI_PROGRAM.getType(), reqVO.getLoginCode(), reqVO.getState()));
|
||||
|
|
@ -152,6 +175,29 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, openid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保用户与当前租户存在关联关系
|
||||
* 如果会员已在系统中注册但尚未在当前租户下关联,则自动创建关联
|
||||
*
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
private void ensureUserTenantRelation(Long userId) {
|
||||
// 获取当前租户ID
|
||||
Long currentTenantId = TenantContextHolder.getTenantId();
|
||||
if (currentTenantId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查用户是否已在当前租户下有关联
|
||||
MemberUserTenantRelDO rel = userTenantRelService.getUserTenantRel(userId, currentTenantId);
|
||||
|
||||
// 如果没有关联,自动创建
|
||||
if (rel == null) {
|
||||
userTenantRelService.assignUserToTenant(userId, currentTenantId, false);
|
||||
log.info("[ensureUserTenantRelation][会员({}) 自动关联租户({})]", userId, currentTenantId);
|
||||
}
|
||||
}
|
||||
|
||||
private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile,
|
||||
LoginLogTypeEnum logType, String openid) {
|
||||
// 插入登陆日志
|
||||
|
|
@ -169,23 +215,35 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
return socialClientApi.getAuthorizeUrl(type, UserTypeEnum.MEMBER.getValue(), redirectUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用手机 + 密码登录
|
||||
*
|
||||
* @param mobile 手机号
|
||||
* @param password 密码
|
||||
* @return 用户对象
|
||||
*/
|
||||
private MemberUserDO login0(String mobile, String password) {
|
||||
final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_MOBILE;
|
||||
|
||||
// 校验账号是否存在
|
||||
MemberUserDO user = userService.getUserByMobile(mobile);
|
||||
if (user == null) {
|
||||
createLoginLog(null, mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
|
||||
// 校验密码是否正确
|
||||
if (!userService.isPasswordMatch(password, user.getPassword())) {
|
||||
createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
|
||||
// 校验是否禁用
|
||||
if (CommonStatusEnum.isDisable(user.getStatus())) {
|
||||
createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.USER_DISABLED);
|
||||
throw exception(AUTH_LOGIN_USER_DISABLED);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
|
@ -201,6 +259,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
reqDTO.setUserIp(getClientIP());
|
||||
reqDTO.setResult(loginResult.getResult());
|
||||
loginLogApi.createLoginLog(reqDTO);
|
||||
|
||||
// 更新最后登录时间
|
||||
if (userId != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
|
||||
userService.updateUserLogin(userId, getClientIP());
|
||||
|
|
@ -220,13 +279,14 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
|
||||
@Override
|
||||
public void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO) {
|
||||
// 情况 1:如果是修改手机场景,需要校验新手机号是否已经注册,说明不能使用该手机了
|
||||
// 情况 1:如果是修改手机场景,需要校验新手机号是否已经注册
|
||||
if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene())) {
|
||||
MemberUserDO user = userService.getUserByMobile(reqVO.getMobile());
|
||||
if (user != null && !Objects.equals(user.getId(), userId)) {
|
||||
throw exception(AUTH_MOBILE_USED);
|
||||
}
|
||||
}
|
||||
|
||||
// 情况 2:如果是重置密码场景,需要校验手机号是存在的
|
||||
if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_RESET_PASSWORD.getScene())) {
|
||||
MemberUserDO user = userService.getUserByMobile(reqVO.getMobile());
|
||||
|
|
@ -234,10 +294,10 @@ public class MemberAuthServiceImpl implements MemberAuthService {
|
|||
throw exception(USER_MOBILE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
// 情况 3:如果是修改密码场景,需要查询手机号,无需前端传递
|
||||
if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene())) {
|
||||
MemberUserDO user = userService.getUser(userId);
|
||||
// TODO 芋艿:后续 member user 手机非强绑定,这块需要做下调整;
|
||||
reqVO.setMobile(user.getMobile());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
package com.fjrcloud.community.module.member.service.user;
|
||||
|
||||
import com.fjrcloud.community.module.member.dal.dataobject.user.MemberUserTenantRelDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会员用户与租户关联 Service 接口
|
||||
*
|
||||
* @author 福建融云
|
||||
*/
|
||||
public interface MemberUserTenantRelService {
|
||||
|
||||
/**
|
||||
* 获取用户的租户关联列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 租户关联列表
|
||||
*/
|
||||
List<MemberUserTenantRelDO> getUserTenantRels(Long userId);
|
||||
|
||||
/**
|
||||
* 获取用户在指定租户的关联关系
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param tenantId 租户ID
|
||||
* @return 关联关系
|
||||
*/
|
||||
MemberUserTenantRelDO getUserTenantRel(Long userId, Long tenantId);
|
||||
|
||||
/**
|
||||
* 将用户分配到租户
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param tenantId 租户ID
|
||||
* @param isDefault 是否为默认租户
|
||||
*/
|
||||
void assignUserToTenant(Long userId, Long tenantId, Boolean isDefault);
|
||||
|
||||
/**
|
||||
* 从租户中移除用户
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param tenantId 租户ID
|
||||
*/
|
||||
void removeUserFromTenant(Long userId, Long tenantId);
|
||||
|
||||
/**
|
||||
* 批量分配用户到多个租户(先删除再新增)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param tenantIds 租户ID列表
|
||||
*/
|
||||
void batchAssignUserToTenants(Long userId, List<Long> tenantIds);
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package com.fjrcloud.community.module.member.service.user;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.fjrcloud.community.module.member.dal.dataobject.user.MemberUserTenantRelDO;
|
||||
import com.fjrcloud.community.module.member.dal.mysql.user.MemberUserTenantRelMapper;
|
||||
import com.fjrcloud.community.module.system.dal.dataobject.tenant.TenantDO;
|
||||
import com.fjrcloud.community.module.system.dal.mysql.tenant.TenantMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static com.fjrcloud.community.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.fjrcloud.community.module.system.enums.ErrorCodeConstants.TENANT_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 会员用户与租户关联 Service 实现类
|
||||
*
|
||||
* @author 福建融云
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class MemberUserTenantRelServiceImpl implements MemberUserTenantRelService {
|
||||
|
||||
@Resource
|
||||
private MemberUserTenantRelMapper memberUserTenantRelMapper;
|
||||
|
||||
@Resource
|
||||
private TenantMapper tenantMapper;
|
||||
|
||||
@Override
|
||||
public List<MemberUserTenantRelDO> getUserTenantRels(Long userId) {
|
||||
return memberUserTenantRelMapper.selectListByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemberUserTenantRelDO getUserTenantRel(Long userId, Long tenantId) {
|
||||
return memberUserTenantRelMapper.selectByUserIdAndTenantId(userId, tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void assignUserToTenant(Long userId, Long tenantId, Boolean isDefault) {
|
||||
// 校验租户是否存在
|
||||
TenantDO tenant = tenantMapper.selectById(tenantId);
|
||||
if (tenant == null) {
|
||||
throw exception(TENANT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 检查关联是否已存在,避免重复创建
|
||||
MemberUserTenantRelDO existRel = memberUserTenantRelMapper.selectByUserIdAndTenantId(userId, tenantId);
|
||||
if (existRel != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果设置为默认租户,需要清除其他默认租户标记
|
||||
if (Boolean.TRUE.equals(isDefault)) {
|
||||
clearDefaultTenant(userId);
|
||||
}
|
||||
|
||||
// 创建新的关联关系
|
||||
MemberUserTenantRelDO rel = new MemberUserTenantRelDO();
|
||||
rel.setUserId(userId);
|
||||
rel.setTenantId(tenantId);
|
||||
rel.setDefaultTenant(isDefault != null ? isDefault : false);
|
||||
memberUserTenantRelMapper.insert(rel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void removeUserFromTenant(Long userId, Long tenantId) {
|
||||
memberUserTenantRelMapper.deleteByUserIdAndTenantId(userId, tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void batchAssignUserToTenants(Long userId, List<Long> tenantIds) {
|
||||
// 先删除该用户的所有租户关联
|
||||
memberUserTenantRelMapper.deleteByUserId(userId);
|
||||
|
||||
// 如果租户列表为空,直接返回
|
||||
if (CollUtil.isEmpty(tenantIds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 批量创建新的关联关系
|
||||
for (Long tenantId : tenantIds) {
|
||||
// 校验租户是否存在
|
||||
TenantDO tenant = tenantMapper.selectById(tenantId);
|
||||
if (tenant == null) {
|
||||
throw exception(TENANT_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 创建关联关系
|
||||
MemberUserTenantRelDO rel = new MemberUserTenantRelDO();
|
||||
rel.setUserId(userId);
|
||||
rel.setTenantId(tenantId);
|
||||
rel.setDefaultTenant(false);
|
||||
memberUserTenantRelMapper.insert(rel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除用户的默认租户标记
|
||||
*
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
private void clearDefaultTenant(Long userId) {
|
||||
List<MemberUserTenantRelDO> rels = memberUserTenantRelMapper.selectListByUserId(userId);
|
||||
for (MemberUserTenantRelDO rel : rels) {
|
||||
if (Boolean.TRUE.equals(rel.getDefaultTenant())) {
|
||||
rel.setDefaultTenant(false);
|
||||
memberUserTenantRelMapper.updateById(rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue