Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
q4speed 2020-06-04 16:41:14 +08:00
commit 79c7ac49a6
18 changed files with 206 additions and 48 deletions

View File

@ -1,9 +1,9 @@
package io.metersphere.controller; package io.metersphere.controller;
import io.metersphere.base.domain.UserRole; import io.metersphere.base.domain.UserRole;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.request.LoginRequest; import io.metersphere.controller.request.LoginRequest;
import io.metersphere.dto.UserDTO; import io.metersphere.dto.UserDTO;
import io.metersphere.i18n.Translator;
import io.metersphere.service.UserService; import io.metersphere.service.UserService;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.SecurityUtils;
@ -64,22 +64,22 @@ public class LoginController {
// 返回 userDTO // 返回 userDTO
return ResultHolder.success(subject.getSession().getAttribute("user")); return ResultHolder.success(subject.getSession().getAttribute("user"));
} else { } else {
return ResultHolder.error("login fail"); return ResultHolder.error(Translator.get("login_fail"));
} }
} catch (ExcessiveAttemptsException e) { } catch (ExcessiveAttemptsException e) {
msg = "excessive attempts"; msg = "excessive_attempts";
} catch (LockedAccountException e) { } catch (LockedAccountException e) {
msg = "the user has been locked."; msg = "user_locked";
} catch (DisabledAccountException e) { } catch (DisabledAccountException e) {
msg = "the user has been disabled. "; msg = "user_has_been_disabled ";
} catch (ExpiredCredentialsException e) { } catch (ExpiredCredentialsException e) {
msg = "user expires. "; msg = "user_expires. ";
} catch (AuthenticationException e) { } catch (AuthenticationException e) {
msg = e.getMessage(); msg = e.getMessage();
} catch (UnauthorizedException e) { } catch (UnauthorizedException e) {
msg = "not authorized. " + e.getMessage(); msg = "not_authorized" + e.getMessage();
} }
return ResultHolder.error(msg); return ResultHolder.error(Translator.get(msg));
} }
@GetMapping(value = "/signout") @GetMapping(value = "/signout")

View File

@ -2,10 +2,7 @@ package io.metersphere.controller;
import io.metersphere.base.domain.SystemParameter; import io.metersphere.base.domain.SystemParameter;
import io.metersphere.service.SystemParameterService; import io.metersphere.service.SystemParameterService;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.HashMap; import java.util.HashMap;
@ -27,4 +24,9 @@ public class SystemParameterController {
SystemParameterService.testConnection(hashMap); SystemParameterService.testConnection(hashMap);
} }
@GetMapping("/version")
public String getVersion() {
return SystemParameterService.getVersion();
}
} }

View File

@ -83,7 +83,9 @@ public class SystemParameterService {
} catch (MessagingException e) { } catch (MessagingException e) {
MSException.throwException(Translator.get("connection_failed")); MSException.throwException(Translator.get("connection_failed"));
} }
}
public String getVersion() {
return System.getenv("MS_VERSION");
} }
} }

View File

@ -101,3 +101,7 @@ password_is_incorrect=Incorrect password
user_not_exist=user does not exist user_not_exist=user does not exist
user_has_been_disabled=the user has been disabled. user_has_been_disabled=the user has been disabled.
excessive_attempts=Excessive attempts excessive_attempts=Excessive attempts
user_locked=the user has been locked.
user_expires=user expires.
not_authorized=not authorized.
login_fail=Login fail

View File

@ -103,5 +103,9 @@ password_is_incorrect=密码不正确
user_not_exist=用户不存在: user_not_exist=用户不存在:
user_has_been_disabled=用户已被禁用 user_has_been_disabled=用户已被禁用
excessive_attempts=操作频繁 excessive_attempts=操作频繁
user_has_been_locked user_locked=用户被锁定
user_expires=用户过期
not_authorized=未经授权

View File

@ -101,3 +101,7 @@ password_is_incorrect=密碼不正確
user_not_exist=用戶不存在: user_not_exist=用戶不存在:
user_has_been_disabled.=用戶已被禁用 user_has_been_disabled.=用戶已被禁用
excessive_attempts=操作頻繁 excessive_attempts=操作頻繁
user_locked=用戶被鎖定
user_expires=用戶過期
not_authorized=未經授權。
login_fail=登入失敗

View File

@ -11,6 +11,7 @@
"@ckeditor/ckeditor5-build-classic": "^18.0.0", "@ckeditor/ckeditor5-build-classic": "^18.0.0",
"@ckeditor/ckeditor5-vue": "^1.0.1", "@ckeditor/ckeditor5-vue": "^1.0.1",
"@fortawesome/fontawesome-svg-core": "^1.2.26", "@fortawesome/fontawesome-svg-core": "^1.2.26",
"@fortawesome/free-brands-svg-icons": "^5.13.0",
"@fortawesome/free-regular-svg-icons": "^5.12.0", "@fortawesome/free-regular-svg-icons": "^5.12.0",
"@fortawesome/free-solid-svg-icons": "^5.12.0", "@fortawesome/free-solid-svg-icons": "^5.12.0",
"@fortawesome/vue-fontawesome": "^0.1.9", "@fortawesome/vue-fontawesome": "^0.1.9",

