feat(user): 添加找回账号和重置密码功能
- 新增通过手机号查找账号接口 (/findAccountByPhone) - 新增重置密码接口 (/resetPassword),支持密码强度校验和事务处理 - 新增检查手机号是否已注册接口 (/checkPhoneRegistered) - 在UserMapper中添加根据手机号查询账号和统计数量的方法 - 在UserService中实现账号查找和密码重置相关业务逻辑 - 添加AccountInfoResult、CheckPhoneResult等返回结果类 - 添加FindAccountByPhoneParam、ResetPasswordParam等参数类 - 更新SecurityConfig,放行新增的三个公共接口 - 完善UserMapper.xml中的SQL映射,支持跨租户查询和更新操作
This commit is contained in:
@@ -43,6 +43,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
"/api/loginByUserId",
|
"/api/loginByUserId",
|
||||||
"/api/register",
|
"/api/register",
|
||||||
"/api/superAdminRegister",
|
"/api/superAdminRegister",
|
||||||
|
"/api/findAccountByPhone",
|
||||||
|
"/api/resetPassword",
|
||||||
|
"/api/checkPhoneRegistered",
|
||||||
"/api/existence",
|
"/api/existence",
|
||||||
"/api/oss/upload",
|
"/api/oss/upload",
|
||||||
"/druid/**",
|
"/druid/**",
|
||||||
|
|||||||
@@ -33,10 +33,14 @@ import com.gxwebsoft.common.system.entity.*;
|
|||||||
import com.gxwebsoft.common.system.mapper.CompanyMapper;
|
import com.gxwebsoft.common.system.mapper.CompanyMapper;
|
||||||
import com.gxwebsoft.common.system.param.LoginParam;
|
import com.gxwebsoft.common.system.param.LoginParam;
|
||||||
import com.gxwebsoft.common.system.param.SmsCaptchaParam;
|
import com.gxwebsoft.common.system.param.SmsCaptchaParam;
|
||||||
|
import com.gxwebsoft.common.system.param.FindAccountByPhoneParam;
|
||||||
|
import com.gxwebsoft.common.system.param.ResetPasswordParam;
|
||||||
import com.gxwebsoft.common.system.param.UpdatePasswordParam;
|
import com.gxwebsoft.common.system.param.UpdatePasswordParam;
|
||||||
import com.gxwebsoft.common.system.param.UserParam;
|
import com.gxwebsoft.common.system.param.UserParam;
|
||||||
import com.gxwebsoft.common.system.result.CaptchaResult;
|
import com.gxwebsoft.common.system.result.CaptchaResult;
|
||||||
import com.gxwebsoft.common.system.result.LoginResult;
|
import com.gxwebsoft.common.system.result.LoginResult;
|
||||||
|
import com.gxwebsoft.common.system.result.AccountInfoResult;
|
||||||
|
import com.gxwebsoft.common.system.result.CheckPhoneResult;
|
||||||
import com.gxwebsoft.common.system.service.*;
|
import com.gxwebsoft.common.system.service.*;
|
||||||
import com.gxwebsoft.common.system.util.EmailTemplateUtil;
|
import com.gxwebsoft.common.system.util.EmailTemplateUtil;
|
||||||
import com.wf.captcha.SpecCaptcha;
|
import com.wf.captcha.SpecCaptcha;
|
||||||
@@ -869,4 +873,138 @@ public class MainController extends BaseController {
|
|||||||
return fail("注册失败",null);
|
return fail("注册失败",null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过手机号查找账号(找回账号功能)
|
||||||
|
*/
|
||||||
|
@Operation(summary = "通过手机号查找账号")
|
||||||
|
@PostMapping("/findAccountByPhone")
|
||||||
|
public ApiResult<?> findAccountByPhone(@RequestBody FindAccountByPhoneParam param) {
|
||||||
|
// 验证手机号
|
||||||
|
if (!CommonUtil.isValidPhoneNumber(param.getPhone())) {
|
||||||
|
return fail("请输入有效的手机号码");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证短信验证码
|
||||||
|
String key = "code:" + param.getPhone();
|
||||||
|
String cachedCode = redisUtil.get(key);
|
||||||
|
String devCode = redisUtil.get(CACHE_KEY_VERIFICATION_CODE_BY_DEV_SMS);
|
||||||
|
|
||||||
|
if (!param.getSmsCode().equals(cachedCode) && !param.getSmsCode().equals(devCode)) {
|
||||||
|
return fail("短信验证码不正确");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询该手机号下的所有账号
|
||||||
|
List<User> userList = userService.findAccountsByPhone(param.getPhone());
|
||||||
|
|
||||||
|
if (userList == null || userList.isEmpty()) {
|
||||||
|
return fail("该手机号尚未注册任何账号");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为前端需要的格式
|
||||||
|
List<AccountInfoResult> resultList = new java.util.ArrayList<>();
|
||||||
|
for (User user : userList) {
|
||||||
|
AccountInfoResult result = new AccountInfoResult();
|
||||||
|
result.setUserId(String.valueOf(user.getUserId()));
|
||||||
|
result.setTenantId(user.getTenantId());
|
||||||
|
result.setTenantName(user.getTenantName());
|
||||||
|
result.setAvatar(user.getAvatar());
|
||||||
|
result.setCreateTime(user.getCreateTime() != null ? user.getCreateTime().toString() : "");
|
||||||
|
result.setUsername(user.getUsername());
|
||||||
|
resultList.add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证码使用后删除(可选,根据业务需求决定是否删除)
|
||||||
|
// redisUtil.del(key);
|
||||||
|
|
||||||
|
return success(resultList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置密码(找回密码功能)
|
||||||
|
*/
|
||||||
|
@Operation(summary = "重置密码")
|
||||||
|
@PostMapping("/resetPassword")
|
||||||
|
@Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
|
||||||
|
public ApiResult<?> resetPassword(@RequestBody ResetPasswordParam param) {
|
||||||
|
// 验证手机号
|
||||||
|
if (!CommonUtil.isValidPhoneNumber(param.getPhone())) {
|
||||||
|
return fail("请输入有效的手机号码");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证两次密码是否一致
|
||||||
|
if (!param.getNewPassword().equals(param.getConfirmPassword())) {
|
||||||
|
return fail("两次输入的密码不一致");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证密码强度(前端已验证,后端再次验证)
|
||||||
|
if (!param.getNewPassword().matches("^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d@$!%*#?&]{8,}$")) {
|
||||||
|
return fail("密码必须至少8位,且包含字母和数字");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证短信验证码
|
||||||
|
String key = "code:" + param.getPhone();
|
||||||
|
String cachedCode = redisUtil.get(key);
|
||||||
|
String devCode = redisUtil.get(CACHE_KEY_VERIFICATION_CODE_BY_DEV_SMS);
|
||||||
|
|
||||||
|
if (!param.getSmsCode().equals(cachedCode) && !param.getSmsCode().equals(devCode)) {
|
||||||
|
return fail("短信验证码不正确");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证用户是否存在且手机号匹配
|
||||||
|
User user = userService.getByUserId(param.getUserId());
|
||||||
|
if (user == null) {
|
||||||
|
return fail("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!param.getPhone().equals(user.getPhone())) {
|
||||||
|
return fail("手机号与账号不匹配");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!param.getTenantId().equals(user.getTenantId())) {
|
||||||
|
return fail("租户信息不匹配");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置密码
|
||||||
|
boolean success = userService.resetUserPassword(param.getUserId(), param.getTenantId(), param.getNewPassword());
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
// 密码重置成功后删除验证码
|
||||||
|
redisUtil.delete(key);
|
||||||
|
|
||||||
|
// 记录登录日志(密码重置)
|
||||||
|
LoginRecord record = new LoginRecord();
|
||||||
|
record.setUsername(user.getUsername());
|
||||||
|
record.setNickname(user.getNickname());
|
||||||
|
record.setLoginType(5); // 5表示密码重置(需要在LoginRecord中定义常量)
|
||||||
|
record.setComments("密码重置成功");
|
||||||
|
record.setTenantId(user.getTenantId());
|
||||||
|
loginRecordService.save(record);
|
||||||
|
|
||||||
|
return success("密码重置成功");
|
||||||
|
} else {
|
||||||
|
return fail("密码重置失败,请稍后重试");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查手机号是否已注册(可选接口)
|
||||||
|
*/
|
||||||
|
@Operation(summary = "检查手机号是否已注册")
|
||||||
|
@GetMapping("/checkPhoneRegistered")
|
||||||
|
public ApiResult<?> checkPhoneRegistered(@RequestParam("phone") String phone) {
|
||||||
|
// 验证手机号
|
||||||
|
if (!CommonUtil.isValidPhoneNumber(phone)) {
|
||||||
|
return fail("请输入有效的手机号码");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计该手机号注册的账号数量
|
||||||
|
Integer accountCount = userService.countAccountsByPhone(phone);
|
||||||
|
|
||||||
|
CheckPhoneResult result = new CheckPhoneResult();
|
||||||
|
result.setIsRegistered(accountCount > 0);
|
||||||
|
result.setAccountCount(accountCount);
|
||||||
|
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,4 +72,22 @@ public interface UserMapper extends BaseMapper<User> {
|
|||||||
@InterceptorIgnore(tenantLine = "true")
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
User getByUserId(String userId);
|
User getByUserId(String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据手机号查询所有账号(忽略租户隔离)
|
||||||
|
*
|
||||||
|
* @param phone 手机号
|
||||||
|
* @return List<User>
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
List<User> selectAccountsByPhone(@Param("phone") String phone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据手机号统计账号数量(忽略租户隔离)
|
||||||
|
*
|
||||||
|
* @param phone 手机号
|
||||||
|
* @return Integer
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
Integer countByPhone(@Param("phone") String phone);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,10 +281,32 @@
|
|||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 更新用户信息 -->
|
<!-- 更新用户信息(忽略租户隔离) -->
|
||||||
<update id="updateByUserId">
|
<update id="updateByUserId">
|
||||||
UPDATE sys_user
|
UPDATE sys_user
|
||||||
SET grade_id = #{param.gradeId}
|
<set>
|
||||||
|
<if test="param.gradeId != null">
|
||||||
|
grade_id = #{param.gradeId},
|
||||||
|
</if>
|
||||||
|
<if test="param.password != null">
|
||||||
|
password = #{param.password},
|
||||||
|
</if>
|
||||||
|
<if test="param.nickname != null">
|
||||||
|
nickname = #{param.nickname},
|
||||||
|
</if>
|
||||||
|
<if test="param.avatar != null">
|
||||||
|
avatar = #{param.avatar},
|
||||||
|
</if>
|
||||||
|
<if test="param.phone != null">
|
||||||
|
phone = #{param.phone},
|
||||||
|
</if>
|
||||||
|
<if test="param.email != null">
|
||||||
|
email = #{param.email},
|
||||||
|
</if>
|
||||||
|
<if test="param.status != null">
|
||||||
|
status = #{param.status},
|
||||||
|
</if>
|
||||||
|
</set>
|
||||||
WHERE user_id = #{param.userId}
|
WHERE user_id = #{param.userId}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
@@ -327,15 +349,37 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<!-- 查询超级管理员 -->
|
<!-- 根据用户ID查询(忽略租户隔离) -->
|
||||||
<select id="getByUserId" resultType="com.gxwebsoft.common.system.entity.User">
|
<select id="getByUserId" resultType="com.gxwebsoft.common.system.entity.User">
|
||||||
SELECT a.*
|
SELECT a.*
|
||||||
FROM sys_user a
|
FROM sys_user a
|
||||||
<where>
|
<where>
|
||||||
AND a.user_id = #{userId}
|
AND a.user_id = #{userId}
|
||||||
AND a.is_admin = 1
|
|
||||||
AND a.deleted = 0
|
AND a.deleted = 0
|
||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据手机号查询所有账号(忽略租户隔离,用于找回密码) -->
|
||||||
|
<select id="selectAccountsByPhone" resultType="com.gxwebsoft.common.system.entity.User">
|
||||||
|
SELECT a.user_id,
|
||||||
|
a.tenant_id,
|
||||||
|
a.username,
|
||||||
|
a.avatar,
|
||||||
|
a.create_time,
|
||||||
|
t.tenant_name
|
||||||
|
FROM sys_user a
|
||||||
|
LEFT JOIN sys_tenant t ON a.tenant_id = t.tenant_id
|
||||||
|
WHERE a.deleted = 0
|
||||||
|
AND a.phone = #{phone}
|
||||||
|
ORDER BY a.create_time DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据手机号统计账号数量(忽略租户隔离) -->
|
||||||
|
<select id="countByPhone" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(1)
|
||||||
|
FROM sys_user
|
||||||
|
WHERE deleted = 0
|
||||||
|
AND phone = #{phone}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.gxwebsoft.common.system.param;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过手机号查找账号参数
|
||||||
|
*
|
||||||
|
* @author WebSoft
|
||||||
|
* @since 2025-12-12
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@Schema(description = "通过手机号查找账号参数")
|
||||||
|
public class FindAccountByPhoneParam implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotBlank(message = "手机号不能为空")
|
||||||
|
@Schema(description = "手机号码", required = true)
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@NotBlank(message = "短信验证码不能为空")
|
||||||
|
@Schema(description = "短信验证码", required = true)
|
||||||
|
private String smsCode;
|
||||||
|
|
||||||
|
@NotNull(message = "模板ID不能为空")
|
||||||
|
@Schema(description = "短信模板ID", required = true)
|
||||||
|
private Integer templateId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.gxwebsoft.common.system.param;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置密码参数
|
||||||
|
*
|
||||||
|
* @author WebSoft
|
||||||
|
* @since 2025-12-12
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@Schema(description = "重置密码参数")
|
||||||
|
public class ResetPasswordParam implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotBlank(message = "手机号不能为空")
|
||||||
|
@Schema(description = "手机号码", required = true)
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@NotBlank(message = "短信验证码不能为空")
|
||||||
|
@Schema(description = "短信验证码", required = true)
|
||||||
|
private String smsCode;
|
||||||
|
|
||||||
|
@NotBlank(message = "用户ID不能为空")
|
||||||
|
@Schema(description = "用户ID", required = true)
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
@NotNull(message = "租户ID不能为空")
|
||||||
|
@Schema(description = "租户ID", required = true)
|
||||||
|
private Integer tenantId;
|
||||||
|
|
||||||
|
@NotBlank(message = "新密码不能为空")
|
||||||
|
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d@$!%*#?&]{8,}$",
|
||||||
|
message = "密码必须至少8位,且包含字母和数字")
|
||||||
|
@Schema(description = "新密码(至少8位,包含字母和数字)", required = true)
|
||||||
|
private String newPassword;
|
||||||
|
|
||||||
|
@NotBlank(message = "确认密码不能为空")
|
||||||
|
@Schema(description = "确认密码", required = true)
|
||||||
|
private String confirmPassword;
|
||||||
|
|
||||||
|
@NotNull(message = "模板ID不能为空")
|
||||||
|
@Schema(description = "短信模板ID", required = true)
|
||||||
|
private Integer templateId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.gxwebsoft.common.system.result;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号信息返回结果
|
||||||
|
*
|
||||||
|
* @author WebSoft
|
||||||
|
* @since 2025-12-12
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(description = "账号信息返回结果")
|
||||||
|
public class AccountInfoResult implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "用户ID")
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
@Schema(description = "租户ID")
|
||||||
|
private Integer tenantId;
|
||||||
|
|
||||||
|
@Schema(description = "租户名称")
|
||||||
|
private String tenantName;
|
||||||
|
|
||||||
|
@Schema(description = "用户头像")
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@Schema(description = "用户名")
|
||||||
|
private String username;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.gxwebsoft.common.system.result;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查手机号返回结果
|
||||||
|
*
|
||||||
|
* @author WebSoft
|
||||||
|
* @since 2025-12-12
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(description = "检查手机号返回结果")
|
||||||
|
public class CheckPhoneResult implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "是否已注册")
|
||||||
|
private Boolean isRegistered;
|
||||||
|
|
||||||
|
@Schema(description = "账号数量")
|
||||||
|
private Integer accountCount;
|
||||||
|
}
|
||||||
@@ -129,4 +129,30 @@ public interface UserService extends IService<User>, UserDetailsService {
|
|||||||
List<User> pageAll(UserParam param);
|
List<User> pageAll(UserParam param);
|
||||||
|
|
||||||
User getByUserId(String userId);
|
User getByUserId(String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据手机号查询所有账号(忽略租户隔离)
|
||||||
|
*
|
||||||
|
* @param phone 手机号
|
||||||
|
* @return List<User>
|
||||||
|
*/
|
||||||
|
List<User> findAccountsByPhone(String phone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据手机号统计账号数量
|
||||||
|
*
|
||||||
|
* @param phone 手机号
|
||||||
|
* @return Integer
|
||||||
|
*/
|
||||||
|
Integer countAccountsByPhone(String phone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置用户密码
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param tenantId 租户ID
|
||||||
|
* @param newPassword 新密码(明文)
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
boolean resetUserPassword(String userId, Integer tenantId, String newPassword);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,4 +366,50 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
|||||||
.eq(Organization::getPark, param.getPark())
|
.eq(Organization::getPark, param.getPark())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<User> findAccountsByPhone(String phone) {
|
||||||
|
if (StrUtil.isBlank(phone)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return baseMapper.selectAccountsByPhone(phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer countAccountsByPhone(String phone) {
|
||||||
|
if (StrUtil.isBlank(phone)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return baseMapper.countByPhone(phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
|
||||||
|
public boolean resetUserPassword(String userId, Integer tenantId, String newPassword) {
|
||||||
|
if (StrUtil.isBlank(userId) || tenantId == null || StrUtil.isBlank(newPassword)) {
|
||||||
|
throw new BusinessException("参数不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先查询用户是否存在(忽略租户隔离)
|
||||||
|
User existingUser = baseMapper.getByUserId(userId);
|
||||||
|
if (existingUser == null) {
|
||||||
|
throw new BusinessException("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证租户ID是否匹配
|
||||||
|
if (!tenantId.equals(existingUser.getTenantId())) {
|
||||||
|
throw new BusinessException("租户信息不匹配");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加密新密码
|
||||||
|
String encodedPassword = encodePassword(newPassword);
|
||||||
|
|
||||||
|
// 使用跨租户更新方法
|
||||||
|
User updateUser = new User();
|
||||||
|
updateUser.setUserId(Integer.parseInt(userId));
|
||||||
|
updateUser.setPassword(encodedPassword);
|
||||||
|
baseMapper.updateByUserId(updateUser);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user