Skip to content
Snippets Groups Projects
Verified Commit a95e62c8 authored by Michael Becker's avatar Michael Becker Committed by GitLab
Browse files

Merge branch 'fixes-incorrect-vr-button-rendering' into 'master'

Fixes issues with incorrectly displaying VR button

See merge request !166187



Merged-by: default avatarMichael Becker <mbecker@gitlab.com>
Approved-by: default avatarMichael Becker <mbecker@gitlab.com>
Approved-by: Savas Vedova's avatarSavas Vedova <svedova@gitlab.com>
Reviewed-by: default avatarDavid Pisek <dpisek@gitlab.com>
Reviewed-by: default avatarSubashis Chakraborty <schakraborty@gitlab.com>
Co-authored-by: default avatarSamantha Ming <sming@gitlab.com>
Co-authored-by: default avatarDarby Frey <dfrey@gitlab.com>
parents e913da21 bcbd3bd7
No related branches found
No related tags found
2 merge requests!170053Security patch upgrade alert: Only expose to admins 17-4,!166187Fixes issues with incorrectly displaying VR button
Pipeline #1457052197 passed with warnings
Pipeline: E2E Omnibus GitLab EE

#1457116354

    Pipeline: E2E CNG

    #1457116326

      Pipeline: E2E GDK

      #1457073817

        +30
        Showing with 105 additions and 36 deletions
        ......@@ -34156,6 +34156,7 @@ Represents a vulnerability.
        | Name | Type | Description |
        | ---- | ---- | ----------- |
        | <a id="vulnerabilityairesolutionavailable"></a>`aiResolutionAvailable` | [`Boolean`](#boolean) | Indicates whether this type of vulnerability can be resolved with AI. |
        | <a id="vulnerabilityairesolutionenabled"></a>`aiResolutionEnabled` | [`Boolean`](#boolean) | Indicates whether this specific vulnerability can be resolved with AI. |
        | <a id="vulnerabilitycommenters"></a>`commenters` | [`UserCoreConnection!`](#usercoreconnection) | All commenters on this noteable. (see [Connections](#connections)) |
        | <a id="vulnerabilityconfirmedat"></a>`confirmedAt` | [`Time`](#time) | Timestamp of when the vulnerability state was changed to confirmed. |
        | <a id="vulnerabilityconfirmedby"></a>`confirmedBy` | [`UserCore`](#usercore) | User that confirmed the vulnerability. |
        ......@@ -375,10 +375,11 @@ export default {
        :loading="isProcessingAction"
        :show-download-patch="canDownloadPatch"
        :show-create-merge-request="canCreateMergeRequest"
        :show-resolve-with-ai="glAbilities.resolveVulnerabilityWithAi"
        :show-explain-with-ai="glAbilities.explainVulnerabilityWithAi"
        :resolve-with-ai-ability="glAbilities.resolveVulnerabilityWithAi"
        :explain-with-ai-ability="glAbilities.explainVulnerabilityWithAi"
        :ai-explanation-available="vulnerability.aiExplanationAvailable"
        :ai-resolution-available="vulnerability.aiResolutionAvailable"
        :ai-resolution-enabled="vulnerability.aiResolutionEnabled"
        @create-merge-request="createMergeRequest"
        @download-patch="downloadPatch"
        @explain-vulnerability="explainVulnerability"
        ......
        ......@@ -68,12 +68,12 @@ export default {
        required: false,
        default: false,
        },
        showExplainWithAi: {
        explainWithAiAbility: {
        type: Boolean,
        required: false,
        default: false,
        },
        showResolveWithAi: {
        resolveWithAiAbility: {
        type: Boolean,
        required: false,
        default: false,
        ......@@ -88,6 +88,11 @@ export default {
        required: false,
        default: false,
        },
        aiResolutionEnabled: {
        type: Boolean,
        required: false,
        default: false,
        },
        },
        computed: {
        onlyAiActionsAvailable() {
        ......@@ -114,14 +119,14 @@ export default {
        availableActions.push(DOWNLOAD_PATCH_ACTION);
        }
        if (this.showExplainWithAi && this.aiExplanationAvailable) {
        if (this.explainWithAiAbility && this.aiExplanationAvailable) {
        availableActions.push(EXPLAIN_VULNERABILITY_ACTION);
        }
        if (this.showResolveWithAi) {
        if (this.resolveWithAiAbility && this.aiResolutionAvailable) {
        availableActions.push({
        ...RESOLVE_VULNERABILITY_ACTION,
        ...(!this.aiResolutionAvailable && {
        ...(!this.aiResolutionEnabled && {
        disabled: true,
        extraAttrs: { disabled: true },
        description: RESOLVE_VULNERABILITY_ACTION.disabledStateDescription,
        ......
        ......@@ -139,6 +139,10 @@ class VulnerabilityType < BaseObject
        null: true,
        description: 'Indicates whether this type of vulnerability can be resolved with AI.'
        field :ai_resolution_enabled, GraphQL::Types::Boolean,
        null: true,
        description: 'Indicates whether this specific vulnerability can be resolved with AI.'
        markdown_field :description_html, null: true
        def dismissal_reason
        ......@@ -226,6 +230,10 @@ def ai_resolution_available
        object.finding&.ai_resolution_available?
        end
        def ai_resolution_enabled
        object.finding&.ai_resolution_enabled?
        end
        private
        def expose_false_positive?
        ......
        ......@@ -83,6 +83,7 @@ def vulnerability_finding_data(vulnerability)
        data[:solution_html] = markdown(vulnerability.present.solution)
        data[:ai_explanation_available] = vulnerability.finding.ai_explanation_available?
        data[:ai_resolution_available] = vulnerability.finding.ai_resolution_available?
        data[:ai_resolution_enabled] = vulnerability.finding.ai_resolution_enabled?
        data
        end
        end
        ......
        ......@@ -550,7 +550,11 @@ def ai_explanation_available?
        end
        def ai_resolution_available?
        AI_ALLOWED_REPORT_TYPES.include?(report_type) && HIGH_CONFIDENCE_AI_RESOLUTION_CWES.include?(cwe_value&.upcase)
        AI_ALLOWED_REPORT_TYPES.include?(report_type)
        end
        def ai_resolution_enabled?
        ai_resolution_available? && HIGH_CONFIDENCE_AI_RESOLUTION_CWES.include?(cwe_value&.upcase)
        end
        protected
        ......
        ......@@ -350,6 +350,7 @@ describe('Vulnerability Header', () => {
        canCreateMergeRequest: actionsEnabled,
        canDownloadPatch: actionsEnabled,
        aiResolutionAvailable: actionsEnabled,
        aiResolutionEnabled: actionsEnabled,
        }),
        glAbilities: {
        resolveVulnerabilityWithAi: actionsEnabled,
        ......@@ -363,9 +364,10 @@ describe('Vulnerability Header', () => {
        loading: false,
        showDownloadPatch: actionsEnabled,
        showCreateMergeRequest: actionsEnabled,
        showExplainWithAi: actionsEnabled,
        showResolveWithAi: actionsEnabled,
        explainWithAiAbility: actionsEnabled,
        resolveWithAiAbility: actionsEnabled,
        aiResolutionAvailable: actionsEnabled,
        aiResolutionEnabled: actionsEnabled,
        });
        });
        });
        ......
        ......@@ -10,10 +10,11 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
        propsData: {
        showDownloadPatch: false,
        showCreateMergeRequest: false,
        showExplainWithAi: false,
        showResolveWithAi: false,
        explainWithAiAbility: false,
        resolveWithAiAbility: false,
        aiResolutionAvailable: true,
        aiExplanationAvailable: true,
        aiResolutionEnabled: true,
        ...propsData,
        },
        });
        ......@@ -41,7 +42,7 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
        description: "Create a merge request to apply the scanner's software patch.",
        };
        const EXPLAIN_WITH_AI_ACTION = {
        propToEnable: 'showExplainWithAi',
        propToEnable: 'explainWithAiAbility',
        name: 'explain-vulnerability',
        text: 'Explain with AI',
        description:
        ......@@ -49,7 +50,7 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
        icon: 'tanuki-ai',
        };
        const RESOLVE_WITH_AI_ACTION = {
        propToEnable: 'showResolveWithAi',
        propToEnable: 'resolveWithAiAbility',
        name: 'resolve-vulnerability',
        text: 'Resolve with AI',
        description: 'Use GitLab Duo to generate a merge request with a suggested solution.',
        ......@@ -112,8 +113,8 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
        createWrapper({
        showDownloadPatch: true,
        showCreateMergeRequest: true,
        showExplainWithAi: true,
        showResolveWithAi: true,
        explainWithAiAbility: true,
        resolveWithAiAbility: true,
        aiResolutionAvailable: true,
        });
        });
        ......@@ -152,8 +153,8 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
        createWrapper({
        showDownloadPatch: nonAiActionsEnabled,
        showCreateMergeRequest: nonAiActionsEnabled,
        showExplainWithAi: true,
        showResolveWithAi: true,
        explainWithAiAbility: true,
        resolveWithAiAbility: true,
        });
        });
        ......@@ -167,18 +168,31 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
        },
        );
        it.each([true, false])(
        'shows/hides the "Resolve with AI" action when "aiResolutionAvailable is "%s"',
        (aiResolutionAvailable) => {
        createWrapper({
        explainWithAiAbility: true,
        resolveWithAiAbility: true,
        aiResolutionAvailable,
        });
        expect(findActionItem(RESOLVE_WITH_AI_ACTION.name).exists()).toBe(aiResolutionAvailable);
        },
        );
        describe.each`
        aiResolutionAvailable | expectActionToBeDisabled | expectLinkToDocs
        ${true} | ${false} | ${false}
        ${false} | ${true} | ${true}
        aiResolutionEnabled | expectActionToBeDisabled | expectLinkToDocs
        ${true} | ${false} | ${false}
        ${false} | ${true} | ${true}
        `(
        'when the ai-resolution is "$aiResolutionAvailable"',
        ({ aiResolutionAvailable, expectActionToBeDisabled, expectLinkToDocs }) => {
        'when the ai-resolution-enabled is "$aiResolutionEnabled"',
        ({ aiResolutionEnabled, expectActionToBeDisabled, expectLinkToDocs }) => {
        beforeEach(() => {
        createWrapper({
        showExplainWithAi: true,
        showResolveWithAi: true,
        aiResolutionAvailable,
        explainWithAiAbility: true,
        resolveWithAiAbility: true,
        aiResolutionEnabled,
        });
        });
        ......@@ -220,7 +234,7 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
        'shows/hides the "Explain with AI" action when the "aiExplanationAvailable" prop is "%s"',
        (aiExplanationAvailable) => {
        createWrapper({
        showExplainWithAi: true,
        explainWithAiAbility: true,
        aiExplanationAvailable,
        });
        ......
        ......@@ -67,6 +67,7 @@
        present_on_default_branch
        cvss
        aiResolutionAvailable
        aiResolutionEnabled
        ]
        end
        ......@@ -309,6 +310,24 @@
        subject { vulnerabilities.first['aiResolutionAvailable'] }
        context 'when the vulnerability is of type SAST' do
        it { is_expected.to be true }
        end
        context 'when the vulnerability is not of type SAST' do
        before do
        vulnerability.finding.update!(report_type: 'dast')
        end
        it { is_expected.to be false }
        end
        end
        describe 'aiResolutionEnabled' do
        let(:query_field) { 'aiResolutionEnabled' }
        subject { vulnerabilities.first['aiResolutionEnabled'] }
        context 'when the vulnerability is of a supported CWE' do
        before do
        vulnerability.finding.identifiers << create(:vulnerabilities_identifier, external_type: 'cwe', name: 'CWE-23')
        ......
        ......@@ -377,7 +377,8 @@
        issue_links: kind_of(Array),
        merge_request_links: kind_of(Array),
        ai_explanation_available: finding.ai_explanation_available?,
        ai_resolution_available: finding.ai_resolution_available?
        ai_resolution_available: finding.ai_resolution_available?,
        ai_resolution_enabled: finding.ai_resolution_enabled?
        )
        expect(subject[:location]['blob_path']).to match(kind_of(String))
        ......
        ......@@ -1701,23 +1701,36 @@
        describe '#ai_resolution_available?' do
        let(:finding) { build(:vulnerabilities_finding) }
        it 'returns true when the finding is a supported CWE' do
        finding.identifiers << build(:vulnerabilities_identifier, external_type: 'cwe', name: 'CWE-23')
        it 'returns true if the finding is a SAST finding' do
        expect(finding.ai_resolution_available?).to be true
        end
        it 'returns false when the finding is an unsupported CWE' do
        finding.identifiers << build(:vulnerabilities_identifier, external_type: 'cwe', name: 'CWE-1')
        expect(finding.ai_resolution_available?).to be false
        end
        it 'returns false if the finding is not a SAST finding' do
        finding.report_type = 'dast'
        finding.identifiers << build(:vulnerabilities_identifier, external_type: 'cwe', name: 'CWE-23')
        expect(finding.ai_resolution_available?).to be false
        end
        end
        describe '#ai_resolution_enabled?' do
        using RSpec::Parameterized::TableSyntax
        let(:finding) { build(:vulnerabilities_finding) }
        where(:finding_report_type, :cwe, :enabled_value) do
        'sast' | 'CWE-1' | false
        'sast' | 'CWE-23' | true
        'dast' | 'CWE-1' | false
        'dast' | 'CWE-23' | false
        end
        with_them do
        it 'returns the expected value for enabled' do
        finding.report_type = finding_report_type
        finding.identifiers << build(:vulnerabilities_identifier, external_type: 'cwe', name: cwe)
        expect(finding.ai_resolution_enabled?).to be enabled_value
        end
        end
        end
        context 'with loose foreign key on vulnerability_occurrences.project_id' do
        it_behaves_like 'cleanup by a loose foreign key' do
        let_it_be(:parent) { create(:project) }
        ......
        0% Loading or .
        You are about to add 0 people to the discussion. Proceed with caution.
        Finish editing this message first!
        Please register or to comment