View File

@ -0,0 +1,109 @@
<template>
<el-dialog
:title="$t('commons.about_us')"
:visible.sync="dialogVisible"
width="20%">
<el-row>
<el-col >
<el-link :underline="false" :href="websiteUrl">
<img class="logo" src="../../../../assets/favicon-彩色.png"/>
</el-link>
<el-link class="url" :href="websiteUrl" >
<span>{{websiteUrl}}</span>
</el-link>
</el-col>
</el-row>
<el-row>
<el-col>
<div class="github">
<el-link :underline="false" :href="githubUrl">
<font-awesome-icon class="github-icon" :icon="['fab', 'github-square']"/>
</el-link>
</div>
<el-link class="url" :href="githubUrl">
<span>{{githubUrl}}</span>
</el-link>
</el-col>
</el-row>
<el-row>
<el-col class="version">
<span>版本:</span> &nbsp;
<span>{{version}}</span>
</el-col>
</el-row>
</el-dialog>
</template>
<script>
export default {
name: "AboutUs",
data() {
return{
dialogVisible: false,
githubUrl: 'https://github.com/metersphere/metersphere',
websiteUrl: 'https://github.com/metersphere/metersphere',
version: '1.0.1'
}
},
created() {
this.getVersion();
},
methods: {
open() {
this.dialogVisible = true;
},
getVersion() {
this.$get('/system/version', response => {
this.version = response.data;
});
}
}
}
</script>
<style scoped>
.logo {
height: 30px;
line-height: 30px;
vertical-align:middle
}
.version {
height: 30px;
line-height: 30px;
margin-left: 5px;
}
.github-icon {
font-size: 20px;
margin-left: 5px;
}
.github {
height: 30px;
width: 30px;
line-height: 30px;
display: inline-block;
}
.el-row {
margin-bottom: 3%;
}
.logo:hover{
color: deepskyblue;
}
.url {
margin-left: 5px;
}
</style>

View File

@ -7,16 +7,21 @@
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item command="personal">{{$t('commons.personal_information')}}</el-dropdown-item> <el-dropdown-item command="personal">{{$t('commons.personal_information')}}</el-dropdown-item>
<el-dropdown-item command="logout">{{$t('commons.exit_system')}}</el-dropdown-item> <el-dropdown-item command="logout">{{$t('commons.exit_system')}}</el-dropdown-item>
<el-dropdown-item command="about">{{$t('commons.about_us')}} <i class="el-icon-info"/></el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
<about-us ref="aboutUs"/>
</el-dropdown> </el-dropdown>
</template> </template>
<script> <script>
import {getCurrentUser} from "../../../../common/js/utils"; import {getCurrentUser} from "../../../../common/js/utils";
import AboutUs from "./AboutUs";
export default { export default {
name: "MsUser", name: "MsUser",
components: {AboutUs},
computed: { computed: {
currentUser: () => { currentUser: () => {
return getCurrentUser(); return getCurrentUser();
@ -35,6 +40,9 @@
window.location.href = "/login"; window.location.href = "/login";
}); });
break; break;
case "about":
this.$refs.aboutUs.open();
break;
default: default:
break; break;
} }

View File

