refactor: 用户第三方平台信息添加校验功能 (#4301)

Co-authored-by: chenjianxing <jianxing.chen@fit2cloud.com>
This commit is contained in:
metersphere-bot 2021-07-01 21:35:13 +08:00 committed by GitHub
parent b0d4e45c58
commit 9154a10a1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 166 additions and 41 deletions

View File

@ -10,6 +10,7 @@ import io.metersphere.commons.utils.Pager;
import io.metersphere.log.annotation.MsAuditLog; import io.metersphere.log.annotation.MsAuditLog;
import io.metersphere.track.issue.domain.PlatformUser; import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.zentao.ZentaoBuild; import io.metersphere.track.issue.domain.zentao.ZentaoBuild;
import io.metersphere.track.request.testcase.AuthUserIssueRequest;
import io.metersphere.track.request.testcase.IssuesRequest; import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest; import io.metersphere.track.request.testcase.IssuesUpdateRequest;
import io.metersphere.track.service.IssuesService; import io.metersphere.track.service.IssuesService;
@ -59,6 +60,11 @@ public class IssuesController {
issuesService.testAuth(orgId, platform); issuesService.testAuth(orgId, platform);
} }
@PostMapping("/user/auth")
public void userAuth(@RequestBody AuthUserIssueRequest authUserIssueRequest) {
issuesService.userAuth(authUserIssueRequest);
}
@GetMapping("/close/{id}") @GetMapping("/close/{id}")
public void closeLocalIssue(@PathVariable String id) { public void closeLocalIssue(@PathVariable String id) {
issuesService.closeLocalIssue(id); issuesService.closeLocalIssue(id);

View File

@ -2,6 +2,7 @@ package io.metersphere.track.issue;
import io.metersphere.base.domain.IssuesDao; import io.metersphere.base.domain.IssuesDao;
import io.metersphere.base.domain.Project; import io.metersphere.base.domain.Project;
import io.metersphere.dto.UserDTO;
import io.metersphere.track.dto.DemandDTO; import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.issue.domain.PlatformUser; import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.request.testcase.IssuesRequest; import io.metersphere.track.request.testcase.IssuesRequest;
@ -46,6 +47,11 @@ public interface IssuesPlatform {
*/ */
void testAuth(); void testAuth();
/**
* 用户信息测试
*/
void userAuth(UserDTO.PlatformInfo userInfo);
/** /**
* 获取缺陷平台项目下的相关人员 * 获取缺陷平台项目下的相关人员
* @return platform user list * @return platform user list

View File

@ -268,7 +268,18 @@ public class JiraPlatform extends AbstractIssuePlatform {
@Override @Override
public void testAuth() { public void testAuth() {
setConfig(); setConfig();
jiraClientV2.getIssueCreateMetadata(); jiraClientV2.auth();
}
@Override
public void userAuth(UserDTO.PlatformInfo userInfo) {
String config = getPlatformConfig(IssuesManagePlatform.Jira.toString());
JiraConfig jiraConfig = JSONObject.parseObject(config, JiraConfig.class);
jiraConfig.setAccount(userInfo.getJiraAccount());
jiraConfig.setPassword(userInfo.getJiraPassword());
validateConfig(jiraConfig);
jiraClientV2.setConfig(jiraConfig);
jiraClientV2.auth();
} }
@Override @Override

View File

@ -0,0 +1,29 @@
package io.metersphere.track.issue;
import io.metersphere.base.domain.IssuesDao;
import io.metersphere.base.domain.Project;
import io.metersphere.dto.UserDTO;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.request.testcase.IssuesRequest;
import java.util.List;
public abstract class LocalAbstractPlatform extends AbstractIssuePlatform {
public LocalAbstractPlatform(IssuesRequest issuesRequest) { super(issuesRequest); }
@Override
public void testAuth() {}
@Override
public void userAuth(UserDTO.PlatformInfo userInfo) {}
@Override
public List<PlatformUser> getPlatformUser() { return null; }
@Override
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {}
@Override
String getProjectId(String projectId) { return null; }
}

View File

@ -2,13 +2,11 @@ package io.metersphere.track.issue;
import io.metersphere.base.domain.IssuesDao; import io.metersphere.base.domain.IssuesDao;
import io.metersphere.base.domain.IssuesWithBLOBs; import io.metersphere.base.domain.IssuesWithBLOBs;
import io.metersphere.base.domain.Project;
import io.metersphere.commons.constants.IssuesManagePlatform; import io.metersphere.commons.constants.IssuesManagePlatform;
import io.metersphere.commons.user.SessionUser; import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.SessionUtils; import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.track.dto.DemandDTO; import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.request.testcase.IssuesRequest; import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest; import io.metersphere.track.request.testcase.IssuesUpdateRequest;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -16,7 +14,7 @@ import org.apache.commons.lang3.StringUtils;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
public class LocalPlatform extends AbstractIssuePlatform { public class LocalPlatform extends LocalAbstractPlatform {
protected String key = IssuesManagePlatform.Local.toString(); protected String key = IssuesManagePlatform.Local.toString();
@ -67,31 +65,4 @@ public class LocalPlatform extends AbstractIssuePlatform {
public void deleteIssue(String id) { public void deleteIssue(String id) {
issuesMapper.deleteByPrimaryKey(id); issuesMapper.deleteByPrimaryKey(id);
} }
@Override
public void testAuth() {
}
@Override
public List<PlatformUser> getPlatformUser() {
return null;
}
@Override
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {
}
@Override
String getProjectId(String projectId) {
return null;
}
public void closeIssue(String issueId) {
IssuesWithBLOBs issues = new IssuesWithBLOBs();
issues.setId(issueId);
issues.setStatus("closed");
issuesMapper.updateByPrimaryKeySelective(issues);
}
} }

View File

@ -159,6 +159,11 @@ public class TapdPlatform extends AbstractIssuePlatform {
} }
} }
@Override
public void userAuth(UserDTO.PlatformInfo userInfo) {
testAuth();
}
@Override @Override
public List<PlatformUser> getPlatformUser() { public List<PlatformUser> getPlatformUser() {
List<PlatformUser> users = new ArrayList<>(); List<PlatformUser> users = new ArrayList<>();

View File

@ -234,6 +234,16 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
zentaoClient.login(); zentaoClient.login();
} }
@Override
public void userAuth(UserDTO.PlatformInfo userInfo) {
String config = getPlatformConfig(IssuesManagePlatform.Zentao.toString());
ZentaoConfig zentaoConfig = JSONObject.parseObject(config, ZentaoConfig.class);
zentaoConfig.setAccount(userInfo.getZentaoUserName());
zentaoConfig.setPassword(userInfo.getZentaoPassword());
zentaoClient.setConfig(zentaoConfig);
zentaoClient.login();
}
public ZentaoConfig setConfig() { public ZentaoConfig setConfig() {
ZentaoConfig config = getConfig(); ZentaoConfig config = getConfig();
zentaoClient.setConfig(config); zentaoClient.setConfig(config);

View File

@ -49,9 +49,13 @@ public abstract class JiraAbstractClient extends BaseClient {
return (JiraAddIssueResponse) getResultForObject(JiraAddIssueResponse.class, response); return (JiraAddIssueResponse) getResultForObject(JiraAddIssueResponse.class, response);
} }
public String getIssueCreateMetadata() { public void auth() {
ResponseEntity<String> response = restTemplate.exchange(getBaseUrl() + "/issue/createmeta", HttpMethod.GET, getAuthHttpEntity(), String.class); try {
return (String) getResultForObject(String.class, response); restTemplate.exchange(getBaseUrl() + "/permissions", HttpMethod.GET, getAuthHttpEntity(), String.class);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(e.getMessage());
}
} }
protected HttpEntity<MultiValueMap> getAuthHttpEntity() { protected HttpEntity<MultiValueMap> getAuthHttpEntity() {

View File

@ -56,8 +56,14 @@ public class ZentaoClient extends BaseClient {
String sessionId = login(); String sessionId = login();
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(paramMap, new HttpHeaders()); HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(paramMap, new HttpHeaders());
RestTemplate restTemplate = new RestTemplate(); RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(getBaseUrl() + "/api-getModel-bug-create.json?zentaosid=" + sessionId, ResponseEntity<String> response = null;
try {
response = restTemplate.exchange(getBaseUrl() + "/api-getModel-bug-create.json?zentaosid=" + sessionId,
HttpMethod.POST, requestEntity, String.class); HttpMethod.POST, requestEntity, String.class);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(e.getMessage());
}
AddIssueResponse addIssueResponse = (AddIssueResponse) getResultForObject(AddIssueResponse.class, response); AddIssueResponse addIssueResponse = (AddIssueResponse) getResultForObject(AddIssueResponse.class, response);
return JSONObject.parseObject(addIssueResponse.getData(), AddIssueResponse.Issue.class); return JSONObject.parseObject(addIssueResponse.getData(), AddIssueResponse.Issue.class);
} }

View File

@ -0,0 +1,13 @@
package io.metersphere.track.request.testcase;
import io.metersphere.dto.UserDTO;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AuthUserIssueRequest extends UserDTO.PlatformInfo {
private String orgId;
private String platform;
}

View File

@ -26,6 +26,7 @@ import io.metersphere.service.ProjectService;
import io.metersphere.track.issue.*; import io.metersphere.track.issue.*;
import io.metersphere.track.issue.domain.PlatformUser; import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.zentao.ZentaoBuild; import io.metersphere.track.issue.domain.zentao.ZentaoBuild;
import io.metersphere.track.request.testcase.AuthUserIssueRequest;
import io.metersphere.track.request.testcase.IssuesRequest; import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest; import io.metersphere.track.request.testcase.IssuesUpdateRequest;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -484,4 +485,11 @@ public class IssuesService {
public List<IssuesDao> relateList(IssuesRequest request) { public List<IssuesDao> relateList(IssuesRequest request) {
return extIssuesMapper.getRelateIssues(request); return extIssuesMapper.getRelateIssues(request);
} }
public void userAuth(AuthUserIssueRequest authUserIssueRequest) {
IssuesRequest issuesRequest = new IssuesRequest();
issuesRequest.setOrganizationId(authUserIssueRequest.getOrgId());
AbstractIssuePlatform abstractPlatform = IssueFactory.createPlatform(authUserIssueRequest.getPlatform(), issuesRequest);
abstractPlatform.userAuth(authUserIssueRequest);
}
} }

View File

@ -52,6 +52,12 @@
{{ $t('organization.integration.link_the_project_now') }} {{ $t('organization.integration.link_the_project_now') }}
</router-link> </router-link>
</div> </div>
<div>
3. {{ $t('organization.integration.use_tip_three') }}
<router-link :to="{name: 'PersonSetting', params: { open: true }}" style="margin-left: 5px">
{{ $t('organization.integration.link_the_info_now') }}
</router-link>
</div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -33,6 +33,12 @@
{{ $t('organization.integration.link_the_project_now') }} {{ $t('organization.integration.link_the_project_now') }}
</router-link> </router-link>
</div> </div>
<div>
3. {{ $t('organization.integration.use_tip_three') }}
<router-link :to="{name: 'PersonSetting', params: { open: true }}" style="margin-left: 5px">
{{ $t('organization.integration.link_the_info_now') }}
</router-link>
</div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -36,6 +36,12 @@
{{ $t('organization.integration.link_the_project_now') }} {{ $t('organization.integration.link_the_project_now') }}
</router-link> </router-link>
</div> </div>
<div>
3. {{ $t('organization.integration.use_tip_three') }}
<router-link :to="{name: 'PersonSetting', params: { open: true }}" style="margin-left: 5px">
{{ $t('organization.integration.link_the_info_now') }}
</router-link>
</div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -10,6 +10,11 @@
<el-input v-model="data.jiraPassword" auto-complete="new-password" <el-input v-model="data.jiraPassword" auto-complete="new-password"
:placeholder="$t('organization.integration.input_api_password')" show-password/> :placeholder="$t('organization.integration.input_api_password')" show-password/>
</el-form-item> </el-form-item>
<el-form-item >
<el-button type="primary" style="float: right" @click="$emit('auth', 'Jira')" size="mini">
{{$t('commons.validate')}}
</el-button>
</el-form-item>
</el-form> </el-form>
</template> </template>

View File

@ -34,7 +34,7 @@
</el-card> </el-card>
<!--Modify personal details--> <!--Modify personal details-->
<el-dialog :close-on-click-modal="false" :title="$t('member.modify_personal_info')" :visible.sync="updateVisible" width="30%" <el-dialog :close-on-click-modal="false" :title="$t('member.modify_personal_info')" :visible.sync="updateVisible" width="40%"
:destroy-on-close="true" @close="handleClose"> :destroy-on-close="true" @close="handleClose">
<el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule" <el-form :model="form" label-position="right" label-width="100px" size="small" :rules="rule"
ref="updateUserForm"> ref="updateUserForm">
@ -51,9 +51,9 @@
<el-input v-model="form.phone" autocomplete="off"/> <el-input v-model="form.phone" autocomplete="off"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<jira-user-info v-if="hasJira" :data="currentPlatformInfo"/> <jira-user-info @auth="handleAuth" v-if="hasJira" :data="currentPlatformInfo"/>
<tapd-user-info v-if="hasTapd" :data="currentPlatformInfo"/> <tapd-user-info @auth="handleAuth" v-if="hasTapd" :data="currentPlatformInfo"/>
<zentao-user-info v-if="hasZentao" :data="currentPlatformInfo"/> <zentao-user-info @auth="handleAuth" v-if="hasZentao" :data="currentPlatformInfo"/>
<template v-slot:footer> <template v-slot:footer>
<ms-dialog-footer <ms-dialog-footer
@cancel="updateVisible = false" @cancel="updateVisible = false"
@ -86,7 +86,7 @@
</template> </template>
<script> <script>
import {TokenKey} from "../../../../common/js/constants"; import {TokenKey, ZEN_TAO} from "../../../../common/js/constants";
import MsDialogFooter from "../../common/components/MsDialogFooter"; import MsDialogFooter from "../../common/components/MsDialogFooter";
import { import {
getCurrentOrganizationId, getCurrentOrganizationId,
@ -276,8 +276,24 @@ export default {
let dataList = []; let dataList = [];
dataList[0] = data; dataList[0] = data;
this.tableData = dataList; this.tableData = dataList;
this.handleRouteOpen();
}) })
}, },
handleRouteOpen() {
let params = this.$route.params;
if (params.open) {
this.edit(this.tableData[0]);
params.open = false;
}
},
handleAuth(type) {
let param = {...this.currentPlatformInfo};
param.orgId = getCurrentOrganizationId();
param.platform = type
this.$parent.result = this.$post("issues/user/auth", param, () => {
this.$success(this.$t('organization.integration.verified'));
});
},
handleClose() { handleClose() {
this.form = {}; this.form = {};
this.ruleForm = {}; this.ruleForm = {};

View File

@ -10,6 +10,11 @@
<el-form-item :label="'Tapd 昵称'" prop="account"> <el-form-item :label="'Tapd 昵称'" prop="account">
<el-input v-model="data.tapdUserName" :placeholder="$t('organization.integration.input_api_account')"/> <el-input v-model="data.tapdUserName" :placeholder="$t('organization.integration.input_api_account')"/>
</el-form-item> </el-form-item>
<el-form-item >
<el-button type="primary" style="float: right" @click="$emit('auth', 'Tapd')" size="mini">
{{$t('commons.validate')}}
</el-button>
</el-form-item>
</el-form> </el-form>
</template> </template>

View File

@ -10,6 +10,11 @@
<el-input v-model="data.zentaoPassword" auto-complete="new-password" <el-input v-model="data.zentaoPassword" auto-complete="new-password"
:placeholder="$t('organization.integration.input_api_password')" show-password/> :placeholder="$t('organization.integration.input_api_password')" show-password/>
</el-form-item> </el-form-item>
<el-form-item >
<el-button type="primary" style="float: right" @click="$emit('auth', 'Zentao')" size="mini">
{{$t('commons.validate')}}
</el-button>
</el-form-item>
</el-form> </el-form>
</template> </template>

View File

@ -96,6 +96,7 @@ export default {
}, },
{ {
path: 'personsetting', path: 'personsetting',
name: 'PersonSetting',
component: () => import('@/business/components/settings/personal/PersonSetting'), component: () => import('@/business/components/settings/personal/PersonSetting'),
meta: {person: true, title: 'commons.personal_setting'} meta: {person: true, title: 'commons.personal_setting'}
}, },

View File

@ -399,7 +399,9 @@ export default {
use_tip_jira: 'Jira software server authentication information is account password, Jira software cloud authentication information is account + token (account settings-security-create API token)', use_tip_jira: 'Jira software server authentication information is account password, Jira software cloud authentication information is account + token (account settings-security-create API token)',
use_tip_zentao: 'The account password is a Zentao account with corresponding permissions, and the account needs to have super model calling interface permissions', use_tip_zentao: 'The account password is a Zentao account with corresponding permissions, and the account needs to have super model calling interface permissions',
use_tip_two: 'After saving the Basic Auth account information, you need to manually associate the ID/key and issue template in the MeterSphere project', use_tip_two: 'After saving the Basic Auth account information, you need to manually associate the ID/key and issue template in the MeterSphere project',
use_tip_three: 'Add your personal platform account',
link_the_project_now: 'Link the project now', link_the_project_now: 'Link the project now',
link_the_info_now: 'Add now',
cancel_edit: 'Cancel edit', cancel_edit: 'Cancel edit',
cancel_integration: 'Cancel integration', cancel_integration: 'Cancel integration',
cancel_confirm: 'Confirm cancellation of integration ', cancel_confirm: 'Confirm cancellation of integration ',

View File

@ -397,7 +397,9 @@ export default {
use_tip_jira: 'Jira software server 认证信息为 账号密码Jira software cloud 认证信息为 账号+令牌(账户设置-安全-创建API令牌)', use_tip_jira: 'Jira software server 认证信息为 账号密码Jira software cloud 认证信息为 账号+令牌(账户设置-安全-创建API令牌)',
use_tip_zentao: '账号密码为具有相应权限的Zentao账号账号需要具有 超级model调用接口权限', use_tip_zentao: '账号密码为具有相应权限的Zentao账号账号需要具有 超级model调用接口权限',
use_tip_two: '保存 Basic Auth 账号信息后,需要在 MeterSphere 项目中手动关联 ID/key 和缺陷模板', use_tip_two: '保存 Basic Auth 账号信息后,需要在 MeterSphere 项目中手动关联 ID/key 和缺陷模板',
use_tip_three: '添加你的个人平台账号',
link_the_project_now: '马上关联项目', link_the_project_now: '马上关联项目',
link_the_info_now: '马上添加',
cancel_edit: '取消编辑', cancel_edit: '取消编辑',
cancel_integration: '取消集成', cancel_integration: '取消集成',
cancel_confirm: '确认取消集成 ', cancel_confirm: '确认取消集成 ',

View File

@ -397,7 +397,9 @@ export default {
use_tip_jira: 'Jira software server 認證信息為 賬號密碼Jira software cloud 認證信息為 賬號+令牌(賬戶設置-安全-創建API令牌)', use_tip_jira: 'Jira software server 認證信息為 賬號密碼Jira software cloud 認證信息為 賬號+令牌(賬戶設置-安全-創建API令牌)',
use_tip_zentao: '賬號密碼為具有相應權限的Zentao賬號賬號需要具有 超級model調用接口權限', use_tip_zentao: '賬號密碼為具有相應權限的Zentao賬號賬號需要具有 超級model調用接口權限',
use_tip_two: '保存 Basic Auth 賬號信息後,需要在 MeterSphere 項目中手動關聯 ID/key 和缺陷模板', use_tip_two: '保存 Basic Auth 賬號信息後,需要在 MeterSphere 項目中手動關聯 ID/key 和缺陷模板',
use_tip_three: '添加你的個人平臺賬號',
link_the_project_now: '馬上關聯項目', link_the_project_now: '馬上關聯項目',
link_the_info_now: '馬上添加',
cancel_edit: '取消編輯', cancel_edit: '取消編輯',
cancel_integration: '取消集成', cancel_integration: '取消集成',
cancel_confirm: '確認取消集成 ', cancel_confirm: '確認取消集成 ',