feat: 禅道用户信息配置

This commit is contained in:
chenjianxing 2021-07-01 12:08:57 +08:00 committed by jianxing
parent 78d7f41783
commit bb63da7e9a
17 changed files with 165 additions and 59 deletions

View File

@ -27,6 +27,8 @@ public class UserDTO extends User {
private String jiraAccount;
private String jiraPassword;
private String tapdUserName;
private String zentaoUserName;
private String zentaoPassword;
}
}

View File

@ -188,6 +188,7 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform {
issues.setCreateTime(System.currentTimeMillis());
issues.setUpdateTime(System.currentTimeMillis());
issues.setNum(getNextNum(issuesRequest.getProjectId()));
issues.setPlatformStatus(issuesRequest.getPlatformStatus());
issuesMapper.insert(issues);
}

View File

@ -86,13 +86,9 @@ public class JiraPlatform extends AbstractIssuePlatform {
String lastmodify = "";
String status = "";
JSONObject fields = jiraIssue.getFields();
JSONObject statusObj = (JSONObject) fields.get("status");
JSONObject assignee = (JSONObject) fields.get("assignee");
if (statusObj != null) {
JSONObject statusCategory = (JSONObject) statusObj.get("statusCategory");
status = statusCategory.getString("name");
}
status = getStatus(fields);
JSONObject assignee = (JSONObject) fields.get("assignee");
String description = fields.getString("description");
Parser parser = Parser.builder().build();
@ -112,6 +108,15 @@ public class JiraPlatform extends AbstractIssuePlatform {
item.setPlatform(IssuesManagePlatform.Jira.toString());
}
private String getStatus(JSONObject fields) {
JSONObject statusObj = (JSONObject) fields.get("status");
if (statusObj != null) {
JSONObject statusCategory = (JSONObject) statusObj.get("statusCategory");
return statusCategory.getString("name");
}
return "";
}
@Override
public List<DemandDTO> getDemandList(String projectId) {
List<DemandDTO> list = new ArrayList<>();
@ -227,6 +232,9 @@ public class JiraPlatform extends AbstractIssuePlatform {
}
});
JiraAddIssueResponse result = jiraClientV2.addIssue(JSONObject.toJSONString(addJiraIssueParam));
JiraIssue issues = jiraClientV2.getIssues(result.getId());
String status = getStatus(issues.getFields());
issuesRequest.setPlatformStatus(status);
issuesRequest.setId(result.getKey());
// 用例与第三方缺陷平台中的缺陷关联

View File