@ -78,7 +78,7 @@
<el-form-item :label="$t('commons.phone')" prop="phone"> <el-form-item :label="$t('commons.phone')" prop="phone">
<el-input v-model="form.phone" autocomplete="off" :disabled="true"/> <el-input v-model="form.phone" autocomplete="off" :disabled="true"/>
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.role')" prop="roleIds"> <el-form-item :label="$t('commons.role')" prop="roleIds" :rules="{required: true, message: $t('role.please_choose_role'), trigger: 'change'}">
<el-select v-model="form.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width"> <el-select v-model="form.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width">
<el-option <el-option
v-for="item in form.allroles" v-for="item in form.allroles"
@ -175,7 +175,7 @@
// 使 // 使
this.$set(this.form, 'roleIds', roleIds); this.$set(this.form, 'roleIds', roleIds);
}, },
updateOrgMember() { updateOrgMember(formName) {
let param = { let param = {
id: this.form.id, id: this.form.id,
name: this.form.name, name: this.form.name,
@ -184,11 +184,15 @@
roleIds: this.form.roleIds, roleIds: this.form.roleIds,
organizationId: this.currentUser().lastOrganizationId organizationId: this.currentUser().lastOrganizationId
} }
this.$refs[formName].validate((valid) => {
if (valid) {
this.result = this.$post("/organization/member/update", param, () => { this.result = this.$post("/organization/member/update", param, () => {
this.$success(this.$t('commons.modify_success')); this.$success(this.$t('commons.modify_success'));
this.updateVisible = false; this.updateVisible = false;
this.initTableData(); this.initTableData();
}); });
}
})
}, },
del(row) { del(row) {
this.$confirm(this.$t('member.remove_member'), '', { this.$confirm(this.$t('member.remove_member'), '', {

View File

@ -125,7 +125,7 @@
<el-form-item :label="$t('commons.phone')" prop="phone"> <el-form-item :label="$t('commons.phone')" prop="phone">
<el-input v-model="memberForm.phone" autocomplete="off" :disabled="true"/> <el-input v-model="memberForm.phone" autocomplete="off" :disabled="true"/>
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.role')" prop="roleIds"> <el-form-item :label="$t('commons.role')" prop="roleIds" :rules="{required: true, message: $t('role.please_choose_role'), trigger: 'change'}">
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')" <el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
class="select-width"> class="select-width">
<el-option <el-option
@ -366,7 +366,7 @@
this.$info(this.$t('commons.remove_cancel')); this.$info(this.$t('commons.remove_cancel'));
}); });
}, },
updateOrgMember() { updateOrgMember(formName) {
let param = { let param = {
id: this.memberForm.id, id: this.memberForm.id,
name: this.memberForm.name, name: this.memberForm.name,
@ -375,11 +375,15 @@
roleIds: this.memberForm.roleIds, roleIds: this.memberForm.roleIds,
workspaceId: this.currentWorkspaceRow.id workspaceId: this.currentWorkspaceRow.id
} }
this.$refs[formName].validate((valid) => {
if (valid) {
this.result = this.$post("/workspace/member/update", param, () => { this.result = this.$post("/workspace/member/update", param, () => {
this.$success(this.$t('commons.modify_success')); this.$success(this.$t('commons.modify_success'));
this.dialogWsMemberUpdateVisible = false; this.dialogWsMemberUpdateVisible = false;
this.cellClick(this.currentWorkspaceRow); this.cellClick(this.currentWorkspaceRow);
}); });
}
})
}, },
buildPagePath(path) { buildPagePath(path) {
return path + "/" + this.dialogCurrentPage + "/" + this.dialogPageSize; return path + "/" + this.dialogCurrentPage + "/" + this.dialogPageSize;

View File

@ -145,7 +145,7 @@
<el-form-item :label="$t('commons.phone')" prop="phone"> <el-form-item :label="$t('commons.phone')" prop="phone">
<el-input v-model="memberForm.phone" autocomplete="off" :disabled="true"/> <el-input v-model="memberForm.phone" autocomplete="off" :disabled="true"/>
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.role')" prop="roleIds"> <el-form-item :label="$t('commons.role')" prop="roleIds" :rules="{required: true, message: $t('role.please_choose_role'), trigger: 'change'}">
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')" <el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
class="select-width"> class="select-width">
<el-option <el-option
@ -427,7 +427,7 @@
} }
}); });
}, },
updateOrgMember() { updateOrgMember(formName) {
let param = { let param = {
id: this.memberForm.id, id: this.memberForm.id,
name: this.memberForm.name, name: this.memberForm.name,
@ -436,11 +436,15 @@
roleIds: this.memberForm.roleIds, roleIds: this.memberForm.roleIds,
organizationId: this.currentRow.id organizationId: this.currentRow.id
} }
this.$refs[formName].validate((valid) => {
if (valid) {
this.result = this.$post("/organization/member/update", param, () => { this.result = this.$post("/organization/member/update", param, () => {
this.$success(this.$t('commons.modify_success')); this.$success(this.$t('commons.modify_success'));
this.dialogOrgMemberUpdateVisible = false; this.dialogOrgMemberUpdateVisible = false;
this.cellClick(this.currentRow); this.cellClick(this.currentRow);
}); });
}
});
}, },
} }

View File

