会员管理优化

master
zzy 2026-04-21 14:58:49 +08:00
parent 3acdbeeb37
commit d88a9ca74a
6 changed files with 364 additions and 20 deletions

View File

@ -1,17 +1,18 @@
package com.fjrcloud.community.module.member.dal.dataobject.user; 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.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; 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 lombok.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@ -26,12 +27,13 @@ import java.util.List;
* @author * @author
*/ */
@TableName(value = "member_user", autoResultMap = true) @TableName(value = "member_user", autoResultMap = true)
@KeySequence("member_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @KeySequence("member_user_seq")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@TenantIgnore
public class MemberUserDO extends TenantBaseDO { public class MemberUserDO extends TenantBaseDO {
// ========== 账号信息 ========== // ========== 账号信息 ==========

View File

@ -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;
}

View File

@ -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);
}
/**
* IDID
*
* @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));
}
/**
* IDID
*
* @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));
}
}

View File

@ -1,20 +1,23 @@
package com.fjrcloud.community.module.member.service.auth; package com.fjrcloud.community.module.member.service.auth;
import cn.hutool.core.lang.Assert; 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.CommonStatusEnum;
import com.fjrcloud.community.framework.common.enums.TerminalEnum; import com.fjrcloud.community.framework.common.enums.TerminalEnum;
import com.fjrcloud.community.framework.common.enums.UserTypeEnum; import com.fjrcloud.community.framework.common.enums.UserTypeEnum;
import com.fjrcloud.community.framework.common.util.monitor.TracerUtils; import com.fjrcloud.community.framework.common.util.monitor.TracerUtils;
import com.fjrcloud.community.framework.common.util.servlet.ServletUtils; 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.controller.app.auth.vo.*;
import com.fjrcloud.community.module.member.convert.auth.AuthConvert; 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.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.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.LoginLogApi;
import com.fjrcloud.community.module.system.api.logger.dto.LoginLogCreateReqDTO; 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.sms.SmsCodeApi;
import com.fjrcloud.community.module.system.api.social.SocialClientApi; import com.fjrcloud.community.module.system.api.social.SocialClientApi;
import com.fjrcloud.community.module.system.api.social.SocialUserApi; 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.*; import static com.fjrcloud.community.module.member.enums.ErrorCodeConstants.*;
/** /**
* Service * Service
* *
* @author * @author
*/ */
@ -49,22 +52,33 @@ public class MemberAuthServiceImpl implements MemberAuthService {
@Resource @Resource
private MemberUserService userService; private MemberUserService userService;
@Resource
private MemberUserTenantRelService userTenantRelService;
@Resource @Resource
private SmsCodeApi smsCodeApi; private SmsCodeApi smsCodeApi;
@Resource @Resource
private LoginLogApi loginLogApi; private LoginLogApi loginLogApi;
@Resource @Resource
private SocialUserApi socialUserApi; private SocialUserApi socialUserApi;
@Resource @Resource
private SocialClientApi socialClientApi; private SocialClientApi socialClientApi;
@Resource @Resource
private OAuth2TokenCommonApi oauth2TokenApi; private OAuth2TokenCommonApi oauth2TokenApi;
@Override @Override
public AppAuthLoginRespVO login(AppAuthLoginReqVO reqVO) { public AppAuthLoginRespVO login(AppAuthLoginReqVO reqVO) {
// 使用手机 + 密码进行登录 // 使用手机 + 密码进行登录
MemberUserDO user = login0(reqVO.getMobile(), reqVO.getPassword()); MemberUserDO user = login0(reqVO.getMobile(), reqVO.getPassword());
// 确保用户与当前租户有关联关系
ensureUserTenantRelation(user.getId());
// 如果 socialType 非空,说明需要绑定社交用户 // 如果 socialType 非空,说明需要绑定社交用户
String openid = null; String openid = null;
if (reqVO.getSocialType() != null) { if (reqVO.getSocialType() != null) {
@ -79,7 +93,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
@Override @Override
@Transactional @Transactional
public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO) { public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO) {
// 校验验证码 // 获得或创建注册用户
String userIp = getClientIP(); String userIp = getClientIP();
// smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp)); // 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); throw exception(AUTH_LOGIN_USER_DISABLED);
} }
// 确保用户与当前租户有关联关系
ensureUserTenantRelation(user.getId());
// 如果 socialType 非空,说明需要绑定社交用户 // 如果 socialType 非空,说明需要绑定社交用户
String openid = null; String openid = null;
if (reqVO.getSocialType() != null) { if (reqVO.getSocialType() != null) {
@ -107,7 +124,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
@Override @Override
@Transactional @Transactional
public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) { public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) {
// 使用 code 授权码进行登录。然后,获得绑定的用户编号 // 使用 code 授权码进行登录,获得绑定的用户编号
SocialUserRespDTO socialUser = socialUserApi.getSocialUserByCode(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), SocialUserRespDTO socialUser = socialUserApi.getSocialUserByCode(UserTypeEnum.MEMBER.getValue(), reqVO.getType(),
reqVO.getCode(), reqVO.getState()); reqVO.getCode(), reqVO.getState());
if (socialUser == null) { if (socialUser == null) {
@ -115,10 +132,10 @@ public class MemberAuthServiceImpl implements MemberAuthService {
} }
// 情况一:已绑定,直接读取用户信息 // 情况一:已绑定,直接读取用户信息
// 情况二:未绑定,注册用户 + 绑定用户
MemberUserDO user; MemberUserDO user;
if (socialUser.getUserId() != null) { if (socialUser.getUserId() != null) {
user = userService.getUser(socialUser.getUserId()); user = userService.getUser(socialUser.getUserId());
// 情况二:未绑定,注册用户 + 绑定用户
} else { } else {
user = userService.createUser(socialUser.getNickname(), socialUser.getAvatar(), getClientIP(), getTerminal()); user = userService.createUser(socialUser.getNickname(), socialUser.getAvatar(), getClientIP(), getTerminal());
socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
@ -128,6 +145,9 @@ public class MemberAuthServiceImpl implements MemberAuthService {
throw exception(USER_NOT_EXISTS); throw exception(USER_NOT_EXISTS);
} }
// 确保用户与当前租户有关联关系
ensureUserTenantRelation(user.getId());
// 创建 Token 令牌,记录登录日志 // 创建 Token 令牌,记录登录日志
return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, socialUser.getOpenid()); return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, socialUser.getOpenid());
} }
@ -139,11 +159,14 @@ public class MemberAuthServiceImpl implements MemberAuthService {
UserTypeEnum.MEMBER.getValue(), reqVO.getPhoneCode()); UserTypeEnum.MEMBER.getValue(), reqVO.getPhoneCode());
Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空"); Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空");
// 获得获得注册用户 // 获得或创建注册用户
MemberUserDO user = userService.createUserIfAbsent(phoneNumberInfo.getPurePhoneNumber(), MemberUserDO user = userService.createUserIfAbsent(phoneNumberInfo.getPurePhoneNumber(),
getClientIP(), TerminalEnum.WECHAT_MINI_PROGRAM.getTerminal()); getClientIP(), TerminalEnum.WECHAT_MINI_PROGRAM.getTerminal());
Assert.notNull(user, "获取用户失败,结果为空"); Assert.notNull(user, "获取用户失败,结果为空");
// 确保用户与当前租户有关联关系
ensureUserTenantRelation(user.getId());
// 绑定社交用户 // 绑定社交用户
String openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), String openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
SocialTypeEnum.WECHAT_MINI_PROGRAM.getType(), reqVO.getLoginCode(), reqVO.getState())); 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); 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, private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile,
LoginLogTypeEnum logType, String openid) { LoginLogTypeEnum logType, String openid) {
// 插入登陆日志 // 插入登陆日志
@ -169,23 +215,35 @@ public class MemberAuthServiceImpl implements MemberAuthService {
return socialClientApi.getAuthorizeUrl(type, UserTypeEnum.MEMBER.getValue(), redirectUri); return socialClientApi.getAuthorizeUrl(type, UserTypeEnum.MEMBER.getValue(), redirectUri);
} }
/**
* 使 +
*
* @param mobile
* @param password
* @return
*/
private MemberUserDO login0(String mobile, String password) { private MemberUserDO login0(String mobile, String password) {
final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_MOBILE; final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_MOBILE;
// 校验账号是否存在 // 校验账号是否存在
MemberUserDO user = userService.getUserByMobile(mobile); MemberUserDO user = userService.getUserByMobile(mobile);
if (user == null) { if (user == null) {
createLoginLog(null, mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); createLoginLog(null, mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
throw exception(AUTH_LOGIN_BAD_CREDENTIALS); throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
} }
// 校验密码是否正确
if (!userService.isPasswordMatch(password, user.getPassword())) { if (!userService.isPasswordMatch(password, user.getPassword())) {
createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
throw exception(AUTH_LOGIN_BAD_CREDENTIALS); throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
} }
// 校验是否禁用 // 校验是否禁用
if (CommonStatusEnum.isDisable(user.getStatus())) { if (CommonStatusEnum.isDisable(user.getStatus())) {
createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.USER_DISABLED); createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.USER_DISABLED);
throw exception(AUTH_LOGIN_USER_DISABLED); throw exception(AUTH_LOGIN_USER_DISABLED);
} }
return user; return user;
} }
@ -201,6 +259,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
reqDTO.setUserIp(getClientIP()); reqDTO.setUserIp(getClientIP());
reqDTO.setResult(loginResult.getResult()); reqDTO.setResult(loginResult.getResult());
loginLogApi.createLoginLog(reqDTO); loginLogApi.createLoginLog(reqDTO);
// 更新最后登录时间 // 更新最后登录时间
if (userId != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) { if (userId != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
userService.updateUserLogin(userId, getClientIP()); userService.updateUserLogin(userId, getClientIP());
@ -220,13 +279,14 @@ public class MemberAuthServiceImpl implements MemberAuthService {
@Override @Override
public void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO) { public void sendSmsCode(Long userId, AppAuthSmsSendReqVO reqVO) {
// 情况 1如果是修改手机场景需要校验新手机号是否已经注册,说明不能使用该手机了 // 情况 1如果是修改手机场景需要校验新手机号是否已经注册
if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene())) { if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene())) {
MemberUserDO user = userService.getUserByMobile(reqVO.getMobile()); MemberUserDO user = userService.getUserByMobile(reqVO.getMobile());
if (user != null && !Objects.equals(user.getId(), userId)) { if (user != null && !Objects.equals(user.getId(), userId)) {
throw exception(AUTH_MOBILE_USED); throw exception(AUTH_MOBILE_USED);
} }
} }
// 情况 2如果是重置密码场景需要校验手机号是存在的 // 情况 2如果是重置密码场景需要校验手机号是存在的
if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_RESET_PASSWORD.getScene())) { if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_RESET_PASSWORD.getScene())) {
MemberUserDO user = userService.getUserByMobile(reqVO.getMobile()); MemberUserDO user = userService.getUserByMobile(reqVO.getMobile());
@ -234,10 +294,10 @@ public class MemberAuthServiceImpl implements MemberAuthService {
throw exception(USER_MOBILE_NOT_EXISTS); throw exception(USER_MOBILE_NOT_EXISTS);
} }
} }
// 情况 3如果是修改密码场景需要查询手机号无需前端传递 // 情况 3如果是修改密码场景需要查询手机号无需前端传递
if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene())) { if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene())) {
MemberUserDO user = userService.getUser(userId); MemberUserDO user = userService.getUser(userId);
// TODO 芋艿:后续 member user 手机非强绑定,这块需要做下调整;
reqVO.setMobile(user.getMobile()); reqVO.setMobile(user.getMobile());
} }

View File

@ -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);
}

View File

@ -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);
}
}
}
}