@ -19,6 +19,7 @@ import io.metersphere.dto.UserDTO;
import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.issue.client.TapdClient;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.tapd.TapdBug;
import io.metersphere.track.issue.domain.tapd.TapdConfig;
import io.metersphere.track.issue.domain.tapd.TapdGetIssueResponse;
import io.metersphere.track.request.testcase.IssuesRequest;
@ -100,13 +101,15 @@ public class TapdPlatform extends AbstractIssuePlatform {
usersStr = String.join(";", platformUsers);
}
String username = SessionUtils.getUser().getName();
String reporter = getReporter();
if (StringUtils.isBlank(reporter)) {
reporter = SessionUtils.getUser().getName();
}
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("title", issuesRequest.getTitle());
paramMap.add("workspace_id", tapdId);
paramMap.add("description", issuesRequest.getDescription());
paramMap.add("reporter", username);
paramMap.add("current_owner", usersStr);
customFields.forEach(item -> {
@ -114,19 +117,19 @@ public class TapdPlatform extends AbstractIssuePlatform {
paramMap.add(item.getCustomData(), item.getValue());
}
});
paramMap.add("reporter", reporter);
ResultHolder result = call(url, HttpMethod.POST, paramMap);
setConfig();
TapdBug bug = tapdClient.addIssue(paramMap);
Map<String, String> statusMap = tapdClient.getStatusMap(getProjectId(this.projectId));
issuesRequest.setPlatformStatus(statusMap.get(bug.getStatus()));
String listJson = JSON.toJSONString(result.getData());
JSONObject jsonObject = JSONObject.parseObject(listJson);
String issuesId = jsonObject.getObject("Bug", Issues.class).getId();
issuesRequest.setId(issuesId);
issuesRequest.setId(bug.getId());
// 用例与第三方缺陷平台中的缺陷关联
handleTestCaseIssues(issuesRequest);
// 插入缺陷表
insertIssues(issuesId, issuesRequest);
insertIssues(bug.getId(), issuesRequest);
}
@Override
@ -200,7 +203,7 @@ public class TapdPlatform extends AbstractIssuePlatform {
count = data.size();
pageNum++;
data.forEach(issue -> {
TapdGetIssueResponse.Bug bug = issue.getBug();
TapdBug bug = issue.getBug();
IssuesDao issuesDao = new IssuesDao();
BeanUtils.copyBean(issuesDao, bug);
issuesDao.setPlatformStatus(statusMap.get(bug.getStatus()));
@ -228,19 +231,20 @@ public class TapdPlatform extends AbstractIssuePlatform {
}
public TapdConfig getConfig() {
TapdConfig tapdConfig = null;
String config = getPlatformConfig(IssuesManagePlatform.Tapd.toString());
if (StringUtils.isNotBlank(config)) {
tapdConfig = JSONObject.parseObject(config, TapdConfig.class);
UserDTO.PlatformInfo userPlatInfo = getUserPlatInfo(this.orgId);
if (userPlatInfo != null && StringUtils.isNotBlank(userPlatInfo.getTapdUserName())) {
// tapdConfig.setAccount(userPlatInfo.getTapdUserName());
}
}
TapdConfig tapdConfig = JSONObject.parseObject(config, TapdConfig.class);
// validateConfig(tapdConfig);
return tapdConfig;
}
public String getReporter() {
UserDTO.PlatformInfo userPlatInfo = getUserPlatInfo(this.orgId);
if (userPlatInfo != null && StringUtils.isNotBlank(userPlatInfo.getTapdUserName())) {
return userPlatInfo.getTapdUserName();
}
return null;
}
public TapdConfig setConfig() {
TapdConfig config = getConfig();
tapdClient.setConfig(config);

View File

@ -13,6 +13,7 @@ import io.metersphere.commons.constants.IssuesStatus;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.dto.CustomFieldItemDTO;
import io.metersphere.dto.UserDTO;
import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.issue.client.ZentaoClient;
import io.metersphere.track.issue.domain.PlatformUser;
@ -158,18 +159,11 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
issuesRequest.setPlatform(IssuesManagePlatform.Zentao.toString());
List<CustomFieldItemDTO> customFields = getCustomFields(issuesRequest.getCustomFields());
setConfig();
String session = zentaoClient.login();
zentaoClient.setConfig(getUserConfig());
String projectId = getProjectId(issuesRequest.getProjectId());
if (StringUtils.isBlank(projectId)) {
MSException.throwException("未关联禅道项目ID.");
}
if (StringUtils.isBlank(session)) {
MSException.throwException("session is null");
}
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("product", projectId);
paramMap.add("title", issuesRequest.getTitle());
@ -203,6 +197,7 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
}
AddIssueResponse.Issue issue = zentaoClient.addIssue(paramMap);
issuesRequest.setPlatformStatus(issue.getStatus());
String id = issue.getId();
if (StringUtils.isNotBlank(id)) {
@ -253,6 +248,22 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
return zentaoConfig;
}
public ZentaoConfig getUserConfig() {
ZentaoConfig zentaoConfig = null;
String config = getPlatformConfig(IssuesManagePlatform.Zentao.toString());
if (StringUtils.isNotBlank(config)) {
zentaoConfig = JSONObject.parseObject(config, ZentaoConfig.class);
UserDTO.PlatformInfo userPlatInfo = getUserPlatInfo(this.orgId);
if (userPlatInfo != null && StringUtils.isNotBlank(userPlatInfo.getZentaoUserName())
&& StringUtils.isNotBlank(userPlatInfo.getZentaoPassword())) {
zentaoConfig.setAccount(userPlatInfo.getZentaoUserName());
zentaoConfig.setPassword(userPlatInfo.getZentaoPassword());
}
}
// validateConfig(jiraConfig);
return zentaoConfig;
}
@Override
public List<PlatformUser> getPlatformUser() {
setConfig();

View File

@ -50,11 +50,11 @@ public abstract class BaseClient {
protected String getResult(ResponseEntity<String> response) {
int statusCodeValue = response.getStatusCodeValue();
LogUtil.debug("responseCode: " + statusCodeValue);
LogUtil.info("responseCode: " + statusCodeValue);
if(statusCodeValue >= 400){
MSException.throwException(response.getBody());
}
LogUtil.debug("result: " + response.getBody());
LogUtil.info("result: " + response.getBody());
return response.getBody();
}

View File

@ -23,7 +23,7 @@ public abstract class JiraAbstractClient extends BaseClient {
protected String PASSWD;
public JiraIssue getIssues(String issuesId) {
LogUtil.debug("getIssues: " + issuesId);
LogUtil.info("getIssues: " + issuesId);
ResponseEntity<String> responseEntity;
responseEntity = restTemplate.exchange(getBaseUrl() + "/issue/" + issuesId, HttpMethod.GET, getAuthHttpEntity(), String.class);
return (JiraIssue) getResultForObject(JiraIssue.class, responseEntity);
@ -35,11 +35,17 @@ public abstract class JiraAbstractClient extends BaseClient {
}
public JiraAddIssueResponse addIssue(String body) {
LogUtil.debug("addIssue: " + body);
LogUtil.info("addIssue: " + body);
HttpHeaders headers = getAuthHeader();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.exchange(getBaseUrl() + "/issue", HttpMethod.POST, requestEntity, String.class);
ResponseEntity<String> response = null;
try {
response = restTemplate.exchange(getBaseUrl() + "/issue", HttpMethod.POST, requestEntity, String.class);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(e.getMessage());
}
return (JiraAddIssueResponse) getResultForObject(JiraAddIssueResponse.class, response);
}

View File

@ -2,6 +2,9 @@ package io.metersphere.track.issue.client;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.track.issue.domain.tapd.AddTapdIssueResponse;
import io.metersphere.track.issue.domain.tapd.TapdBug;
import io.metersphere.track.issue.domain.tapd.TapdConfig;
import io.metersphere.track.issue.domain.tapd.TapdGetIssueResponse;
import org.springframework.http.HttpEntity;
@ -53,6 +56,19 @@ public class TapdClient extends BaseClient {
return (TapdGetIssueResponse) getResultForObject(TapdGetIssueResponse.class, response);
}
public TapdBug addIssue(MultiValueMap<String, Object> paramMap) {
String url = getBaseUrl() + "/bugs";
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(paramMap, getAuthHeader());
ResponseEntity<String> response = null;
try {
response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(e.getMessage());
}
return ((AddTapdIssueResponse) getResultForObject(AddTapdIssueResponse.class, response)).getData().getBug();
}
protected HttpEntity<MultiValueMap> getAuthHttpEntity() {
return new HttpEntity<>(getAuthHeader());
}

View File

@ -34,7 +34,6 @@ public class ZentaoClient extends BaseClient {
GetUserResponse getUserResponse = (GetUserResponse) getResultForObject(GetUserResponse.class, response);
GetUserResponse.User user = getUserResponse.getUser();
if (user == null) {
LogUtil.error("login fail");
LogUtil.error(JSONObject.toJSON(getUserResponse));
// 登录失败获取的session无效置空session
MSException.throwException("zentao login fail");

View File

@ -0,0 +1,20 @@
package io.metersphere.track.issue.domain.tapd;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AddTapdIssueResponse {
private int status;
private Data data;
private String info;
@Getter
@Setter
public static class Data {
private TapdBug bug;
}
}

View File

@ -0,0 +1,16 @@
package io.metersphere.track.issue.domain.tapd;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TapdBug {
private String id;
private String title;
private String description;
// private String priority;
// private String severity;
// private String reporter;
private String status;
}

View File

@ -16,18 +16,6 @@ public class TapdGetIssueResponse {
@Getter
@Setter
public static class Data {
private Bug bug;
}
@Getter
@Setter
public static class Bug {
private String id;
private String title;
private String description;
// private String priority;
// private String severity;
// private String reporter;
private String status;
private TapdBug bug;
}
}

View File

@ -8,6 +8,7 @@ import lombok.Setter;
public class GetUserResponse {
private String status;
private User user;
private String reason;
@Getter
@Setter

View File

@ -1,7 +1,7 @@
<template>
<el-form label-position="right" label-width="100px" size="small">
<el-form-item :label="'Jira 信息'">
<ms-instructions-icon size="10" :content="'该信息为对接 Jira 的用户认证信息,若未填写,则使用组织中配置的默认信息'"/>
<ms-instructions-icon size="10" :content="'该信息为通过Jira提交缺陷的用户认证信息,若未填写,则使用组织中配置的默认信息'"/>
</el-form-item>
<el-form-item :label="'Jira ' + $t('organization.integration.account')" prop="account">
<el-input v-model="data.jiraAccount" :placeholder="$t('organization.integration.input_api_account')"/>

View File

@ -53,6 +53,7 @@
</el-form>
<jira-user-info v-if="hasJira" :data="currentPlatformInfo"/>
<tapd-user-info v-if="hasTapd" :data="currentPlatformInfo"/>
<zentao-user-info v-if="hasZentao" :data="currentPlatformInfo"/>
<template v-slot:footer>
<ms-dialog-footer
@cancel="updateVisible = false"
@ -98,10 +99,11 @@ import {EMAIL_REGEX, PHONE_REGEX} from "@/common/js/regex";
import JiraUserInfo from "@/business/components/settings/personal/JiraUserInfo";
import TapdUserInfo from "@/business/components/settings/personal/TapdUserInfo";
import {getIntegrationService} from "@/network/organization";
import ZentaoUserInfo from "@/business/components/settings/personal/ZentaoUserInfo";
export default {
name: "MsPersonSetting",
components: {TapdUserInfo, JiraUserInfo, MsDialogFooter, MsTableOperatorButton},
components: {ZentaoUserInfo, TapdUserInfo, JiraUserInfo, MsDialogFooter, MsTableOperatorButton},
inject: [
'reload'
],
@ -118,11 +120,14 @@ export default {
currentPlatformInfo: {
jiraAccount: '',
jiraPassword: '',
tapdUserName: ''
tapdUserName: '',
zentaoUserName: '',
zentaoPassword: ''
},
ruleForm: {},
hasJira: false,
hasTapd: false,
hasZentao: false,
rule: {
name: [
{required: true, message: this.$t('member.input_name'), trigger: 'blur'},
@ -209,9 +214,9 @@ export default {
if (platforms.indexOf("Jira") !== -1) {
this.hasJira = true;
}
// if (platforms.indexOf("Zentao") !== -1) {
// this.zentao = true;
// }
if (platforms.indexOf("Zentao") !== -1) {
this.hasZentao = true;
}
});
},
editPassword(row) {

View File

@ -0,0 +1,29 @@
<template>
<el-form label-position="right" label-width="100px" size="small">
<el-form-item :label="'禅道信息'">
<ms-instructions-icon size="10" :content="'该信息为通过禅道提交缺陷的的用户名、密码,若未填写,则使用组织中配置的默认信息'"/>
</el-form-item>
<el-form-item :label="'禅道' + $t('organization.integration.account')" prop="account">
<el-input v-model="data.zentaoUserName" :placeholder="$t('organization.integration.input_api_account')"/>
</el-form-item>
<el-form-item :label="'禅道' + $t('organization.integration.password')" prop="password">
<el-input v-model="data.zentaoPassword" auto-complete="new-password"
:placeholder="$t('organization.integration.input_api_password')" show-password/>
</el-form-item>
</el-form>
</template>
<script>
import MsInstructionsIcon from "@/business/components/common/components/MsInstructionsIcon";
export default {
name: "ZentaoUserInfo",
components: {MsInstructionsIcon},
props: ['data'],
}
</script>
<style scoped>
.instructions-icon {
margin-left: -5px;
}
</style>

View File

@ -158,11 +158,11 @@ export default {
let platform = this.issueTemplate.platform;
if (platform === 'Zentao') {
this.hasZentaoId = true;
this.result = this.$post("/issues/zentao/builds", {projectId: this.projectId}, response => {
this.result = this.$post("/issues/zentao/builds", {projectId: this.projectId, organizationId: getCurrentOrganizationId()}, response => {
if (response.data) {
this.Builds = response.data;
}
this.result = this.$post("/issues/zentao/user", {projectId: this.projectId}, response => {
this.result = this.$post("/issues/zentao/user", {projectId: this.projectId, organizationId: getCurrentOrganizationId()}, response => {
this.zentaoUsers = response.data;
});
});