From f2c238798db0e8d85e8a9ca87e371b485247d0fa Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Tue, 20 Sep 2022 14:26:15 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat(=E7=B3=BB=E7=BB=9F=E7=AE=A1=E7=90=86-?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=AE=A1=E7=90=86):=20=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=99=90=E5=88=B6=E4=BB=A5=E5=8F=8A=E8=A7=A3=E9=94=81=E7=94=A8?= =?UTF-8?q?=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/entity/AccountLockStatus.java | 13 + .../io/dataease/auth/server/AuthServer.java | 25 +- .../auth/service/AuthUserService.java | 11 + .../service/impl/AuthUserServiceImpl.java | 76 +++++ .../commons/constants/ParamConstants.java | 6 + .../controller/sys/SysUserController.java | 21 +- .../controller/sys/response/BasicInfo.java | 3 +- .../sys/response/SysUserGridResponse.java | 2 + .../system/SystemParameterService.java | 26 ++ .../main/resources/db/migration/V40__1.15.sql | 10 +- .../resources/i18n/messages_en_US.properties | 9 +- .../resources/i18n/messages_zh_CN.properties | 9 +- .../resources/i18n/messages_zh_TW.properties | 9 +- frontend/src/api/system/user.js | 13 +- frontend/src/lang/en.js | 2 + frontend/src/lang/tw.js | 2 + frontend/src/lang/zh.js | 2 + .../views/system/SysParam/BasicSetting.vue | 264 +++++++++++------- frontend/src/views/system/SysParam/index.vue | 2 +- frontend/src/views/system/user/index.vue | 35 ++- 20 files changed, 418 insertions(+), 122 deletions(-) create mode 100644 backend/src/main/java/io/dataease/auth/entity/AccountLockStatus.java diff --git a/backend/src/main/java/io/dataease/auth/entity/AccountLockStatus.java b/backend/src/main/java/io/dataease/auth/entity/AccountLockStatus.java new file mode 100644 index 0000000000..fbd62da94a --- /dev/null +++ b/backend/src/main/java/io/dataease/auth/entity/AccountLockStatus.java @@ -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; +} diff --git a/backend/src/main/java/io/dataease/auth/server/AuthServer.java b/backend/src/main/java/io/dataease/auth/server/AuthServer.java index 046015a14f..b367411469 100644 --- a/backend/src/main/java/io/dataease/auth/server/AuthServer.java +++ b/backend/src/main/java/io/dataease/auth/server/AuthServer.java @@ -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 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")); } } diff --git a/backend/src/main/java/io/dataease/auth/service/AuthUserService.java b/backend/src/main/java/io/dataease/auth/service/AuthUserService.java index d6a885b960..01eb0d0f72 100644 --- a/backend/src/main/java/io/dataease/auth/service/AuthUserService.java +++ b/backend/src/main/java/io/dataease/auth/service/AuthUserService.java @@ -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(); + } diff --git a/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java index 825dd7ff03..949a2465ca 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java @@ -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 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 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 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); + } } diff --git a/backend/src/main/java/io/dataease/commons/constants/ParamConstants.java b/backend/src/main/java/io/dataease/commons/constants/ParamConstants.java index 6eef4b8d2c..858d0fa71f 100644 --- a/backend/src/main/java/io/dataease/commons/constants/ParamConstants.java +++ b/backend/src/main/java/io/dataease/commons/constants/ParamConstants.java @@ -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; diff --git a/backend/src/main/java/io/dataease/controller/sys/SysUserController.java b/backend/src/main/java/io/dataease/controller/sys/SysUserController.java index 098834c39e..a03fad7d85 100644 --- a/backend/src/main/java/io/dataease/controller/sys/SysUserController.java +++ b/backend/src/main/java/io/dataease/controller/sys/SysUserController.java @@ -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> userGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody KeyGridRequest request) { Page page = PageHelper.startPage(goPage, pageSize, true); - return PageUtils.setPageInfo(page, sysUserService.query(request)); + List 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()); + } + } diff --git a/backend/src/main/java/io/dataease/controller/sys/response/BasicInfo.java b/backend/src/main/java/io/dataease/controller/sys/response/BasicInfo.java index 7038a03406..40e49a008c 100644 --- a/backend/src/main/java/io/dataease/controller/sys/response/BasicInfo.java +++ b/backend/src/main/java/io/dataease/controller/sys/response/BasicInfo.java @@ -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; diff --git a/backend/src/main/java/io/dataease/controller/sys/response/SysUserGridResponse.java b/backend/src/main/java/io/dataease/controller/sys/response/SysUserGridResponse.java index a38a57d0f8..976069c2ef 100644 --- a/backend/src/main/java/io/dataease/controller/sys/response/SysUserGridResponse.java +++ b/backend/src/main/java/io/dataease/controller/sys/response/SysUserGridResponse.java @@ -16,5 +16,7 @@ public class SysUserGridResponse extends SysUser { private SysUserDept dept; @ApiModelProperty("角色ID集合") private List roleIds; + @ApiModelProperty("锁定") + private Boolean locked; } diff --git a/backend/src/main/java/io/dataease/service/system/SystemParameterService.java b/backend/src/main/java/io/dataease/service/system/SystemParameterService.java index 0b70c4ccd1..e3ff651273 100644 --- a/backend/src/main/java/io/dataease/service/system/SystemParameterService.java +++ b/backend/src/main/java/io/dataease/service/system/SystemParameterService.java @@ -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 paramList = this.getParamList("basic"); List homePageList = this.getParamList("ui.openHomePage"); List marketPageList = this.getParamList("ui.openMarketPage"); + List loginLimitList = this.getParamList("loginlimit"); paramList.addAll(homePageList); paramList.addAll(marketPageList); + paramList.addAll(loginLimitList); BasicInfo result = new BasicInfo(); result.setOpenHomePage("true"); + Map 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; diff --git a/backend/src/main/resources/db/migration/V40__1.15.sql b/backend/src/main/resources/db/migration/V40__1.15.sql index 37325010ad..97ef1b647b 100644 --- a/backend/src/main/resources/db/migration/V40__1.15.sql +++ b/backend/src/main/resources/db/migration/V40__1.15.sql @@ -67,4 +67,12 @@ ALTER TABLE `sys_task_email` ALTER TABLE `sys_task_email` - ADD COLUMN `reci_users` varchar(255) NULL COMMENT '接收人账号' AFTER `conditions`; \ No newline at end of file + 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; \ No newline at end of file diff --git a/backend/src/main/resources/i18n/messages_en_US.properties b/backend/src/main/resources/i18n/messages_en_US.properties index 034bab0a46..054d6108ae 100644 --- a/backend/src/main/resources/i18n/messages_en_US.properties +++ b/backend/src/main/resources/i18n/messages_en_US.properties @@ -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 \ No newline at end of file +I18N_DS_INVALID_TABLE=Datasource has invalid tables + + +I18N_ACCOUNT_LOCKED=Account\u3010%s\u3011is locked\uFF01 \ No newline at end of file diff --git a/backend/src/main/resources/i18n/messages_zh_CN.properties b/backend/src/main/resources/i18n/messages_zh_CN.properties index 6aa870b885..feb7cc26af 100644 --- a/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/backend/src/main/resources/i18n/messages_zh_TW.properties b/backend/src/main/resources/i18n/messages_zh_TW.properties index d8fff127a1..f699e9a526 100644 --- a/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/frontend/src/api/system/user.js b/frontend/src/api/system/user.js index 3e4d895d24..4e4ee78512 100644 --- a/frontend/src/api/system/user.js +++ b/frontend/src/api/system/user.js @@ -9,7 +9,8 @@ const pathMap = { createPath: '/api/user/create', updatePath: '/api/user/update', editPasswordPath: '/api/user/adminUpdatePwd', - editStatusPath: '/api/user/updateStatus' + editStatusPath: '/api/user/updateStatus', + unlockPath: '/api/user/unlock/' } export function userLists(page, size, data) { return request({ @@ -133,4 +134,12 @@ export function existLdapUsers() { }) } -export default { editPassword, delUser, editUser, addUser, userLists, editStatus, personInfo, updatePerson, updatePersonPwd, allRoles, roleGrid, ldapUsers, saveLdapUser, existLdapUsers } +export function unLock(username) { + return request({ + url: pathMap.unlockPath + username, + method: 'post', + loading: false + }) +} + +export default { editPassword, delUser, editUser, addUser, userLists, editStatus, personInfo, updatePerson, updatePersonPwd, allRoles, roleGrid, ldapUsers, saveLdapUser, existLdapUsers, unLock } diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index 87cf5a7bf2..2b5e5e2489 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -131,6 +131,8 @@ export default { default_login: 'Normal' }, commons: { + unlock: 'Unlock', + unlock_success: 'Unlock success', no_result: 'No Result', manage_member: 'Managing members', confirm_remove_cancel: 'Are you sure to delete the role?', diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index 4447e957a2..2266fd69fe 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -131,6 +131,8 @@ export default { default_login: '普通登錄' }, commons: { + unlock: '解鎖', + unlock_success: '解鎖成功', no_result: '没有找到相关内容', manage_member: '管理成員', user_confirm_remove_cancel: '確定將該用戶從角色中移除嗎?', diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index d43377e106..3923bafda2 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -131,6 +131,8 @@ export default { default_login: '普通登录' }, commons: { + unlock: '解锁', + unlock_success: '解锁成功', no_result: '没有找到相关内容', manage_member: '管理成员', confirm_remove_cancel: '确定删除该角色吗?', diff --git a/frontend/src/views/system/SysParam/BasicSetting.vue b/frontend/src/views/system/SysParam/BasicSetting.vue index 1185d9e152..365462ac0a 100644 --- a/frontend/src/views/system/SysParam/BasicSetting.vue +++ b/frontend/src/views/system/SysParam/BasicSetting.vue @@ -1,11 +1,11 @@ + slot="append" + >{{ $t('components.day') }} - + - + @@ -50,7 +65,7 @@ {{ - $t("login.default_login") + $t("login.default_login") }} LDAP OIDC @@ -62,18 +77,25 @@ {{ $t('system_parameter_setting.cas_reset') + '[/cas/reset/{adminAcount}/{adminPwd}]' }} --> - + + + {{ $t("commons.yes") }} {{ $t("commons.no") }} - + {{ $t("commons.yes") }} {{ $t("commons.no") }} @@ -84,16 +106,24 @@ \ No newline at end of file + diff --git a/frontend/src/views/dataset/add/AddExcel.vue b/frontend/src/views/dataset/add/AddExcel.vue index 81268ae966..8793376f91 100644 --- a/frontend/src/views/dataset/add/AddExcel.vue +++ b/frontend/src/views/dataset/add/AddExcel.vue @@ -1,11 +1,5 @@