【功能新增】INFRA:增加 ConfigApi,支持参数配置的读取
parent
7fbb96b0f0
commit
b728e66282
|
@ -0,0 +1,21 @@
|
||||||
|
package cn.iocoder.yudao.module.infra.api.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.infra.enums.ApiConstants;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||||
|
@Tag(name = "RPC 服务 - 参数配置")
|
||||||
|
public interface ConfigApi {
|
||||||
|
|
||||||
|
String PREFIX = ApiConstants.PREFIX + "/config";
|
||||||
|
|
||||||
|
@GetMapping(PREFIX + "/get-value-by-key")
|
||||||
|
@Operation(summary = "根据参数键查询参数值")
|
||||||
|
CommonResult<String> getConfigValueByKey(@RequestParam("key") String key);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package cn.iocoder.yudao.module.infra.api.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
|
||||||
|
import cn.iocoder.yudao.module.infra.service.config.ConfigService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||||
|
@Validated
|
||||||
|
public class ConfigApiImpl implements ConfigApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<String> getConfigValueByKey(String key) {
|
||||||
|
ConfigDO config = configService.getConfigByKey(key);
|
||||||
|
return success(config != null ? config.getValue() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,7 +14,6 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_002_000_001, "登录失败,账号被禁用");
|
ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_002_000_001, "登录失败,账号被禁用");
|
||||||
ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_004, "验证码不正确,原因:{}");
|
ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_004, "验证码不正确,原因:{}");
|
||||||
ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定");
|
ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定");
|
||||||
ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1_002_000_006, "Token 已经过期");
|
|
||||||
ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在");
|
ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在");
|
||||||
|
|
||||||
// ========== 菜单模块 1-002-001-000 ==========
|
// ========== 菜单模块 1-002-001-000 ==========
|
||||||
|
@ -42,6 +41,7 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1_002_003_005, "用户密码校验失败");
|
ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1_002_003_005, "用户密码校验失败");
|
||||||
ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用");
|
ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用");
|
||||||
ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!");
|
ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!");
|
||||||
|
ErrorCode USER_IMPORT_INIT_PASSWORD = new ErrorCode(1_002_003_009, "初始密码不能为空");
|
||||||
|
|
||||||
// ========== 部门模块 1-002-004-000 ==========
|
// ========== 部门模块 1-002-004-000 ==========
|
||||||
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
|
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
|
||||||
|
@ -49,7 +49,6 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode DEPT_NOT_FOUND = new ErrorCode(1_002_004_002, "当前部门不存在");
|
ErrorCode DEPT_NOT_FOUND = new ErrorCode(1_002_004_002, "当前部门不存在");
|
||||||
ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1_002_004_003, "存在子部门,无法删除");
|
ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1_002_004_003, "存在子部门,无法删除");
|
||||||
ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1_002_004_004, "不能设置自己为父部门");
|
ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1_002_004_004, "不能设置自己为父部门");
|
||||||
ErrorCode DEPT_EXISTS_USER = new ErrorCode(1_002_004_005, "部门中存在员工,无法删除");
|
|
||||||
ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1_002_004_006, "部门({})不处于开启状态,不允许选择");
|
ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1_002_004_006, "部门({})不处于开启状态,不允许选择");
|
||||||
ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1_002_004_007, "不能设置自己的子部门为父部门");
|
ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1_002_004_007, "不能设置自己的子部门为父部门");
|
||||||
|
|
||||||
|
@ -96,11 +95,8 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在");
|
ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在");
|
||||||
ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1_002_014_001, "验证码已过期");
|
ErrorCode SMS_CODE_EXPIRED = new ErrorCode(1_002_014_001, "验证码已过期");
|
||||||
ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用");
|
ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用");
|
||||||
ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确");
|
|
||||||
ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量");
|
ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量");
|
||||||
ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频繁");
|
ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频繁");
|
||||||
ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用");
|
|
||||||
ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用");
|
|
||||||
|
|
||||||
// ========== 租户信息 1-002-015-000 ==========
|
// ========== 租户信息 1-002-015-000 ==========
|
||||||
ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1_002_015_000, "租户不存在");
|
ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1_002_015_000, "租户不存在");
|
||||||
|
@ -138,7 +134,6 @@ public interface ErrorCodeConstants {
|
||||||
ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1_002_021_000, "client_id 不匹配");
|
ErrorCode OAUTH2_GRANT_CLIENT_ID_MISMATCH = new ErrorCode(1_002_021_000, "client_id 不匹配");
|
||||||
ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1_002_021_001, "redirect_uri 不匹配");
|
ErrorCode OAUTH2_GRANT_REDIRECT_URI_MISMATCH = new ErrorCode(1_002_021_001, "redirect_uri 不匹配");
|
||||||
ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1_002_021_002, "state 不匹配");
|
ErrorCode OAUTH2_GRANT_STATE_MISMATCH = new ErrorCode(1_002_021_002, "state 不匹配");
|
||||||
ErrorCode OAUTH2_GRANT_CODE_NOT_EXISTS = new ErrorCode(1_002_021_003, "code 不存在");
|
|
||||||
|
|
||||||
// ========== OAuth2 授权 1-002-022-000 =========
|
// ========== OAuth2 授权 1-002-022-000 =========
|
||||||
ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1_002_022_000, "code 不存在");
|
ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1_002_022_000, "code 不存在");
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package cn.iocoder.yudao.module.system.framework.rpc.config;
|
package cn.iocoder.yudao.module.system.framework.rpc.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
|
||||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||||
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@EnableFeignClients(clients = {FileApi.class, WebSocketSenderApi.class})
|
@EnableFeignClients(clients = {FileApi.class, WebSocketSenderApi.class, ConfigApi.class})
|
||||||
public class RpcConfiguration {
|
public class RpcConfiguration {
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
|
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
|
||||||
|
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
|
||||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||||
|
@ -32,7 +33,6 @@ import com.mzt.logapi.service.impl.DiffParseFunction;
|
||||||
import com.mzt.logapi.starter.annotation.LogRecord;
|
import com.mzt.logapi.starter.annotation.LogRecord;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -57,8 +57,7 @@ import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AdminUserServiceImpl implements AdminUserService {
|
public class AdminUserServiceImpl implements AdminUserService {
|
||||||
|
|
||||||
@Value("${sys.user.init-password:yudaoyuanma}")
|
static final String USER_INIT_PASSWORD_KEY = "system.user.init-password";
|
||||||
private String userInitPassword;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private AdminUserMapper userMapper;
|
private AdminUserMapper userMapper;
|
||||||
|
@ -80,6 +79,8 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private FileApi fileApi;
|
private FileApi fileApi;
|
||||||
|
@Resource
|
||||||
|
private ConfigApi configApi;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@ -428,9 +429,17 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入
|
@Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入
|
||||||
public UserImportRespVO importUserList(List<UserImportExcelVO> importUsers, boolean isUpdateSupport) {
|
public UserImportRespVO importUserList(List<UserImportExcelVO> importUsers, boolean isUpdateSupport) {
|
||||||
|
// 1.1 参数校验
|
||||||
if (CollUtil.isEmpty(importUsers)) {
|
if (CollUtil.isEmpty(importUsers)) {
|
||||||
throw exception(USER_IMPORT_LIST_IS_EMPTY);
|
throw exception(USER_IMPORT_LIST_IS_EMPTY);
|
||||||
}
|
}
|
||||||
|
// 1.2 初始化密码不能为空
|
||||||
|
String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY).getCheckedData();
|
||||||
|
if (StrUtil.isEmpty(initPassword)) {
|
||||||
|
throw exception(USER_IMPORT_INIT_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 遍历,逐个创建 or 更新
|
||||||
UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>())
|
UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>())
|
||||||
.updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
|
.updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
|
||||||
importUsers.forEach(importUser -> {
|
importUsers.forEach(importUser -> {
|
||||||
|
@ -446,7 +455,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||||
AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername());
|
AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername());
|
||||||
if (existUser == null) {
|
if (existUser == null) {
|
||||||
userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class)
|
userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class)
|
||||||
.setPassword(encodePassword(userInitPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组
|
.setPassword(encodePassword(initPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组
|
||||||
respVO.getCreateUsernames().add(importUser.getUsername());
|
respVO.getCreateUsernames().add(importUser.getUsername());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
|
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
|
||||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||||
|
@ -26,6 +27,7 @@ import cn.iocoder.yudao.module.system.service.dept.DeptService;
|
||||||
import cn.iocoder.yudao.module.system.service.dept.PostService;
|
import cn.iocoder.yudao.module.system.service.dept.PostService;
|
||||||
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
|
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
|
||||||
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
|
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
@ -41,6 +43,7 @@ import java.util.function.Consumer;
|
||||||
|
|
||||||
import static cn.hutool.core.util.RandomUtil.randomBytes;
|
import static cn.hutool.core.util.RandomUtil.randomBytes;
|
||||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||||
|
@ -49,6 +52,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
|
import static cn.iocoder.yudao.module.system.service.user.AdminUserServiceImpl.USER_INIT_PASSWORD_KEY;
|
||||||
import static java.util.Collections.singleton;
|
import static java.util.Collections.singleton;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static org.assertj.core.util.Lists.newArrayList;
|
import static org.assertj.core.util.Lists.newArrayList;
|
||||||
|
@ -79,6 +83,14 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
|
||||||
private TenantService tenantService;
|
private TenantService tenantService;
|
||||||
@MockBean
|
@MockBean
|
||||||
private FileApi fileApi;
|
private FileApi fileApi;
|
||||||
|
@MockBean
|
||||||
|
private ConfigApi configApi;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before() {
|
||||||
|
// mock 初始化密码
|
||||||
|
when(configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY)).thenReturn(success("yudaoyuanma"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatUser_success() {
|
public void testCreatUser_success() {
|
||||||
|
|
Loading…
Reference in New Issue