Skip to content
代码片段 群组 项目
未验证 提交 29542e18 编辑于 作者: Michał Wielich's avatar Michał Wielich 提交者: GitLab
浏览文件

Merge branch 'remove-old-finding-modal-from-mr-widget-security-reports' into 'master'

Remove old finding modal from mr widget security reports

See merge request https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144341



Merged-by: default avatarMichał Wielich <mwielich@gitlab.com>
Approved-by: default avatarRoss Byrne <robyrne@gitlab.com>
Approved-by: default avatarDavid Pisek <dpisek@gitlab.com>
Approved-by: default avatarSavas Vedova <svedova@gitlab.com>
Approved-by: default avatarMichał Wielich <mwielich@gitlab.com>
Reviewed-by: default avatarDavid Pisek <dpisek@gitlab.com>
Co-authored-by: default avatarlorenzvanherwaarden <lvanherwaarden@gitlab.com>
No related branches found
No related tags found
无相关合并请求
...@@ -3,29 +3,14 @@ import { GlBadge, GlButton } from '@gitlab/ui'; ...@@ -3,29 +3,14 @@ import { GlBadge, GlButton } from '@gitlab/ui';
import { SEVERITY_LEVELS } from 'ee/security_dashboard/store/constants'; import { SEVERITY_LEVELS } from 'ee/security_dashboard/store/constants';
import MrWidget from '~/vue_merge_request_widget/components/widget/widget.vue'; import MrWidget from '~/vue_merge_request_widget/components/widget/widget.vue';
import MrWidgetRow from '~/vue_merge_request_widget/components/widget/widget_content_row.vue'; import MrWidgetRow from '~/vue_merge_request_widget/components/widget/widget_content_row.vue';
import toast from '~/vue_shared/plugins/global_toast';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility'; import { s__ } from '~/locale';
import { s__, sprintf } from '~/locale';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { TYPENAME_PROJECT } from '~/graphql_shared/constants';
import FindingModal from 'ee/vue_shared/security_reports/components/modal.vue';
import { VULNERABILITY_MODAL_ID } from 'ee/vue_shared/security_reports/components/constants';
import findingQuery from 'ee/security_dashboard/graphql/queries/mr_widget_finding.query.graphql';
import dismissFindingMutation from 'ee/security_dashboard/graphql/mutations/dismiss_finding.mutation.graphql';
import revertFindingToDetectedMutation from 'ee/security_dashboard/graphql/mutations/revert_finding_to_detected.mutation.graphql';
import createIssueMutation from 'ee/security_dashboard/graphql/mutations/finding_create_issue.mutation.graphql';
import SummaryHighlights from 'ee/vue_shared/security_reports/components/summary_highlights.vue'; import SummaryHighlights from 'ee/vue_shared/security_reports/components/summary_highlights.vue';
import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants'; import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants';
import { capitalizeFirstCharacter, convertToCamelCase } from '~/lib/utils/text_utility'; import { capitalizeFirstCharacter, convertToCamelCase } from '~/lib/utils/text_utility';
import { helpPagePath } from '~/helpers/help_page_helper'; import { helpPagePath } from '~/helpers/help_page_helper';
import { CRITICAL, HIGH } from '~/vulnerabilities/constants'; import { CRITICAL, HIGH } from '~/vulnerabilities/constants';
import download from '~/lib/utils/downloader';
import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller'; import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils';
import { getDismissalTransitionForVulnerability } from 'ee/vue_shared/security_reports/components/helpers';
import SummaryText, { MAX_NEW_VULNERABILITIES } from './summary_text.vue'; import SummaryText, { MAX_NEW_VULNERABILITIES } from './summary_text.vue';
import SecurityTrainingPromoWidget from './security_training_promo_widget.vue'; import SecurityTrainingPromoWidget from './security_training_promo_widget.vue';
import { i18n, popovers, reportTypes } from './i18n'; import { i18n, popovers, reportTypes } from './i18n';
...@@ -33,7 +18,6 @@ import { i18n, popovers, reportTypes } from './i18n'; ...@@ -33,7 +18,6 @@ import { i18n, popovers, reportTypes } from './i18n';
export default { export default {
name: 'WidgetSecurityReports', name: 'WidgetSecurityReports',
components: { components: {
FindingModal,
VulnerabilityFindingModal: () => VulnerabilityFindingModal: () =>
import('ee/security_dashboard/components/pipeline/vulnerability_finding_modal.vue'), import('ee/security_dashboard/components/pipeline/vulnerability_finding_modal.vue'),
MrWidget, MrWidget,
...@@ -46,7 +30,6 @@ export default { ...@@ -46,7 +30,6 @@ export default {
DynamicScroller, DynamicScroller,
DynamicScrollerItem, DynamicScrollerItem,
}, },
mixins: [glFeatureFlagsMixin()],
i18n, i18n,
props: { props: {
mr: { mr: {
...@@ -57,9 +40,6 @@ export default { ...@@ -57,9 +40,6 @@ export default {
data() { data() {
return { return {
isLoading: true, isLoading: true,
isCreatingIssue: false,
isDismissingFinding: false,
isCreatingMergeRequest: false,
hasAtLeastOneReportWithMaxNewVulnerabilities: false, hasAtLeastOneReportWithMaxNewVulnerabilities: false,
modalData: null, modalData: null,
topLevelErrorMessage: '', topLevelErrorMessage: '',
...@@ -67,64 +47,6 @@ export default { ...@@ -67,64 +47,6 @@ export default {
}; };
}, },
apollo: {
securityReportFinding: {
manual: true,
query: findingQuery,
errorPolicy: 'none',
variables() {
return {
fullPath: this.mr.sourceProjectFullPath,
pipelineId: this.pipelineIid,
uuid: this.modalData.vulnerability.uuid,
};
},
error() {
this.modalData.error = this.$options.i18n.findingLoadingError;
},
result({ data }) {
const finding = data.project.pipeline.securityReportFinding;
const { mergeRequest, vulnerability } = finding;
if (mergeRequest) {
this.$set(this.modalData.vulnerability, 'hasMergeRequest', true);
const mergeRequestData = {
author: mergeRequest.author,
merge_request_path: mergeRequest.webUrl,
created_at: mergeRequest.createdAt,
merge_request_iid: mergeRequest.iid,
};
this.modalData.vulnerability.merge_request_links = [mergeRequestData];
}
const issue = finding.issueLinks?.nodes.find((x) => x.linkType === 'CREATED')?.issue;
if (issue) {
this.$set(this.modalData.vulnerability, 'hasIssue', true);
const issueData = {
author: issue.author,
created_at: issue.createdAt,
issue_url: issue.webUrl,
issue_iid: issue.iid,
link_type: 'created',
};
this.modalData.vulnerability.issue_links = [issueData];
}
this.modalData.vulnerability.state_transitions = vulnerability
? vulnerability.stateTransitions.nodes.map(convertObjectPropsToSnakeCase)
: [];
},
skip() {
return !this.modalData;
},
},
},
computed: { computed: {
reports() { reports() {
return this.endpoints return this.endpoints
...@@ -228,17 +150,6 @@ export default { ...@@ -228,17 +150,6 @@ export default {
return EXTENSION_ICONS.success; return EXTENSION_ICONS.success;
}, },
hasCreateIssuePath() {
return Boolean(
this.mr.createVulnerabilityFeedbackIssuePath ||
this.modalData?.vulnerability?.create_jira_issue_url,
);
},
canDismissFinding() {
return Boolean(this.mr.createVulnerabilityFeedbackDismissalPath);
},
actionButtons() { actionButtons() {
return [ return [
{ {
...@@ -249,10 +160,6 @@ export default { ...@@ -249,10 +160,6 @@ export default {
]; ];
}, },
showStandaloneFindingModal() {
return this.glFeatures.standaloneFindingModalMergeRequestWidget && this.modalData;
},
endpoints() { endpoints() {
// TODO: check if gl.mrWidgetData can be safely removed after we migrate to the // TODO: check if gl.mrWidgetData can be safely removed after we migrate to the
// widget extension. // widget extension.
...@@ -397,209 +304,7 @@ export default { ...@@ -397,209 +304,7 @@ export default {
error: null, error: null,
title: finding.name, title: finding.name,
vulnerability: finding, vulnerability: finding,
isShowingDeleteButtons: false,
}; };
this.isDismissingFinding = false;
this.$root.$emit(BV_SHOW_MODAL, VULNERABILITY_MODAL_ID);
},
createNewIssue() {
this.isCreatingIssue = true;
const finding = this.modalData?.vulnerability;
this.$apollo
.mutate({
mutation: createIssueMutation,
variables: {
projectId: convertToGraphQLId(TYPENAME_PROJECT, finding.project.id),
findingUuid: finding.uuid,
},
})
.then(({ data }) => {
visitUrl(data.securityFindingCreateIssue.issue.webUrl);
})
.catch(() => {
this.isCreatingIssue = false;
this.modalData.error = s__(
'ciReport|There was an error creating the issue. Please try again.',
);
});
},
dismissFinding(comment, toastMsg, errorMsg) {
const finding = this.modalData?.vulnerability;
this.isDismissingFinding = true;
this.$apollo
.mutate({
mutation: dismissFindingMutation,
refetchQueries: [findingQuery],
variables: {
uuid: finding.uuid,
comment,
},
})
.then(({ data }) => {
const { errors } = data.securityFindingDismiss;
if (errors.length > 0) {
this.modalData.error = sprintf(
s__('ciReport|There was an error dismissing the vulnerability: %{error}'),
{ error: errors[0] },
);
return;
}
this.modalData.vulnerability.state = 'dismissed';
this.hideModal();
toast(
toastMsg ||
sprintf(s__("SecurityReports|Dismissed '%{vulnerabilityName}'"), {
vulnerabilityName: finding.name,
}),
);
})
.catch(() => {
this.modalData.error =
errorMsg ||
s__('ciReport|There was an error dismissing the vulnerability. Please try again.');
})
.finally(() => {
this.isDismissingFinding = false;
});
},
revertDismissVulnerability() {
this.isDismissingFinding = true;
this.$apollo
.mutate({
mutation: revertFindingToDetectedMutation,
refetchQueries: [findingQuery],
variables: {
uuid: this.modalData.vulnerability.uuid,
},
})
.then(({ data }) => {
const { errors } = data.securityFindingRevertToDetected;
if (errors.length > 0) {
this.modalData.error = sprintf(
s__('ciReport|There was an error reverting the dismissal: %{error}'),
{ error: errors[0] },
);
return;
}
this.modalData.vulnerability.state = 'detected';
this.modalData.vulnerability.dismissal_feedback = null;
this.hideModal();
})
.catch(() => {
this.modalData.error = s__(
'ciReport|There was an error reverting the dismissal. Please try again.',
);
})
.finally(() => {
this.isDismissingFinding = false;
});
},
openDismissalCommentBox() {
this.$set(this.modalData, 'isCommentingOnDismissal', true);
},
closeDismissalCommentBox() {
this.$set(this.modalData, 'isCommentingOnDismissal', false);
},
addDismissalComment(comment) {
const finding = this.modalData.vulnerability;
const isEditingDismissalContent = Boolean(
getDismissalTransitionForVulnerability(finding).comment,
);
const errorMsg = s__('SecurityReports|There was an error adding the comment.');
const toastMsg = isEditingDismissalContent
? sprintf(s__("SecurityReports|Comment edited on '%{vulnerabilityName}'"), {
vulnerabilityName: finding.name,
})
: sprintf(s__("SecurityReports|Comment added to '%{vulnerabilityName}'"), {
vulnerabilityName: finding.name,
});
this.dismissFinding(comment, toastMsg, errorMsg);
},
hideDismissalDeleteButtons() {
this.modalData.isShowingDeleteButtons = false;
},
showDismissalDeleteButtons() {
this.modalData.isShowingDeleteButtons = true;
},
deleteDismissalComment() {
const { vulnerability: finding } = this.modalData;
const errorMsg = s__('SecurityReports|There was an error deleting the comment.');
const toastMsg = sprintf(s__("SecurityReports|Comment deleted on '%{vulnerabilityName}'"), {
vulnerabilityName: finding.name,
});
// This will cause the spinner to be displayed
this.isDismissingFinding = true;
this.dismissFinding(undefined, toastMsg, errorMsg);
},
createMergeRequest() {
const finding = this.modalData.vulnerability;
finding.target_branch = this.mr.sourceBranch;
this.isCreatingMergeRequest = true;
axios
.post(this.mr.createVulnerabilityFeedbackMergeRequestPath, {
vulnerability_feedback: {
feedback_type: 'merge_request',
category: finding.report_type,
project_fingerprint: finding.project_fingerprint,
finding_uuid: finding.uuid,
vulnerability_data: { ...finding, category: finding.report_type },
},
})
.then(({ data }) => {
const url = data.merge_request_links.at(-1).merge_request_path;
visitUrl(url);
})
.catch(() => {
this.isCreatingMergeRequest = false;
this.modalData.error = s__(
'ciReport|There was an error creating the merge request. Please try again.',
);
});
},
downloadPatch() {
download({
fileData: this.modalData.vulnerability.remediations[0].diff,
fileName: 'remediation.patch',
});
},
hideModal() {
this.$root.$emit(BV_HIDE_MODAL, VULNERABILITY_MODAL_ID);
}, },
clearModalData() { clearModalData() {
...@@ -656,7 +361,7 @@ export default { ...@@ -656,7 +361,7 @@ export default {
</template> </template>
<template #content> <template #content>
<vulnerability-finding-modal <vulnerability-finding-modal
v-if="showStandaloneFindingModal" v-if="modalData"
:finding-uuid="modalData.vulnerability.uuid" :finding-uuid="modalData.vulnerability.uuid"
:pipeline-iid="pipelineIid" :pipeline-iid="pipelineIid"
:project-full-path="mr.targetProjectFullPath" :project-full-path="mr.targetProjectFullPath"
...@@ -664,30 +369,6 @@ export default { ...@@ -664,30 +369,6 @@ export default {
@dismissed="updateFindingState('dismissed')" @dismissed="updateFindingState('dismissed')"
@detected="updateFindingState('detected')" @detected="updateFindingState('detected')"
/> />
<finding-modal
v-else-if="modalData"
:visible="true"
:modal="modalData"
:is-dismissing-vulnerability="isDismissingFinding"
:is-creating-merge-request="isCreatingMergeRequest"
:is-creating-issue="isCreatingIssue"
:is-loading-additional-info="$apollo.queries.securityReportFinding.loading"
:can-create-issue="hasCreateIssuePath"
:can-dismiss-vulnerability="canDismissFinding"
@addDismissalComment="addDismissalComment"
@createMergeRequest="createMergeRequest"
@closeDismissalCommentBox="closeDismissalCommentBox"
@openDismissalCommentBox="openDismissalCommentBox"
@editVulnerabilityDismissalComment="openDismissalCommentBox"
@deleteDismissalComment="deleteDismissalComment"
@downloadPatch="downloadPatch"
@revertDismissVulnerability="revertDismissVulnerability"
@createNewIssue="createNewIssue"
@dismissVulnerability="dismissFinding"
@showDismissalDeleteButtons="showDismissalDeleteButtons"
@hideDismissalDeleteButtons="hideDismissalDeleteButtons"
@hidden="clearModalData"
/>
<security-training-promo-widget <security-training-promo-widget
:security-configuration-path="mr.securityConfigurationPath" :security-configuration-path="mr.securityConfigurationPath"
:project-full-path="mr.sourceProjectFullPath" :project-full-path="mr.sourceProjectFullPath"
......
...@@ -11,7 +11,6 @@ module MergeRequestsController ...@@ -11,7 +11,6 @@ module MergeRequestsController
before_action only: [:show] do before_action only: [:show] do
push_frontend_feature_flag(:anonymous_visual_review_feedback) push_frontend_feature_flag(:anonymous_visual_review_feedback)
push_frontend_feature_flag(:standalone_finding_modal_merge_request_widget, @project)
push_frontend_feature_flag(:merge_trains_skip_train, @project) push_frontend_feature_flag(:merge_trains_skip_train, @project)
end end
......
---
name: standalone_finding_modal_merge_request_widget
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/413516
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/425936
milestone: '16.5'
type: development
group: group::threat insights
default_enabled: true
...@@ -441,78 +441,3 @@ export const emptyResponse = () => ({ ...@@ -441,78 +441,3 @@ export const emptyResponse = () => ({
added: [], added: [],
fixed: [], fixed: [],
}); });
export const findingMockData = {
id: 'b58fadc9-e4af-5404-ba6b-e4ee14801c6f',
stateComment: 'Existing comment',
dismissedAt: '2023-03-07T10:50:09Z',
dismissedBy: {
name: 'Administrator',
username: 'root',
webUrl: 'http://gdk.test:3000/root',
id: 'gid://gitlab/User/15',
},
vulnerability: {
id: 1,
stateTransitions: {
nodes: [
{
comment: 'Existing comment',
toState: 'DISMISSED',
createdAt: '2023-03-07T10:50:09Z',
author: {
name: 'Administrator',
username: 'root',
webUrl: 'http://gdk.test:3000/root',
id: 'gid://gitlab/User/15',
},
},
],
},
},
mergeRequest: {
id: 'git://gitlab/MergeRequest/7',
iid: 7,
webUrl: 'http://gdk.test:3000/root/security-reports-v2/-/merge_requests/7',
createdAt: '2023-03-07T10:50:09Z',
author: {
id: 'gid://gitlab/User/1',
name: 'Administrator',
username: 'root',
webUrl: 'http://gdk.test:3000/root',
},
},
issueLinks: {
nodes: [
{
id: 'git://gitlab/IssueLink/1',
linkType: 'CREATED',
issue: {
id: 'gid://gitlab/Issue/2',
iid: '2',
webUrl: 'http://gdk.test:3000/root/security-reports-v2/-/issues/2',
createdAt: '2023-03-07T10:50:09Z',
author: {
id: 'gid://gitlab/User/1',
name: 'Administrator',
username: 'root',
webUrl: 'http://gdk.test:3000/root',
},
},
},
],
},
};
export const findingQueryMockData = () =>
jest.fn().mockResolvedValue({
data: {
project: {
id: 'gid://gitlab/Project/11',
pipeline: {
id: 'gid://gitlab/Ci::Pipeline/13',
securityReportFinding: findingMockData,
},
},
},
});
...@@ -58764,24 +58764,9 @@ msgstr "" ...@@ -58764,24 +58764,9 @@ msgstr ""
msgid "ciReport|TTFB P95" msgid "ciReport|TTFB P95"
msgstr "" msgstr ""
   
msgid "ciReport|There was an error creating the issue. Please try again."
msgstr ""
msgid "ciReport|There was an error creating the merge request. Please try again." msgid "ciReport|There was an error creating the merge request. Please try again."
msgstr "" msgstr ""
   
msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
msgstr ""
msgid "ciReport|There was an error dismissing the vulnerability: %{error}"
msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
msgid "ciReport|There was an error reverting the dismissal: %{error}"
msgstr ""
msgid "ciReport|This report contains all Code Quality issues in the source branch." msgid "ciReport|This report contains all Code Quality issues in the source branch."
msgstr "" msgstr ""
   
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册