From 2bc933fbdac11d9b075a1f668957093bd59ba707 Mon Sep 17 00:00:00 2001
From: Mark Florian <mflorian@gitlab.com>
Date: Thu, 17 Jun 2021 13:03:41 +0100
Subject: [PATCH] Document Security Configuration page redesign

This change also tweaks the appearance of the redesigned Security
Configuration page:

- Adds static text to left column
- Limits the width of the page content
- Adjusts column fractions to 4:8
- Fixes a bug where the configuration history link wasn't displaying
- Moves a line-height class to the SectionLayout component
- Changes the description of DAST Scans to better reflect the feature

Part of https://gitlab.com/gitlab-org/gitlab/-/issues/331614.
---
 .../components/constants.js                   |  4 +-
 .../components/redesigned_app.vue             | 57 +++++++++++--------
 .../components/section_layout.vue             |  6 +-
 .../security/configuration/show.html.haml     |  2 +
 .../configuration/index.md                    | 46 +++++++++++++++
 locale/gitlab.pot                             | 14 +++--
 .../components/redesigned_app_spec.js         | 37 +++++++++---
 7 files changed, 126 insertions(+), 40 deletions(-)

diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index 142dade914b32..f4e060fbcdc07 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -34,8 +34,8 @@ export const DAST_CONFIG_HELP_PATH = helpPagePath('user/application_security/das
 });
 
 export const DAST_PROFILES_NAME = __('DAST Scans');