@ -164,7 +164,7 @@
<el-form-item :label="$t('commons.phone')" prop="phone"> <el-form-item :label="$t('commons.phone')" prop="phone">
<el-input v-model="memberForm.phone" autocomplete="off" :disabled="true"/> <el-input v-model="memberForm.phone" autocomplete="off" :disabled="true"/>
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.role')" prop="roleIds"> <el-form-item :label="$t('commons.role')" prop="roleIds" :rules="{required: true, message: $t('role.please_choose_role'), trigger: 'change'}">
<el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')" <el-select v-model="memberForm.roleIds" multiple :placeholder="$t('role.please_choose_role')"
class="select-width"> class="select-width">
<el-option <el-option
@ -405,7 +405,7 @@
this.$info(this.$t('commons.remove_cancel')); this.$info(this.$t('commons.remove_cancel'));
}); });
}, },
updateWorkspaceMember() { updateWorkspaceMember(formName) {
let param = { let param = {
id: this.memberForm.id, id: this.memberForm.id,
name: this.memberForm.name, name: this.memberForm.name,
@ -414,11 +414,15 @@
roleIds: this.memberForm.roleIds, roleIds: this.memberForm.roleIds,
workspaceId: this.currentWorkspaceRow.id workspaceId: this.currentWorkspaceRow.id
} }
this.$refs[formName].validate((valid) => {
if (valid) {
this.result = this.$post("/workspace/member/update", param, () => { this.result = this.$post("/workspace/member/update", param, () => {
this.$success(this.$t('commons.modify_success')); this.$success(this.$t('commons.modify_success'));
this.dialogWsMemberUpdateVisible = false; this.dialogWsMemberUpdateVisible = false;
this.cellClick(this.currentWorkspaceRow); this.cellClick(this.currentWorkspaceRow);
}); });
}
});
}, },
}, },
data() { data() {

View File

@ -79,7 +79,7 @@
<el-form-item :label="$t('commons.phone')" prop="phone"> <el-form-item :label="$t('commons.phone')" prop="phone">
<el-input v-model="form.phone" autocomplete="off" :disabled="true"/> <el-input v-model="form.phone" autocomplete="off" :disabled="true"/>
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.role')" prop="roleIds"> <el-form-item :label="$t('commons.role')" prop="roleIds" :rules="{required: true, message: $t('role.please_choose_role'), trigger: 'change'}">
<el-select v-model="form.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width"> <el-select v-model="form.roleIds" multiple :placeholder="$t('role.please_choose_role')" class="select-width">
<el-option <el-option
v-for="item in form.allroles" v-for="item in form.allroles"
@ -197,7 +197,7 @@
// 使 // 使
this.$set(this.form, 'roleIds', roleIds); this.$set(this.form, 'roleIds', roleIds);
}, },
updateWorkspaceMember() { updateWorkspaceMember(formName) {
let param = { let param = {
id: this.form.id, id: this.form.id,
name: this.form.name, name: this.form.name,
@ -206,11 +206,15 @@
roleIds: this.form.roleIds, roleIds: this.form.roleIds,
workspaceId: this.currentUser().lastWorkspaceId workspaceId: this.currentUser().lastWorkspaceId
} }
this.$refs[formName].validate((valid) => {
if (valid) {
this.result = this.$post("/workspace/member/update", param, () => { this.result = this.$post("/workspace/member/update", param, () => {
this.$success(this.$t('commons.modify_success')); this.$success(this.$t('commons.modify_success'));
this.updateVisible = false; this.updateVisible = false;
this.initTableData(); this.initTableData();
}); });
}
});
}, },
create() { create() {
this.form = {}; this.form = {};

View File

@ -1,11 +1,12 @@
import {library} from '@fortawesome/fontawesome-svg-core' import {library} from '@fortawesome/fontawesome-svg-core'
import {fas} from '@fortawesome/free-solid-svg-icons' import {fas} from '@fortawesome/free-solid-svg-icons'
import {far} from '@fortawesome/free-regular-svg-icons' import {far} from '@fortawesome/free-regular-svg-icons'
import { fab } from '@fortawesome/free-brands-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome' import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'
export default { export default {
install(Vue) { install(Vue) {
library.add(fas, far); library.add(fas, far, fab);
Vue.component('font-awesome-icon', FontAwesomeIcon); Vue.component('font-awesome-icon', FontAwesomeIcon);
} }
} }

View File

@ -4,6 +4,7 @@ export default {
'organization': 'Organization', 'organization': 'Organization',
'setting': 'Setting', 'setting': 'Setting',
'project': 'Project', 'project': 'Project',
'about_us': 'About Us',
current_project: 'Current Project', current_project: 'Current Project',
'name': 'Name', 'name': 'Name',
'description': 'Description', 'description': 'Description',

View File

@ -4,6 +4,7 @@ export default {
'organization': '组织', 'organization': '组织',
'setting': '设置', 'setting': '设置',
'project': '项目', 'project': '项目',
'about_us': '关于',
current_project: '当前项目', current_project: '当前项目',
'name': '名称', 'name': '名称',
'description': '描述', 'description': '描述',

View File

@ -4,6 +4,7 @@ export default {
'organization': '組織', 'organization': '組織',
'setting': '設置', 'setting': '設置',
'project': '項目', 'project': '項目',
'about_us': '關於',
current_project: '當前項目', current_project: '當前項目',
'name': '名稱', 'name': '名稱',
'description': '描述', 'description': '描述',