From 285dfef529c9c7997ce6cc29b8eea7ff28972a8f Mon Sep 17 00:00:00 2001
From: Sri <srirangan@gmail.com>
Date: Fri, 11 Feb 2022 12:45:22 +0000
Subject: [PATCH] Include secret manager tip in service accounts list

`Project :: Infra :: Google Cloud` contains a component that
lists out service accounts for the user.

Let's include a tip that encourages users to learn more
about storing and maintaining secrets with a dedicated secret
manager.

This commit also refactors strings and introduces a component
level `i18n` object.
---
 .../components/service_accounts_list.vue      | 48 ++++++++++++++-----
 locale/gitlab.pot                             | 12 +++--
 .../components/service_accounts_list_spec.js  | 19 +++++---
 3 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/app/assets/javascripts/google_cloud/components/service_accounts_list.vue b/app/assets/javascripts/google_cloud/components/service_accounts_list.vue
index b70b25a5dc36..4db847464820 100644
--- a/app/assets/javascripts/google_cloud/components/service_accounts_list.vue
+++ b/app/assets/javascripts/google_cloud/components/service_accounts_list.vue
@@ -1,9 +1,9 @@
 <script>
-import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import { GlAlert, GlButton, GlEmptyState, GlLink, GlSprintf, GlTable } from '@gitlab/ui';
 import { __ } from '~/locale';
 
 export default {
-  components: { GlButton, GlEmptyState, GlTable },
+  components: { GlAlert, GlButton, GlEmptyState, GlLink, GlSprintf, GlTable },
   props: {
     list: {
       type: Array,
@@ -28,6 +28,22 @@ export default {
       ],
     };
   },
+  i18n: {
+    createServiceAccount: __('Create service account'),
+    found: __('✔'),
+    notFound: __('Not found'),
+    noServiceAccountsTitle: __('No service accounts'),
+    noServiceAccountsDescription: __(
+      'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
+    ),
+    serviceAccountsTitle: __('Service accounts'),
+    serviceAccountsDescription: __(
+      'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
+    ),
+    secretManagersDescription: __(
+      'Enhance security by storing service account keys in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}',
+    ),
+  },
 };
 </script>
 