-export const DAST_PROFILES_DESCRIPTION = __(
-  'Saved scan settings and target site settings which are reusable.',
+export const DAST_PROFILES_DESCRIPTION = s__(
+  'SecurityConfiguration|Manage profiles for use by DAST scans.',
 );
 export const DAST_PROFILES_HELP_PATH = helpPagePath('user/application_security/dast/index');
 export const DAST_PROFILES_CONFIG_TEXT = s__('SecurityConfiguration|Manage scans');
diff --git a/app/assets/javascripts/security_configuration/components/redesigned_app.vue b/app/assets/javascripts/security_configuration/components/redesigned_app.vue
index d8a12f4a792f6..64d908392b5d8 100644
--- a/app/assets/javascripts/security_configuration/components/redesigned_app.vue
+++ b/app/assets/javascripts/security_configuration/components/redesigned_app.vue
@@ -8,12 +8,15 @@ import UpgradeBanner from './upgrade_banner.vue';
 
 export const i18n = {
   compliance: s__('SecurityConfiguration|Compliance'),
+  configurationHistory: s__('SecurityConfiguration|Configuration history'),
   securityTesting: s__('SecurityConfiguration|Security testing'),
-  securityTestingDescription: s__(
+  latestPipelineDescription: s__(
     `SecurityConfiguration|The status of the tools only applies to the
-      default branch and is based on the %{linkStart}latest pipeline%{linkEnd}.
-      Once you've enabled a scan for the default branch, any subsequent feature
-      branch you create will include the scan.`,
+     default branch and is based on the %{linkStart}latest pipeline%{linkEnd}.`,
+  ),
+  description: s__(
+    `SecurityConfiguration|Once you've enabled a scan for the default branch,
+     any subsequent feature branch you create will include the scan.`,
   ),
   securityConfiguration: __('Security Configuration'),
 };
@@ -84,16 +87,19 @@ export default {
       <gl-tab data-testid="security-testing-tab" :title="$options.i18n.securityTesting">
         <section-layout :heading="$options.i18n.securityTesting">
           <template #description>
-            <p
-              v-if="latestPipelinePath"
-              data-testid="latest-pipeline-info-security"
-              class="gl-line-height-20"
-            >
-              <gl-sprintf :message="$options.i18n.securityTestingDescription">
-                <template #link="{ content }">
-                  <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
-                </template>
-              </gl-sprintf>
+            <p>
+              <span data-testid="latest-pipeline-info-security">
+                <gl-sprintf
+                  v-if="latestPipelinePath"
+                  :message="$options.i18n.latestPipelineDescription"
+                >
+                  <template #link="{ content }">
+                    <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
+                  </template>
+                </gl-sprintf>
+              </span>
+
+              {{ $options.i18n.description }}
             </p>
             <p v-if="canViewCiHistory">
               <gl-link data-testid="security-view-history-link" :href="gitlabCiHistoryPath">{{
@@ -115,16 +121,19 @@ export default {
       <gl-tab data-testid="compliance-testing-tab" :title="$options.i18n.compliance">
         <section-layout :heading="$options.i18n.compliance">
           <template #description>
-            <p
-              v-if="latestPipelinePath"
-              class="gl-line-height-20"
-              data-testid="latest-pipeline-info-compliance"
-            >
-              <gl-sprintf :message="$options.i18n.securityTestingDescription">
-                <template #link="{ content }">
-                  <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
-                </template>
-              </gl-sprintf>
+            <p>
+              <span data-testid="latest-pipeline-info-compliance">
+                <gl-sprintf
+                  v-if="latestPipelinePath"
+                  :message="$options.i18n.latestPipelineDescription"
+                >
+                  <template #link="{ content }">
+                    <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
+                  </template>
+                </gl-sprintf>
+              </span>
+
+              {{ $options.i18n.description }}
             </p>
             <p v-if="canViewCiHistory">
               <gl-link data-testid="compliance-view-history-link" :href="gitlabCiHistoryPath">{{
diff --git a/app/assets/javascripts/security_configuration/components/section_layout.vue b/app/assets/javascripts/security_configuration/components/section_layout.vue
index 1e1f83a6d9919..e351f9b9d8da7 100644
--- a/app/assets/javascripts/security_configuration/components/section_layout.vue
+++ b/app/assets/javascripts/security_configuration/components/section_layout.vue
@@ -11,12 +11,12 @@ export default {
 </script>
 
 <template>
-  <div class="row">
-    <div class="col-lg-5">
+  <div class="row gl-line-height-20">
+    <div class="col-lg-4">
       <h2 class="gl-font-size-h2 gl-mt-0">{{ heading }}</h2>
       <slot name="description"></slot>
     </div>
-    <div class="col-lg-7">
+    <div class="col-lg-8">
       <slot name="features"></slot>
     </div>
   </div>
diff --git a/app/views/projects/security/configuration/show.html.haml b/app/views/projects/security/configuration/show.html.haml
index 4d6feb9de6da3..9eb842d101589 100644
--- a/app/views/projects/security/configuration/show.html.haml
+++ b/app/views/projects/security/configuration/show.html.haml
@@ -1,4 +1,6 @@
 - breadcrumb_title _("Security Configuration")
 - page_title _("Security Configuration")
+- redesign_enabled = ::Feature.enabled?(:security_configuration_redesign, default_enabled: :yaml)
+- @content_class = "limit-container-width" unless fluid_layout || !redesign_enabled
 
 #js-security-configuration-static{ data: { project_path: @project.full_path, upgrade_path: security_upgrade_path } }
diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md
index 8c34303ca0069..f2fb11da66e84 100644
--- a/doc/user/application_security/configuration/index.md
+++ b/doc/user/application_security/configuration/index.md
@@ -25,6 +25,27 @@ For each security control the page displays:
 - **Security Control:** Name, description, and a documentation link.
 - **Manage:** A management option or a documentation link.
 
+## UI redesign
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326926) in 14.0 for GitLab Free and Premium, behind a feature flag, disabled by default.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - It can be enabled or disabled for a single project.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-ui-redesign). **(FREE SELF)**
+
+WARNING:
+This feature might not be available to you. Check the **version history** note above for details.
+
+The Security Configuration page has been redesigned in GitLab Free and Premium.
+The same functionality exists as before, but presented in a more extensible
+way.
+
+For each security control the page displays:
+
+- Its name, description and a documentation link.
+- Whether or not it is available.
+- A configuration button or a link to its configuration guide.
+
 ## Status **(ULTIMATE)**
 
 > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20711) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6.
@@ -52,3 +73,28 @@ You can configure the following security controls:
 - Secret Detection
   - Select **Configure via Merge Request** to create a merge request with the changes required to
     enable Secret Detection. For more details, see [Enable Secret Detection via an automatic merge request](../secret_detection/index.md#enable-secret-detection-via-an-automatic-merge-request).
+
+## Enable or disable UI redesign **(FREE SELF)**
+
+The Security Configuration redesign is under development, but is ready for
+production use. It is deployed behind a feature flag that is **disabled by
+default**.
+[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) can enable it.
+
+To enable it:
+
+```ruby
+# For the instance
+Feature.enable(:security_configuration_redesign)
+# For a single project
+Feature.enable(:security_configuration_redesign, Project.find(<project id>))
+```
+
+To disable it:
+
+```ruby
+# For the instance
+Feature.disable(:security_configuration_redesign)
+# For a single project
+Feature.disable(:security_configuration_redesign, Project.find(<project id>))
+```
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index bd43054fda51c..aad534d813580 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -28306,9 +28306,6 @@ msgstr ""
 msgid "Save space and find images in the container Registry. remove unneeded tags and keep only the ones you want. %{linkStart}How does cleanup work?%{linkEnd}"
 msgstr ""
 
-msgid "Saved scan settings and target site settings which are reusable."
-msgstr ""
-
 msgid "Saving"
 msgstr ""
 
@@ -28706,6 +28703,9 @@ msgstr ""
 msgid "SecurityConfiguration|Configuration guide"
 msgstr ""
 
+msgid "SecurityConfiguration|Configuration history"
+msgstr ""
+
 msgid "SecurityConfiguration|Configure"
 msgstr ""
 
@@ -28754,6 +28754,9 @@ msgstr ""
 msgid "SecurityConfiguration|Manage"
 msgstr ""
 
+msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
+msgstr ""
+
 msgid "SecurityConfiguration|Manage scans"
 msgstr ""
 
@@ -28763,6 +28766,9 @@ msgstr ""
 msgid "SecurityConfiguration|Not enabled"
 msgstr ""
 
+msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
 msgid "SecurityConfiguration|Runtime security metrics for application environments."
 msgstr ""
 
@@ -28787,7 +28793,7 @@ msgstr ""
 msgid "SecurityConfiguration|Testing & Compliance"
 msgstr ""
 
-msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
 msgstr ""
 
 msgid "SecurityConfiguration|Upgrade or start a free trial"
diff --git a/spec/frontend/security_configuration/components/redesigned_app_spec.js b/spec/frontend/security_configuration/components/redesigned_app_spec.js
index 7e27a3e11082a..69c79082f5a68 100644
--- a/spec/frontend/security_configuration/components/redesigned_app_spec.js
+++ b/spec/frontend/security_configuration/components/redesigned_app_spec.js
@@ -23,6 +23,7 @@ import {
 } from '~/vue_shared/security_reports/constants';
 
 const upgradePath = '/upgrade';
+const gitlabCiHistoryPath = 'test/historyPath';
 
 describe('redesigned App component', () => {
   let wrapper;
@@ -52,8 +53,28 @@ describe('redesigned App component', () => {
   const findTabs = () => wrapper.findAllComponents(GlTab);
   const findByTestId = (id) => wrapper.findByTestId(id);
   const findFeatureCards = () => wrapper.findAllComponents(FeatureCard);
-  const findComplianceViewHistoryLink = () => findByTestId('compliance-view-history-link');
-  const findSecurityViewHistoryLink = () => findByTestId('security-view-history-link');
+  const findLink = ({ href, text, container = wrapper }) => {
+    const selector = `a[href="${href}"]`;
+    const link = container.find(selector);
+
+    if (link.exists() && link.text() === text) {
+      return link;
+    }
+
+    return wrapper.find(`${selector} does not exist`);
+  };
+  const findSecurityViewHistoryLink = () =>
+    findLink({
+      href: gitlabCiHistoryPath,
+      text: i18n.configurationHistory,
+      container: findByTestId('security-testing-tab'),
+    });
+  const findComplianceViewHistoryLink = () =>
+    findLink({
+      href: gitlabCiHistoryPath,
+      text: i18n.configurationHistory,
+      container: findByTestId('compliance-testing-tab'),
+    });
   const findUpgradeBanner = () => wrapper.findComponent(UpgradeBanner);
 
   const securityFeaturesMock = [
@@ -119,6 +140,10 @@ describe('redesigned App component', () => {
       expect(cards.at(1).props()).toEqual({ feature: complianceFeaturesMock[0] });
     });
 
+    it('renders a basic description', () => {
+      expect(wrapper.text()).toContain(i18n.description);
+    });
+
     it('should not show latest pipeline link when latestPipelinePath is not defined', () => {
       expect(findByTestId('latest-pipeline-info').exists()).toBe(false);
     });
@@ -193,9 +218,8 @@ describe('redesigned App component', () => {
     it('should show latest pipeline info on the security tab  with correct link when latestPipelinePath is defined', () => {
       const latestPipelineInfoSecurity = findByTestId('latest-pipeline-info-security');
 
-      expect(latestPipelineInfoSecurity.exists()).toBe(true);
       expect(latestPipelineInfoSecurity.text()).toMatchInterpolatedText(
-        i18n.securityTestingDescription,
+        i18n.latestPipelineDescription,
       );
       expect(latestPipelineInfoSecurity.find('a').attributes('href')).toBe('test/path');
     });
@@ -203,9 +227,8 @@ describe('redesigned App component', () => {
     it('should show latest pipeline info on the compliance tab  with correct link when latestPipelinePath is defined', () => {
       const latestPipelineInfoCompliance = findByTestId('latest-pipeline-info-compliance');
 
-      expect(latestPipelineInfoCompliance.exists()).toBe(true);
       expect(latestPipelineInfoCompliance.text()).toMatchInterpolatedText(
-        i18n.securityTestingDescription,
+        i18n.latestPipelineDescription,
       );
       expect(latestPipelineInfoCompliance.find('a').attributes('href')).toBe('test/path');
     });
@@ -217,7 +240,7 @@ describe('redesigned App component', () => {
         augmentedSecurityFeatures: securityFeaturesMock,
         augmentedComplianceFeatures: complianceFeaturesMock,
         gitlabCiPresent: true,
-        gitlabCiHistoryPath: 'test/historyPath',
+        gitlabCiHistoryPath,
       });
     });
 
-- 
GitLab