feat: 支持展示并复制重置后的密码
- 账号重置接口返回本次使用的默认强密码 - 管理端新增紧凑结果弹窗与复制反馈 - 补充服务测试和中英文文案
This commit is contained in:
@@ -32,7 +32,14 @@ public interface SysAccountService extends IService<SysAccount> {
|
||||
|
||||
SysAccount getByUsername(String userKey);
|
||||
|
||||
void resetPassword(BigInteger accountId, BigInteger operatorId);
|
||||
/**
|
||||
* 将账号密码重置为系统默认强密码。
|
||||
*
|
||||
* @param accountId 账号 ID
|
||||
* @param operatorId 操作人账号 ID
|
||||
* @return 本次重置后使用的明文密码
|
||||
*/
|
||||
String resetPassword(BigInteger accountId, BigInteger operatorId);
|
||||
|
||||
SysAccountBatchActionResultVo removeBatchWithResult(Collection<BigInteger> ids);
|
||||
|
||||
|
||||
@@ -231,21 +231,30 @@ public class SysAccountServiceImpl extends ServiceImpl<SysAccountMapper, SysAcco
|
||||
return getOne(w);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将账号密码重置为系统默认强密码。
|
||||
*
|
||||
* @param accountId 账号 ID
|
||||
* @param operatorId 操作人账号 ID
|
||||
* @return 本次重置后使用的明文密码
|
||||
*/
|
||||
@Override
|
||||
public void resetPassword(BigInteger accountId, BigInteger operatorId) {
|
||||
public String resetPassword(BigInteger accountId, BigInteger operatorId) {
|
||||
SysAccount record = getById(accountId);
|
||||
if (record == null) {
|
||||
throw new BusinessException("用户不存在");
|
||||
}
|
||||
validateResetPasswordAllowed(record);
|
||||
String plainPassword = accountSecurityProperties.getDefaultResetPassword();
|
||||
SysAccount update = new SysAccount();
|
||||
update.setId(accountId);
|
||||
update.setPassword(BCrypt.hashpw(accountSecurityProperties.getDefaultResetPassword()));
|
||||
update.setPassword(BCrypt.hashpw(plainPassword));
|
||||
update.setPasswordResetRequired(true);
|
||||
update.setModified(new Date());
|
||||
update.setModifiedBy(operatorId);
|
||||
updateById(update);
|
||||
StpUtil.kickout(accountId);
|
||||
return plainPassword;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
package tech.easyflow.system.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.crypto.digest.BCrypt;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import tech.easyflow.common.constant.enums.EnumAccountType;
|
||||
import tech.easyflow.system.config.AccountSecurityProperties;
|
||||
import tech.easyflow.system.entity.SysAccount;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -51,4 +60,54 @@ public class SysAccountServiceImplTest {
|
||||
assertEquals("3", displayNameMap.get(BigInteger.valueOf(3)));
|
||||
verify(service, times(1)).list(any(QueryWrapper.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证重置密码返回实际明文,同时持久化对应密文并踢出旧登录态。
|
||||
*
|
||||
* @throws Exception 注入测试配置失败
|
||||
*/
|
||||
@Test
|
||||
public void shouldReturnPlainPasswordAfterReset() throws Exception {
|
||||
BigInteger accountId = BigInteger.valueOf(10);
|
||||
BigInteger operatorId = BigInteger.valueOf(20);
|
||||
String expectedPassword = "!Reset123";
|
||||
SysAccountServiceImpl service = spy(new SysAccountServiceImpl());
|
||||
AccountSecurityProperties properties = new AccountSecurityProperties();
|
||||
properties.setDefaultResetPassword(expectedPassword);
|
||||
properties.afterPropertiesSet();
|
||||
setField(service, "accountSecurityProperties", properties);
|
||||
|
||||
SysAccount account = new SysAccount();
|
||||
account.setId(accountId);
|
||||
account.setAccountType(EnumAccountType.NORMAL.getCode());
|
||||
doReturn(account).when(service).getById(accountId);
|
||||
doReturn(true).when(service).updateById(any(SysAccount.class));
|
||||
|
||||
try (MockedStatic<StpUtil> stp = mockStatic(StpUtil.class)) {
|
||||
String actualPassword = service.resetPassword(accountId, operatorId);
|
||||
|
||||
assertEquals(expectedPassword, actualPassword);
|
||||
ArgumentCaptor<SysAccount> updateCaptor = ArgumentCaptor.forClass(SysAccount.class);
|
||||
verify(service).updateById(updateCaptor.capture());
|
||||
SysAccount update = updateCaptor.getValue();
|
||||
assertTrue(BCrypt.checkpw(expectedPassword, update.getPassword()));
|
||||
assertEquals(Boolean.TRUE, update.getPasswordResetRequired());
|
||||
assertEquals(operatorId, update.getModifiedBy());
|
||||
stp.verify(() -> StpUtil.kickout(accountId), times(1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置测试对象的私有字段。
|
||||
*
|
||||
* @param target 目标对象
|
||||
* @param fieldName 字段名
|
||||
* @param value 字段值
|
||||
* @throws Exception 字段不存在或不可访问
|
||||
*/
|
||||
private void setField(Object target, String fieldName, Object value) throws Exception {
|
||||
Field field = SysAccountServiceImpl.class.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user