mirror of
https://github.com/dataease/dataease.git
synced 2026-05-20 02:58:10 +08:00
feat(系统管理-用户管理): 登录限制以及解锁用户
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package io.dataease.auth.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AccountLockStatus {
|
||||
|
||||
private Boolean locked = false;
|
||||
|
||||
private String username;
|
||||
|
||||
private Long unlockTime;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import io.dataease.auth.api.dto.CurrentRoleDto;
|
||||
import io.dataease.auth.api.dto.CurrentUserDto;
|
||||
import io.dataease.auth.api.dto.LoginDto;
|
||||
import io.dataease.auth.config.RsaProperties;
|
||||
import io.dataease.auth.entity.AccountLockStatus;
|
||||
import io.dataease.auth.entity.SysUserEntity;
|
||||
import io.dataease.auth.entity.TokenInfo;
|
||||
import io.dataease.auth.service.AuthUserService;
|
||||
@@ -67,10 +68,18 @@ public class AuthServer implements AuthApi {
|
||||
Integer loginType = loginDto.getLoginType();
|
||||
boolean isSupportLdap = authUserService.supportLdap();
|
||||
if (loginType == 1 && isSupportLdap) {
|
||||
AccountLockStatus accountLockStatus = authUserService.lockStatus(username, 1);
|
||||
if (accountLockStatus.getLocked()) {
|
||||
String msg = Translator.get("I18N_ACCOUNT_LOCKED");
|
||||
msg = String.format(msg, username);
|
||||
DataEaseException.throwException(msg);
|
||||
}
|
||||
LdapXpackService ldapXpackService = SpringContextUtil.getBean(LdapXpackService.class);
|
||||
LdapValidateRequest request = LdapValidateRequest.builder().userName(username).password(pwd).build();
|
||||
ValidateResult<XpackLdapUserEntity> validateResult = ldapXpackService.login(request);
|
||||
|
||||
if (!validateResult.isSuccess()) {
|
||||
authUserService.recordLoginFail(username, 1);
|
||||
DataEaseException.throwException(validateResult.getMsg());
|
||||
}
|
||||
XpackLdapUserEntity ldapUserEntity = validateResult.getData();
|
||||
@@ -96,20 +105,29 @@ public class AuthServer implements AuthApi {
|
||||
username = validateResult.getData().getUsername();
|
||||
}
|
||||
// 增加ldap登录方式
|
||||
AccountLockStatus accountLockStatus = authUserService.lockStatus(username, 0);
|
||||
if (accountLockStatus.getLocked()) {
|
||||
String msg = Translator.get("I18N_ACCOUNT_LOCKED");
|
||||
msg = String.format(msg, username);
|
||||
DataEaseException.throwException(msg);
|
||||
}
|
||||
|
||||
SysUserEntity user = authUserService.getUserByName(username);
|
||||
|
||||
if (ObjectUtils.isEmpty(user)) {
|
||||
DataEaseException.throwException(Translator.get("i18n_id_or_pwd_error"));
|
||||
authUserService.recordLoginFail(username, 0);
|
||||
DataEaseException.throwException(Translator.get("i18n_user_do_not_exist"));
|
||||
}
|
||||
|
||||
// 验证登录类型是否与用户类型相同
|
||||
if (!sysUserService.validateLoginType(user.getFrom(), loginType)) {
|
||||
DataEaseException.throwException(Translator.get("i18n_id_or_pwd_error"));
|
||||
authUserService.recordLoginFail(username, 0);
|
||||
DataEaseException.throwException(Translator.get("i18n_login_type_error"));
|
||||
}
|
||||
|
||||
if (user.getEnabled() == 0) {
|
||||
DataEaseException.throwException(Translator.get("i18n_id_or_pwd_error"));
|
||||
authUserService.recordLoginFail(username, 0);
|
||||
DataEaseException.throwException(Translator.get("i18n_user_is_disable"));
|
||||
}
|
||||
String realPwd = user.getPassword();
|
||||
|
||||
@@ -121,6 +139,7 @@ public class AuthServer implements AuthApi {
|
||||
pwd = CodingUtil.md5(pwd);
|
||||
|
||||
if (!StringUtils.equals(pwd, realPwd)) {
|
||||
authUserService.recordLoginFail(username, 0);
|
||||
DataEaseException.throwException(Translator.get("i18n_id_or_pwd_error"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.dataease.auth.service;
|
||||
|
||||
import io.dataease.auth.api.dto.CurrentRoleDto;
|
||||
import io.dataease.auth.entity.AccountLockStatus;
|
||||
import io.dataease.auth.entity.SysUserEntity;
|
||||
|
||||
import java.util.List;
|
||||
@@ -38,9 +39,19 @@ public interface AuthUserService {
|
||||
|
||||
Boolean supportLark();
|
||||
|
||||
Boolean supportLoginLimit();
|
||||
|
||||
Boolean pluginLoaded();
|
||||
|
||||
void checkAdmin(String uname, String pwd);
|
||||
|
||||
void recordLoginFail(String username, Integer logintype);
|
||||
|
||||
void unlockAccount(String username, Integer logintype);
|
||||
|
||||
AccountLockStatus lockStatus(String username, Integer logintype);
|
||||
|
||||
void clearAllLock();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.dataease.auth.service.impl;
|
||||
|
||||
import io.dataease.auth.api.dto.CurrentRoleDto;
|
||||
import io.dataease.auth.entity.AccountLockStatus;
|
||||
import io.dataease.auth.entity.SysUserEntity;
|
||||
import io.dataease.commons.utils.CodingUtil;
|
||||
import io.dataease.exception.DataEaseException;
|
||||
@@ -9,7 +10,10 @@ import io.dataease.auth.service.AuthUserService;
|
||||
import io.dataease.commons.constants.AuthConstants;
|
||||
import io.dataease.commons.utils.LogUtil;
|
||||
import io.dataease.i18n.Translator;
|
||||
import io.dataease.plugins.common.base.domain.SysLoginLimit;
|
||||
import io.dataease.plugins.common.base.domain.SysLoginLimitExample;
|
||||
import io.dataease.plugins.common.base.domain.SysUser;
|
||||
import io.dataease.plugins.common.base.mapper.SysLoginLimitMapper;
|
||||
import io.dataease.plugins.common.base.mapper.SysUserMapper;
|
||||
import io.dataease.plugins.common.service.PluginCommonService;
|
||||
import io.dataease.plugins.config.SpringContextUtil;
|
||||
@@ -18,9 +22,12 @@ import io.dataease.plugins.xpack.cas.service.CasXpackService;
|
||||
import io.dataease.plugins.xpack.dingtalk.service.DingtalkXpackService;
|
||||
import io.dataease.plugins.xpack.lark.service.LarkXpackService;
|
||||
import io.dataease.plugins.xpack.ldap.service.LdapXpackService;
|
||||
import io.dataease.plugins.xpack.loginlimit.dto.response.LoginLimitInfo;
|
||||
import io.dataease.plugins.xpack.loginlimit.service.LoginLimitXpackService;
|
||||
import io.dataease.plugins.xpack.oidc.service.OidcXpackService;
|
||||
|
||||
import io.dataease.plugins.xpack.wecom.service.WecomXpackService;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
@@ -46,6 +53,9 @@ public class AuthUserServiceImpl implements AuthUserService {
|
||||
@Resource
|
||||
private DynamicMenuServiceImpl dynamicMenuService;
|
||||
|
||||
@Resource
|
||||
private SysLoginLimitMapper sysLoginLimitMapper;
|
||||
|
||||
/**
|
||||
* 此处需被F2CRealm登录认证调用 也就是说每次请求都会被调用 所以最好加上缓存
|
||||
*
|
||||
@@ -196,6 +206,15 @@ public class AuthUserServiceImpl implements AuthUserService {
|
||||
return larkXpackService.isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean supportLoginLimit() {
|
||||
Map<String, LoginLimitXpackService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((LoginLimitXpackService.class));
|
||||
if (beansOfType.keySet().size() == 0) return false;
|
||||
LoginLimitXpackService loginLimitXpackService = SpringContextUtil.getBean(LoginLimitXpackService.class);
|
||||
if (ObjectUtils.isEmpty(loginLimitXpackService)) return false;
|
||||
return loginLimitXpackService.isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean pluginLoaded() {
|
||||
Map<String, PluginCommonService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((PluginCommonService.class));
|
||||
@@ -221,4 +240,61 @@ public class AuthUserServiceImpl implements AuthUserService {
|
||||
DataEaseException.throwException(Translator.get("i18n_id_or_pwd_error"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordLoginFail(String username, Integer logintype) {
|
||||
if (!supportLoginLimit()) return;
|
||||
long now = System.currentTimeMillis();
|
||||
SysLoginLimit sysLoginLimit = new SysLoginLimit();
|
||||
sysLoginLimit.setUsername(username);
|
||||
sysLoginLimit.setLoginType(logintype);
|
||||
sysLoginLimit.setRecordTime(now);
|
||||
sysLoginLimitMapper.insert(sysLoginLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlockAccount(String username, Integer logintype) {
|
||||
SysLoginLimitExample example = new SysLoginLimitExample();
|
||||
example.createCriteria().andUsernameEqualTo(username).andLoginTypeEqualTo(logintype);
|
||||
sysLoginLimitMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountLockStatus lockStatus(String username, Integer logintype) {
|
||||
AccountLockStatus accountLockStatus = new AccountLockStatus();
|
||||
accountLockStatus.setUsername(username);
|
||||
if (!supportLoginLimit()) return accountLockStatus;
|
||||
|
||||
LoginLimitXpackService loginLimitXpackService = SpringContextUtil.getBean(LoginLimitXpackService.class);
|
||||
LoginLimitInfo info = loginLimitXpackService.info();
|
||||
Integer limitTimes = info.getLimitTimes();
|
||||
Integer relieveTimes = info.getRelieveTimes();
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
long longRelieveTimes = Long.parseLong(relieveTimes.toString());
|
||||
long dividingPointTime = now - (longRelieveTimes * 60L * 1000L);
|
||||
SysLoginLimitExample example = new SysLoginLimitExample();
|
||||
example.createCriteria().andUsernameEqualTo(username).andLoginTypeEqualTo(logintype).andRecordTimeGreaterThan(dividingPointTime);
|
||||
List<SysLoginLimit> sysLoginLimits = sysLoginLimitMapper.selectByExample(example);
|
||||
if (CollectionUtils.isNotEmpty(sysLoginLimits)) {
|
||||
boolean needLock = sysLoginLimits.size() >= limitTimes;
|
||||
accountLockStatus.setLocked(needLock);
|
||||
if (needLock) {
|
||||
long unlockTime = now + (longRelieveTimes * 60L * 1000L);
|
||||
accountLockStatus.setUnlockTime(unlockTime);
|
||||
}
|
||||
|
||||
}
|
||||
example.clear();
|
||||
example.createCriteria().andUsernameEqualTo(username).andLoginTypeEqualTo(logintype).andRecordTimeLessThanOrEqualTo(dividingPointTime);
|
||||
sysLoginLimitMapper.deleteByExample(example);
|
||||
return accountLockStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllLock() {
|
||||
SysLoginLimitExample example = new SysLoginLimitExample();
|
||||
sysLoginLimitMapper.deleteByExample(example);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,12 @@ public interface ParamConstants {
|
||||
|
||||
OPEN_MARKET_PAGE("ui.openMarketPage"),
|
||||
TEMPLATE_MARKET_ULR("basic.templateMarketUlr"),
|
||||
|
||||
LOGIN_LIMIT_LIMITTIMES("loginlimit.limitTimes"),
|
||||
|
||||
LOGIN_LIMIT_RELIEVETIMES("loginlimit.relieveTimes"),
|
||||
|
||||
LOGIN_LIMIT_OPEN("loginlimit.open"),
|
||||
TEMPLATE_ACCESS_KEY("basic.templateAccessKey");
|
||||
|
||||
private String value;
|
||||
|
||||
@@ -5,6 +5,8 @@ import com.github.pagehelper.PageHelper;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import io.dataease.auth.annotation.DeLog;
|
||||
import io.dataease.auth.api.dto.CurrentUserDto;
|
||||
import io.dataease.auth.entity.AccountLockStatus;
|
||||
import io.dataease.auth.service.AuthUserService;
|
||||
import io.dataease.commons.constants.SysLogConstants;
|
||||
import io.dataease.commons.utils.BeanUtils;
|
||||
import io.dataease.controller.sys.request.KeyGridRequest;
|
||||
@@ -21,6 +23,7 @@ import io.dataease.controller.sys.request.SysUserPwdRequest;
|
||||
import io.dataease.controller.sys.request.SysUserStateRequest;
|
||||
import io.dataease.controller.sys.response.RoleUserItem;
|
||||
import io.dataease.controller.sys.response.SysUserGridResponse;
|
||||
import io.dataease.plugins.common.base.domain.SysUser;
|
||||
import io.dataease.service.sys.SysRoleService;
|
||||
import io.dataease.service.sys.SysUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -51,6 +54,9 @@ public class SysUserController {
|
||||
@Resource
|
||||
private SysRoleService sysRoleService;
|
||||
|
||||
@Resource
|
||||
private AuthUserService authUserService;
|
||||
|
||||
@ApiOperation("查询用户")
|
||||
@RequiresPermissions("user:read")
|
||||
@PostMapping("/userGrid/{goPage}/{pageSize}")
|
||||
@@ -62,7 +68,12 @@ public class SysUserController {
|
||||
public Pager<List<SysUserGridResponse>> userGrid(@PathVariable int goPage, @PathVariable int pageSize,
|
||||
@RequestBody KeyGridRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
|
||||
return PageUtils.setPageInfo(page, sysUserService.query(request));
|
||||
List<SysUserGridResponse> users = sysUserService.query(request);
|
||||
users.forEach(user -> {
|
||||
AccountLockStatus accountLockStatus = authUserService.lockStatus(user.getUsername(), user.getFrom());
|
||||
user.setLocked(accountLockStatus.getLocked());
|
||||
});
|
||||
return PageUtils.setPageInfo(page, users);
|
||||
}
|
||||
|
||||
@ApiIgnore
|
||||
@@ -207,4 +218,12 @@ public class SysUserController {
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@PostMapping("/unlock/{username}")
|
||||
public void unlock(@PathVariable("username") String username) {
|
||||
SysUser sysUser = new SysUser();
|
||||
sysUser.setUsername(username);
|
||||
SysUser one = sysUserService.findOne(sysUser);
|
||||
authUserService.unlockAccount(username, one.getFrom());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@ package io.dataease.controller.sys.response;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import io.dataease.plugins.xpack.loginlimit.dto.response.LoginLimitInfo;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BasicInfo implements Serializable {
|
||||
public class BasicInfo extends LoginLimitInfo implements Serializable {
|
||||
|
||||
@ApiModelProperty("请求超时时间")
|
||||
private String frontTimeOut;
|
||||
|
||||
@@ -16,5 +16,7 @@ public class SysUserGridResponse extends SysUser {
|
||||
private SysUserDept dept;
|
||||
@ApiModelProperty("角色ID集合")
|
||||
private List<Long> roleIds;
|
||||
@ApiModelProperty("锁定")
|
||||
private Boolean locked;
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.dataease.plugins.config.SpringContextUtil;
|
||||
import io.dataease.plugins.xpack.cas.dto.CasSaveResult;
|
||||
import io.dataease.plugins.xpack.cas.service.CasXpackService;
|
||||
import io.dataease.plugins.xpack.display.service.DisplayXpackService;
|
||||
import io.dataease.plugins.xpack.loginlimit.service.LoginLimitXpackService;
|
||||
import io.dataease.service.FileService;
|
||||
import io.dataease.service.datasource.DatasourceService;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
@@ -58,10 +59,14 @@ public class SystemParameterService {
|
||||
List<SystemParameter> paramList = this.getParamList("basic");
|
||||
List<SystemParameter> homePageList = this.getParamList("ui.openHomePage");
|
||||
List<SystemParameter> marketPageList = this.getParamList("ui.openMarketPage");
|
||||
List<SystemParameter> loginLimitList = this.getParamList("loginlimit");
|
||||
paramList.addAll(homePageList);
|
||||
paramList.addAll(marketPageList);
|
||||
paramList.addAll(loginLimitList);
|
||||
BasicInfo result = new BasicInfo();
|
||||
result.setOpenHomePage("true");
|
||||
Map<String, LoginLimitXpackService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((LoginLimitXpackService.class));
|
||||
Boolean loginLimitPluginLoaded = beansOfType.keySet().size() > 0;
|
||||
if (!CollectionUtils.isEmpty(paramList)) {
|
||||
for (SystemParameter param : paramList) {
|
||||
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.FRONT_TIME_OUT.getValue())) {
|
||||
@@ -94,6 +99,27 @@ public class SystemParameterService {
|
||||
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.DS_CHECK_INTERVAL_TYPE.getValue())) {
|
||||
result.setDsCheckIntervalType(param.getParamValue());
|
||||
}
|
||||
|
||||
|
||||
if (loginLimitPluginLoaded) {
|
||||
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.LOGIN_LIMIT_LIMITTIMES.getValue())) {
|
||||
String paramValue = param.getParamValue();
|
||||
if (StringUtils.isNotBlank(paramValue)) {
|
||||
result.setLimitTimes(Integer.parseInt(paramValue));
|
||||
}
|
||||
}
|
||||
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.LOGIN_LIMIT_RELIEVETIMES.getValue())) {
|
||||
String paramValue = param.getParamValue();
|
||||
if (StringUtils.isNotBlank(paramValue)) {
|
||||
result.setRelieveTimes(Integer.parseInt(paramValue));
|
||||
}
|
||||
}
|
||||
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.LOGIN_LIMIT_OPEN.getValue())) {
|
||||
boolean open = StringUtils.equals("true", param.getParamValue());
|
||||
result.setOpen(open ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -67,4 +67,12 @@ ALTER TABLE `sys_task_email`
|
||||
|
||||
|
||||
ALTER TABLE `sys_task_email`
|
||||
ADD COLUMN `reci_users` varchar(255) NULL COMMENT '接收人账号' AFTER `conditions`;
|
||||
ADD COLUMN `reci_users` varchar(255) NULL COMMENT '接收人账号' AFTER `conditions`;
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `sys_login_limit`;
|
||||
CREATE TABLE `sys_login_limit` (
|
||||
`login_type` int(8) NOT NULL,
|
||||
`username` varchar(255) NOT NULL,
|
||||
`record_time` bigint(13) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
|
||||
@@ -70,6 +70,10 @@ i18n_sql_not_empty=SQL can not be empty.
|
||||
i18n_datasource_not_allow_delete_msg= datasets are using this data source and cannot be deleted
|
||||
i18n_task_name_repeat=Name is used in same data set
|
||||
i18n_id_or_pwd_error=Invalid ID or password
|
||||
i18n_user_do_not_exist=User do not exist
|
||||
i18n_user_is_disable=User is disable
|
||||
i18n_login_type_error=Login type error
|
||||
i18n_account_is_locked=Account is locked
|
||||
i18n_datasource_delete=Data source is delete
|
||||
i18n_dataset_delete=Data set is deleted
|
||||
i18n_dataset_no_permission=Data set no permission
|
||||
@@ -220,4 +224,7 @@ I18N_USER_SOURCE_PWD_ERROR=Source password error
|
||||
I18N_USER_PWD_FORMAT_ERROR=Password format error
|
||||
|
||||
I18N_DS_INVALID=Datasource is invalid.
|
||||
I18N_DS_INVALID_TABLE=Datasource has invalid tables
|
||||
I18N_DS_INVALID_TABLE=Datasource has invalid tables
|
||||
|
||||
|
||||
I18N_ACCOUNT_LOCKED=Account\u3010%s\u3011is locked\uFF01
|
||||
@@ -70,6 +70,10 @@ i18n_sql_not_empty=SQL \u4E0D\u80FD\u4E3A\u7A7A
|
||||
i18n_datasource_not_allow_delete_msg= \u4E2A\u6570\u636E\u96C6\u6B63\u5728\u4F7F\u7528\u6B64\u6570\u636E\u6E90\uFF0C\u65E0\u6CD5\u5220\u9664
|
||||
i18n_task_name_repeat=\u540C\u4E00\u6570\u636E\u96C6\u4E0B\u4EFB\u52A1\u540D\u79F0\u5DF2\u88AB\u4F7F\u7528
|
||||
i18n_id_or_pwd_error=\u65E0\u6548\u7684ID\u6216\u5BC6\u7801
|
||||
i18n_user_do_not_exist=\u7528\u6237\u4E0D\u5B58\u5728
|
||||
i18n_user_is_disable=\u7528\u6237\u72B6\u6001\u65E0\u6548
|
||||
i18n_login_type_error=\u767B\u5F55\u65B9\u5F0F\u9519\u8BEF
|
||||
i18n_account_is_locked=\u8D26\u6237\u5DF2\u9501\u5B9A
|
||||
i18n_datasource_delete=\u5F53\u524D\u7528\u5230\u7684\u6570\u636E\u6E90\u5DF2\u88AB\u5220\u9664
|
||||
i18n_dataset_delete=\u5F53\u524D\u7528\u5230\u7684\u6570\u636E\u96C6\u5DF2\u88AB\u5220\u9664
|
||||
i18n_dataset_no_permission=\u5F53\u524D\u7528\u5230\u7684\u6570\u636E\u96C6\u6CA1\u6709\u6743\u9650
|
||||
@@ -220,4 +224,7 @@ I18N_USER_SOURCE_PWD_ERROR=\u539F\u59CB\u5BC6\u7801\u9519\u8BEF
|
||||
I18N_USER_PWD_FORMAT_ERROR=\u5BC6\u7801\u683C\u5F0F\u9519\u8BEF
|
||||
|
||||
I18N_DS_INVALID=\u6570\u636E\u6E90\u65E0\u6548.
|
||||
I18N_DS_INVALID_TABLE=\u6570\u636E\u6E90\u4E2D\u6709\u65E0\u6548\u7684\u8868
|
||||
I18N_DS_INVALID_TABLE=\u6570\u636E\u6E90\u4E2D\u6709\u65E0\u6548\u7684\u8868
|
||||
|
||||
|
||||
I18N_ACCOUNT_LOCKED=\u8D26\u53F7\u3010%s\u3011\u5DF2\u9501\u5B9A\uFF01
|
||||
@@ -70,6 +70,10 @@ i18n_sql_not_empty=SQL \u4E0D\u80FD\u70BA\u7A7A
|
||||
i18n_datasource_not_allow_delete_msg= \u500B\u6578\u64DA\u96C6\u6B63\u5728\u4F7F\u7528\u6B64\u6578\u64DA\u6E90\uFF0C\u7121\u6CD5\u522A\u9664
|
||||
i18n_task_name_repeat=\u540C\u4E00\u6578\u64DA\u96C6\u4E0B\u4EFB\u52D9\u540D\u7A31\u5DF2\u88AB\u4F7F\u7528
|
||||
i18n_id_or_pwd_error=\u7121\u6548\u7684ID\u6216\u5BC6\u78BC
|
||||
i18n_user_do_not_exist=\u7528\u6236\u4E0D\u5B58\u5728
|
||||
i18n_user_is_disable=\u7528\u6236\u72C0\u614B\u7121\u6548
|
||||
i18n_login_type_error=\u767B\u9304\u65B9\u5F0F\u932F\u8AA4
|
||||
i18n_account_is_locked=\u8CEC\u6236\u5DF2\u9396\u5B9A
|
||||
i18n_datasource_delete=\u7576\u524D\u7528\u5230\u7684\u6578\u64DA\u6E90\u5DF2\u88AB\u522A\u9664
|
||||
i18n_dataset_delete=\u7576\u524D\u7528\u5230\u7684\u6578\u64DA\u96C6\u5DF2\u88AB\u522A\u9664
|
||||
i18n_dataset_no_permission=\u7576\u524D\u7528\u5230\u7684\u6578\u64DA\u96C6\u6C92\u6709\u6B0A\u9650
|
||||
@@ -216,4 +220,7 @@ I18N_USER_SOURCE_PWD_ERROR=\u539F\u59CB\u5BC6\u78BC\u932F\u8AA4
|
||||
I18N_USER_PWD_FORMAT_ERROR=\u5BC6\u78BC\u683C\u5F0F\u932F\u8AA4
|
||||
|
||||
I18N_DS_INVALID=\u6578\u64DA\u6E90\u7121\u6548.
|
||||
I18N_DS_INVALID_TABLE=\u6578\u64DA\u6E90\u4E2D\u6709\u7121\u6548\u7684\u8868
|
||||
I18N_DS_INVALID_TABLE=\u6578\u64DA\u6E90\u4E2D\u6709\u7121\u6548\u7684\u8868
|
||||
|
||||
|
||||
I18N_ACCOUNT_LOCKED=\u8CEC\u865F\u3010%s\u3011\u5DF2\u9396\u5B9A\uFF01
|
||||
Reference in New Issue
Block a user