@@ -35,31 +51,39 @@ export default {
   <div>
     <gl-empty-state
       v-if="list.length === 0"
-      :title="__('No service accounts')"
-      :description="
-        __('Service Accounts keys authorize GitLab to deploy your Google Cloud project')
-      "
+      :title="$options.i18n.noServiceAccountsTitle"
+      :description="$options.i18n.noServiceAccountsDescription"
       :primary-button-link="createUrl"
-      :primary-button-text="__('Create service account')"
+      :primary-button-text="$options.i18n.createServiceAccount"
       :svg-path="emptyIllustrationUrl"
     />
 
     <div v-else>
-      <h2 class="gl-font-size-h2">{{ __('Service Accounts') }}</h2>
-      <p>{{ __('Service Accounts keys authorize GitLab to deploy your Google Cloud project') }}</p>
+      <h2 class="gl-font-size-h2">{{ $options.i18n.serviceAccountsTitle }}</h2>
+      <p>{{ $options.i18n.serviceAccountsDescription }}</p>
 
       <gl-table :items="list" :fields="tableFields">
         <template #cell(service_account_exists)="{ value }">
-          {{ value ? '✔' : __('Not found') }}
+          {{ value ? $options.i18n.found : $options.i18n.notFound }}
         </template>
         <template #cell(service_account_key_exists)="{ value }">
-          {{ value ? '✔' : __('Not found') }}
+          {{ value ? $options.i18n.found : $options.i18n.notFound }}
         </template>
       </gl-table>
 
       <gl-button :href="createUrl" category="primary" variant="info">
-        {{ __('Create service account') }}
+        {{ $options.i18n.createServiceAccount }}
       </gl-button>
+
+      <gl-alert class="gl-mt-5" :dismissible="false" variant="tip">
+        <gl-sprintf :message="$options.i18n.secretManagersDescription">
+          <template #docLink="{ content }">
+            <gl-link href="https://docs.gitlab.com/ee/ci/secrets/">
+              {{ content }}
+            </gl-link>
+          </template>
+        </gl-sprintf>
+      </gl-alert>
     </div>
   </div>
 </template>
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 76f157581cdd..37737fbc3f3b 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -13619,6 +13619,9 @@ msgstr ""
 msgid "Enforce two-factor authentication for all user sign-ins."
 msgstr ""
 
+msgid "Enhance security by storing service account keys in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
+msgstr ""
+
 msgid "Ensure connectivity is available from the GitLab server to the Prometheus server"
 msgstr ""
 
@@ -33032,9 +33035,6 @@ msgstr ""
 msgid "Service Account Key"
 msgstr ""
 
-msgid "Service Accounts"
-msgstr ""
-
 msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
 msgstr ""
 
@@ -33047,6 +33047,9 @@ msgstr ""
 msgid "Service account generated successfully"
 msgstr ""
 
+msgid "Service accounts"
+msgstr ""
+
 msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
 msgstr ""
 
@@ -44133,3 +44136,6 @@ msgstr ""
 
 msgid "{project}"
 msgstr ""
+
+msgid "✔"
+msgstr ""
diff --git a/spec/frontend/google_cloud/components/service_accounts_list_spec.js b/spec/frontend/google_cloud/components/service_accounts_list_spec.js
index cdb3f74051cb..f7051c8a53d9 100644
--- a/spec/frontend/google_cloud/components/service_accounts_list_spec.js
+++ b/spec/frontend/google_cloud/components/service_accounts_list_spec.js
@@ -1,5 +1,5 @@
 import { mount } from '@vue/test-utils';
-import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import { GlAlert, GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
 import ServiceAccountsList from '~/google_cloud/components/service_accounts_list.vue';
 
 describe('ServiceAccounts component', () => {
@@ -28,7 +28,7 @@ describe('ServiceAccounts component', () => {
     it('shows the link to create new service accounts', () => {
       const button = findButtonInEmptyState();
       expect(button.exists()).toBe(true);
-      expect(button.text()).toBe('Create service account');
+      expect(button.text()).toBe(ServiceAccountsList.i18n.createServiceAccount);
       expect(button.attributes('href')).toBe('#create-url');
     });
   });
@@ -41,6 +41,7 @@ describe('ServiceAccounts component', () => {
     const findTable = () => wrapper.findComponent(GlTable);
     const findRows = () => findTable().findAll('tr');
     const findButton = () => wrapper.findComponent(GlButton);
+    const findSecretManagerTip = () => wrapper.findComponent(GlAlert);
 
     beforeEach(() => {
       const propsData = {
@@ -52,13 +53,11 @@ describe('ServiceAccounts component', () => {
     });
 
     it('shows the title', () => {
-      expect(findTitle().text()).toBe('Service Accounts');
+      expect(findTitle().text()).toBe(ServiceAccountsList.i18n.serviceAccountsTitle);
     });
 
     it('shows the description', () => {
-      expect(findDescription().text()).toBe(
-        'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
-      );
+      expect(findDescription().text()).toBe(ServiceAccountsList.i18n.serviceAccountsDescription);
     });
 
     it('shows the table', () => {
@@ -72,8 +71,14 @@ describe('ServiceAccounts component', () => {
     it('shows the link to create new service accounts', () => {
       const button = findButton();
       expect(button.exists()).toBe(true);
-      expect(button.text()).toBe('Create service account');
+      expect(button.text()).toBe(ServiceAccountsList.i18n.createServiceAccount);
       expect(button.attributes('href')).toBe('#create-url');
     });
+
+    it('must contain secret managers tip', () => {
+      const tip = findSecretManagerTip();
+      const expectedText = ServiceAccountsList.i18n.secretManagersDescription.substr(0, 48);
+      expect(tip.text()).toContain(expectedText);
+    });
   });
 });
-- 
GitLab