diff --git a/ee/app/assets/javascripts/on_demand_scans_form/components/on_demand_scans_form.vue b/ee/app/assets/javascripts/on_demand_scans_form/components/on_demand_scans_form.vue index cb205acefd9cbeef64bf8dbb355936b03a03a4e8..842ee7fc2f00050bf89b1550054379ea5a4500f1 100644 --- a/ee/app/assets/javascripts/on_demand_scans_form/components/on_demand_scans_form.vue +++ b/ee/app/assets/javascripts/on_demand_scans_form/components/on_demand_scans_form.vue @@ -173,7 +173,12 @@ export default { SITE_PROFILES_QUERY, ), }, - inject: ['projectPath', 'onDemandScansPath'], + inject: [ + 'projectPath', + 'onDemandScansPath', + 'siteProfilesLibraryPath', + 'scannerProfilesLibraryPath', + ], props: { defaultBranch: { type: String, @@ -505,6 +510,8 @@ export default { v-if="glFeatures.dastUiRedesign" :saved-profiles="dastScan" :full-path="projectPath" + :scanner-profiles-library-path="scannerProfilesLibraryPath" + :site-profiles-library-path="siteProfilesLibraryPath" @error="showErrors" @profiles-selected="selectProfiles" /> diff --git a/ee/app/assets/javascripts/security_configuration/dast/components/configuration_form.vue b/ee/app/assets/javascripts/security_configuration/dast/components/configuration_form.vue index 7c1cc274c36710a5028ed3c1ee12ee373d8a02dc..6ff3c730c7df7b746eb4014740deff60e70ee1f0 100644 --- a/ee/app/assets/javascripts/security_configuration/dast/components/configuration_form.vue +++ b/ee/app/assets/javascripts/security_configuration/dast/components/configuration_form.vue @@ -30,7 +30,13 @@ export default { DastProfilesConfigurator, }, mixins: [glFeatureFlagMixin()], - inject: ['gitlabCiYamlEditPath', 'securityConfigurationPath', 'projectPath'], + inject: [ + 'gitlabCiYamlEditPath', + 'securityConfigurationPath', + 'projectPath', + 'siteProfilesLibraryPath', + 'scannerProfilesLibraryPath', + ], i18n: { dastConfigurationHeader: s__('DastConfig|DAST CI/CD configuration'), dastConfigurationDescription: s__( @@ -88,6 +94,8 @@ export default { :configuration-header="$options.i18n.dastConfigurationHeader" class="gl-mb-6" :full-path="projectPath" + :scanner-profiles-library-path="scannerProfilesLibraryPath" + :site-profiles-library-path="siteProfilesLibraryPath" @error="showErrors" @profiles-selected="updateProfiles" > diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator.vue b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator.vue index ecf3d7ec110a0d92fca6a6ec9c38996ce97018b1..fe846639349536dc5e8ecc1600d0e72b31173e4c 100644 --- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator.vue +++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator.vue @@ -92,6 +92,16 @@ export default { required: false, default: '', }, + siteProfilesLibraryPath: { + type: String, + required: false, + default: '', + }, + scannerProfilesLibraryPath: { + type: String, + required: false, + default: '', + }, }, data() { return { @@ -116,10 +126,11 @@ export default { isLoadingProfiles() { return ['scannerProfiles', 'siteProfiles'].some((name) => this.$apollo.queries[name].loading); }, + isScannerProfile() { + return this.profileType === SCANNER_TYPE; + }, profileIdInUse() { - return this.profileType === SCANNER_TYPE - ? this.savedScannerProfileId - : this.savedSiteProfileId; + return this.isScannerProfile ? this.savedScannerProfileId : this.savedSiteProfileId; }, savedScannerProfileId() { return this.savedProfiles?.dastScannerProfile.id; @@ -138,12 +149,13 @@ export default { : null; }, selectedProfileId() { - return this.profileType === SCANNER_TYPE - ? this.selectedScannerProfileId - : this.selectedSiteProfileId; + return this.isScannerProfile ? this.selectedScannerProfileId : this.selectedSiteProfileId; }, selectedProfiles() { - return this.profileType === SCANNER_TYPE ? this.scannerProfiles : this.siteProfiles; + return this.isScannerProfile ? this.scannerProfiles : this.siteProfiles; + }, + libraryLink() { + return this.isScannerProfile ? this.scannerProfilesLibraryPath : this.siteProfilesLibraryPath; }, }, watch: { @@ -269,6 +281,7 @@ export default { :profiles="selectedProfiles" :profile-id-in-use="profileIdInUse" :active-profile="activeProfile" + :library-link="libraryLink" :profile-type="profileType" :is-open="isSideDrawerOpen" :is-loading="isLoadingProfiles" diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue index b7591ab750891489861a3447ccd8bf5752f4c613..1418a059b0f80747fc7efeb784b2a2718f338244 100644 --- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue +++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue @@ -1,6 +1,7 @@ <script> import { isEmpty } from 'lodash'; -import { GlDrawer } from '@gitlab/ui'; +import { GlDrawer, GlLink } from '@gitlab/ui'; +import { s__, sprintf } from '~/locale'; import { SCANNER_TYPE, SIDEBAR_VIEW_MODE } from 'ee/on_demand_scans/constants'; import { REFERRAL } from 'ee/security_configuration/dast_profiles/dast_scanner_profiles/constants'; import DastProfilesLoader from 'ee/security_configuration/dast_profiles/components/dast_profiles_loader.vue'; @@ -32,8 +33,12 @@ import DastProfilesSidebarList from './dast_profiles_sidebar_list.vue'; export default { SIDEBAR_VIEW_MODE, + i18n: { + footerLinkText: s__('DastProfiles|Manage %{profileType} profiles'), + }, components: { GlDrawer, + GlLink, DastProfilesLoader, DastProfilesSidebarHeader, DastProfilesSidebarEmptyState, @@ -92,6 +97,11 @@ export default { required: false, default: SIDEBAR_VIEW_MODE.READING_MODE, }, + libraryLink: { + type: String, + required: false, + default: null, + }, }, data() { return { @@ -115,6 +125,11 @@ export default { isEditingMode() { return this.sidebarViewMode === SIDEBAR_VIEW_MODE.EDITING_MODE; }, + footerLinkText() { + return sprintf(this.$options.i18n.footerLinkText, { + profileType: this.profileType, + }); + }, }, /** * Only if activeProfile is passed from parent @@ -231,5 +246,12 @@ export default { /> </template> </template> + <template v-if="libraryLink" #footer> + <div class="gl-w-full gl-text-center"> + <gl-link :href="libraryLink"> + {{ footerLinkText }} + </gl-link> + </div> + </template> </gl-drawer> </template> diff --git a/ee/spec/frontend/security_configuration/dast/components/configuration_form_spec.js b/ee/spec/frontend/security_configuration/dast/components/configuration_form_spec.js index 486709cffa55481aa800c0dac51f3a8305e85c33..77bd433b0c81945a7d721fad59fda865eff97e44 100644 --- a/ee/spec/frontend/security_configuration/dast/components/configuration_form_spec.js +++ b/ee/spec/frontend/security_configuration/dast/components/configuration_form_spec.js @@ -19,6 +19,8 @@ const [siteProfile] = siteProfiles; const securityConfigurationPath = '/security/configuration'; const gitlabCiYamlEditPath = '/ci/editor'; const projectPath = '/project/path'; +const siteProfilesLibraryPath = 'siteProfilesLibraryPath'; +const scannerProfilesLibraryPath = 'scannerProfilesLibraryPath'; const selectedScannerProfileName = 'My Scan profile'; const selectedSiteProfileName = 'My site profile'; @@ -75,6 +77,8 @@ describe('EE - DAST Configuration Form', () => { provide: { securityConfigurationPath, gitlabCiYamlEditPath, + scannerProfilesLibraryPath, + siteProfilesLibraryPath, projectPath, ...glFeatures, }, diff --git a/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar_spec.js b/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar_spec.js index 1d2c2dcd50a11d94e39536b018c93fa458f86946..df6dc097fda643b0e0b24b53dd84e9e62fa0def5 100644 --- a/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar_spec.js +++ b/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar_spec.js @@ -1,5 +1,6 @@ -import { GlDrawer } from '@gitlab/ui'; +import { GlDrawer, GlLink } from '@gitlab/ui'; import { nextTick } from 'vue'; +import { __ } from '~/locale'; import { mountExtended } from 'helpers/vue_test_utils_helper'; import DastProfilesSidebar from 'ee/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue'; import DastProfilesLoader from 'ee/security_configuration/dast_profiles/components/dast_profiles_loader.vue'; @@ -9,6 +10,7 @@ import { SCANNER_TYPE, SITE_TYPE, SIDEBAR_VIEW_MODE } from 'ee/on_demand_scans/c describe('DastProfilesSidebar', () => { let wrapper; const projectPath = 'projectPath'; + const libraryLink = 'libraryLink'; const createComponent = (options = {}) => { wrapper = mountExtended(DastProfilesSidebar, { @@ -27,6 +29,7 @@ describe('DastProfilesSidebar', () => { const findSidebarHeader = () => wrapper.findByTestId('sidebar-header'); const findEmptyStateHeader = () => wrapper.findByTestId('empty-state-header'); const findNewScanButton = () => wrapper.findByTestId('new-profile-button'); + const findFooterLink = () => wrapper.findComponent(GlLink); const findEmptyNewScanButton = () => wrapper.findByTestId('new-empty-profile-button'); const findNewDastScannerProfileForm = () => wrapper.findByTestId('dast-scanner-parent-group'); const findCancelButton = () => wrapper.findByTestId('dast-profile-form-cancel-button'); @@ -130,4 +133,17 @@ describe('DastProfilesSidebar', () => { expect(findGlDrawer().props('headerSticky')).toEqual(true); }); }); + + describe('sticky footer', () => { + it.each` + profileType | expectedResult + ${SCANNER_TYPE} | ${__(`Manage ${SCANNER_TYPE} profiles`)} + ${SITE_TYPE} | ${__(`Manage ${SITE_TYPE} profiles`)} + `('renders correctly for $profileType profiles', ({ profileType, expectedResult }) => { + createComponent({ profileType, libraryLink }); + + expect(findFooterLink().text()).toBe(expectedResult); + expect(findFooterLink().attributes('href')).toEqual(libraryLink); + }); + }); }); diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 8c2ae8d59899fb0ca25568c90d3d00f1dbd4f0c5..306bc42ef784eedc1055cac05cc5b60ad3880ee9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -11553,6 +11553,9 @@ msgstr "" msgid "DastProfiles|Include debug messages in the DAST console output." msgstr "" +msgid "DastProfiles|Manage %{profileType} profiles" +msgstr "" + msgid "DastProfiles|Manage profiles" msgstr ""