会员管理优化
parent
3acdbeeb37
commit
d88a9ca74a
|
|
@ -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 {
|
||||||
|
|
||||||
// ========== 账号信息 ==========
|
// ========== 账号信息 ==========
|
||||||
|
|
|
||||||
|
|
@ -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;
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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