Add Key clear page under Operations section

This page will allow privileged user to clear encrypted keys.
- Only admin and CE login user will be able to see the page
- The UI will be different for both, admin and CE login user(service)
- This page is IBM only

Signed-off-by: Sandeepa Singh <sandeepa.singh@ibm.com>
Change-Id: Ic6fe3454de815629a6b2250daa99ab21f2b316c3
diff --git a/src/components/AppNavigation/AppNavigationMixin.js b/src/components/AppNavigation/AppNavigationMixin.js
index edeabc5..bbbbb1e 100644
--- a/src/components/AppNavigation/AppNavigationMixin.js
+++ b/src/components/AppNavigation/AppNavigationMixin.js
@@ -77,6 +77,11 @@
               route: '/operations/kvm',
             },
             {
+              id: 'key-clear',
+              label: this.$t('appNavigation.keyClear'),
+              route: '/operations/key-clear',
+            },
+            {
               id: 'firmware',
               label: this.$t('appNavigation.firmware'),
               route: '/operations/firmware',
diff --git a/src/env/components/AppNavigation/ibm.js b/src/env/components/AppNavigation/ibm.js
index 32f5c9f..ed84e17 100644
--- a/src/env/components/AppNavigation/ibm.js
+++ b/src/env/components/AppNavigation/ibm.js
@@ -70,33 +70,7 @@
           id: 'operations',
           label: this.$t('appNavigation.operations'),
           icon: 'iconControl',
-          children: [
-            {
-              id: 'factory-reset',
-              label: this.$t('appNavigation.factoryReset'),
-              route: '/operations/factory-reset',
-            },
-            {
-              id: 'firmware',
-              label: this.$t('appNavigation.firmware'),
-              route: '/operations/firmware',
-            },
-            {
-              id: 'reboot-bmc',
-              label: this.$t('appNavigation.rebootBmc'),
-              route: '/operations/reboot-bmc',
-            },
-            {
-              id: 'serial-over-lan',
-              label: this.$t('appNavigation.serialOverLan'),
-              route: '/operations/serial-over-lan',
-            },
-            {
-              id: 'server-power-operations',
-              label: this.$t('appNavigation.serverPowerOperations'),
-              route: '/operations/server-power-operations',
-            },
-          ],
+          children: this.operationsNavigationItems(),
         },
         {
           id: 'settings',
@@ -167,6 +141,47 @@
       ],
     };
   },
+  methods: {
+    operationsNavigationItems() {
+      const username = this.$store.getters['global/username'];
+      let operationNavigationItems = [
+        {
+          id: 'factory-reset',
+          label: this.$t('appNavigation.factoryReset'),
+          route: '/operations/factory-reset',
+        },
+        {
+          id: 'firmware',
+          label: this.$t('appNavigation.firmware'),
+          route: '/operations/firmware',
+        },
+        {
+          id: 'reboot-bmc',
+          label: this.$t('appNavigation.rebootBmc'),
+          route: '/operations/reboot-bmc',
+        },
+        {
+          id: 'serial-over-lan',
+          label: this.$t('appNavigation.serialOverLan'),
+          route: '/operations/serial-over-lan',
+        },
+        {
+          id: 'server-power-operations',
+          label: this.$t('appNavigation.serverPowerOperations'),
+          route: '/operations/server-power-operations',
+        },
+      ];
+      let pageKeyClear = {
+        id: 'key-clear',
+        label: this.$t('appNavigation.keyClear'),
+        route: '/operations/key-clear',
+      };
+      if (username === 'service' || username === 'admin') {
+        operationNavigationItems.splice(2, 0, pageKeyClear);
+      }
+      return operationNavigationItems;
+    },
+  },
 };
 
 export default AppNavigationMixin;
diff --git a/src/env/router/ibm.js b/src/env/router/ibm.js
index c6ac61f..0ccf90b 100644
--- a/src/env/router/ibm.js
+++ b/src/env/router/ibm.js
@@ -19,6 +19,7 @@
 import ProfileSettings from '@/views/ProfileSettings';
 import RebootBmc from '@/views/Operations/RebootBmc';
 import Policies from '@/views/SecurityAndAccess/Policies';
+import KeyClear from '@/views/Operations/KeyClear';
 import Sensors from '@/views/HardwareStatus/Sensors';
 import SerialOverLan from '@/views/Operations/SerialOverLan';
 import SerialOverLanConsole from '@/views/Operations/SerialOverLan/SerialOverLanConsole';
@@ -223,6 +224,14 @@
         },
       },
       {
+        path: '/operations/key-clear',
+        name: 'key-clear',
+        component: KeyClear,
+        meta: {
+          title: i18n.t('appPageTitle.keyClear'),
+        },
+      },
+      {
         path: '/operations/reboot-bmc',
         name: 'reboot-bmc',
         component: RebootBmc,
diff --git a/src/env/store/ibm.js b/src/env/store/ibm.js
index 787f897..86fc52d 100644
--- a/src/env/store/ibm.js
+++ b/src/env/store/ibm.js
@@ -1,8 +1,11 @@
 import store from '@/store';
 import DumpsStore from '@/store/modules/Logs/DumpsStore';
+import KeyClearStore from '@/store/modules/Operations/KeyClearStore';
 
 store.unregisterModule('virtualMedia');
 
 store.registerModule('dumps', DumpsStore);
 
+store.registerModule('key-clear', KeyClearStore);
+
 export default store;
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index ddc556d..d8df61c 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -126,7 +126,8 @@
     "serverPowerOperations": "@:appPageTitle.serverPowerOperations",
     "certificates": "@:appPageTitle.certificates",
     "virtualMedia": "@:appPageTitle.virtualMedia",
-    "power": "@:appPageTitle.power"
+    "power": "@:appPageTitle.power",
+    "keyClear": "@:appPageTitle.keyClear"
   },
   "appPageTitle": {
     "changePassword": "Change password",
@@ -154,7 +155,8 @@
     "serialOverLan": "Serial over LAN (SOL) console",
     "serverPowerOperations": "Server power operations",
     "certificates": "Certificates",
-    "virtualMedia": "Virtual media"
+    "virtualMedia": "Virtual media",
+    "keyClear": "Key clear"
   },
   "pageChangePassword": {
     "changePassword": "Change password",
@@ -444,6 +446,39 @@
       "errorEnableIdentifyLed": "Error enabling Identify LED."
     }
   },
+  "pageKeyClear": {
+    "description": "Securely clear sensitive data on the system",
+    "alert": {
+      "description": "Due to senstivity of the data that will be cleared, verification through physical presence is required to authorize this operation.",
+      "title": "This operation requires physical presence and system reboot"
+    },
+    "form": {
+      "clearAllSetGenesisIPL": "Clear all and set genesis IPL",
+      "clear": "Clear",
+      "clearAllLabel": "Clear all",
+      "clearAllHeperText":"Clear all the sensitive data that is controlled by the platform firmware",
+      "clearHypervisorSystemKeyLabel":"Clear hypervisor system key",
+      "clearHypervisorSystemKeyHelperText":"This indicates the hypervisor to clear the system key.",
+      "clearOperatingSystemKeysLabel":"Clear operating system keys label",
+      "clearOperatingSystemKeysHelperText":"This indicates OPAL to clear the operating system Secure Boot keys.",
+      "clearSystemSecurityKeyLabel":"Clear system security officer key",
+      "clearSystemSecurityKeyHelperText":"This incicates OPAL/PEF to clear teh system security officer keys.",
+      "keyClearOptionsLabel": "Key clear options",
+      "keyClearNotRequested": "Key clear not requested",
+      "none": "None",
+      "setFactoryDefault": "Set factory default"
+    },
+    "modal":{
+      "clear": "Clear keys",
+      "clearAllMessage": "Any encryption keys contained in the selected data will be lost. System will not be able to decrypt any data that requires these keys.",
+      "clearAllTitle": "Warning: This operation is not reversible"
+     
+    },
+    "toast":{
+      "selectedKeyClearedError": "Error clearing keys",
+      "selectedKeyClearedSuccess": "Keys cleared successfully"
+    }
+  },
   "pageKvm": {
     "openNewTab": "Open in new tab",
     "buttonCtrlAltDelete": "Send Ctrl+Alt+Delete",
diff --git a/src/router/routes.js b/src/router/routes.js
index b99aac5..3cbdabc 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -21,6 +21,7 @@
 import ProfileSettings from '@/views/ProfileSettings';
 import RebootBmc from '@/views/Operations/RebootBmc';
 import Policies from '@/views/SecurityAndAccess/Policies';
+import KeyClear from '@/views/Operations/KeyClear';
 import Sensors from '@/views/HardwareStatus/Sensors';
 import SerialOverLan from '@/views/Operations/SerialOverLan';
 import SerialOverLanConsole from '@/views/Operations/SerialOverLan/SerialOverLanConsole';
@@ -191,6 +192,14 @@
         },
       },
       {
+        path: '/operations/key-clear',
+        name: 'key-clear',
+        component: KeyClear,
+        meta: {
+          title: i18n.t('appPageTitle.keyClear'),
+        },
+      },
+      {
         path: '/operations/kvm',
         name: 'kvm',
         component: Kvm,
diff --git a/src/store/index.js b/src/store/index.js
index d7c1b22..ba248c5 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -27,6 +27,7 @@
 import PostCodeLogsStore from './modules/Logs/PostCodeLogsStore';
 import PoliciesStore from './modules/SecurityAndAccess/PoliciesStore';
 import FactoryResetStore from './modules/Operations/FactoryResetStore';
+import KeyClearStore from './modules/Operations/KeyClearStore';
 
 import WebSocketPlugin from './plugins/WebSocketPlugin';
 import DateTimeStore from './modules/Settings/DateTimeStore';
@@ -67,6 +68,7 @@
     virtualMedia: VirtualMediaStore,
     policies: PoliciesStore,
     factoryReset: FactoryResetStore,
+    keyClear: KeyClearStore,
   },
   plugins: [WebSocketPlugin],
 });
diff --git a/src/store/modules/Operations/KeyClearStore.js b/src/store/modules/Operations/KeyClearStore.js
new file mode 100644
index 0000000..1dc96e0
--- /dev/null
+++ b/src/store/modules/Operations/KeyClearStore.js
@@ -0,0 +1,25 @@
+import api from '@/store/api';
+import i18n from '@/i18n';
+
+const KeyClearStore = {
+  namespaced: true,
+  actions: {
+    async clearEncryptionKeys(_, selectedKey) {
+      const selectedKeyForClearing = {
+        Attributes: { hb_key_clear_request: selectedKey },
+      };
+      return await api
+        .patch(
+          '/redfish/v1/Systems/system/Bios/Settings',
+          selectedKeyForClearing
+        )
+        .then(() => i18n.t('pageKeyClear.toast.selectedKeyClearedSuccess'))
+        .catch((error) => {
+          console.log('Key clear', error);
+          throw new Error(i18n.t('pageKeyClear.toast.selectedKeyClearedError'));
+        });
+    },
+  },
+};
+
+export default KeyClearStore;
diff --git a/src/views/Operations/KeyClear/KeyClear.vue b/src/views/Operations/KeyClear/KeyClear.vue
new file mode 100644
index 0000000..2524da1
--- /dev/null
+++ b/src/views/Operations/KeyClear/KeyClear.vue
@@ -0,0 +1,106 @@
+<template>
+  <b-container fluid="xl">
+    <page-title :description="$t('pageKeyClear.description')" />
+    <b-row>
+      <b-col md="8" xl="6">
+        <alert variant="info" class="mb-4">
+          <div class="font-weight-bold">
+            {{ $t('pageKeyClear.alert.title') }}
+          </div>
+          <div>
+            {{ $t('pageKeyClear.alert.description') }}
+          </div>
+        </alert>
+      </b-col>
+    </b-row>
+    <!-- Reset Form -->
+    <b-form id="key-clear" @submit.prevent="onKeyClearSubmit(keyOption)">
+      <b-row>
+        <b-col md="8">
+          <b-form-group :label="$t('pageKeyClear.form.keyClearOptionsLabel')">
+            <b-form-radio-group
+              id="key-clear-options"
+              v-model="keyOption"
+              stacked
+            >
+              <b-form-radio class="mb-1" value="NONE">
+                {{ $t('pageKeyClear.form.none') }}
+              </b-form-radio>
+              <b-form-text id="key-clear-not-requested" class="ml-4 mb-3">
+                {{ $t('pageKeyClear.form.keyClearNotRequested') }}
+              </b-form-text>
+              <b-form-radio class="mb-1" value="ALL">
+                {{ $t('pageKeyClear.form.clearAllLabel') }}
+              </b-form-radio>
+              <b-form-text id="clear-all" class="ml-4 mb-3">
+                {{ $t('pageKeyClear.form.clearAllHeperText') }}
+              </b-form-text>
+              <b-form-radio class="mb-1" value="POWERVM_SYSKEY">
+                {{ $t('pageKeyClear.form.clearHypervisorSystemKeyLabel') }}
+              </b-form-radio>
+              <b-form-text id="clear-hypervisor-key" class="ml-4 mb-3">
+                {{ $t('pageKeyClear.form.clearHypervisorSystemKeyHelperText') }}
+              </b-form-text>
+              <template v-if="username == 'service'">
+                <b-form-radio class="mb-1" value="MFG_ALL">
+                  {{ $t('pageKeyClear.form.clearAllSetGenesisIPL') }}
+                </b-form-radio>
+                <b-form-radio class="mb-1" value="MFG">
+                  {{ $t('pageKeyClear.form.setFactoryDefault') }}
+                </b-form-radio>
+              </template>
+            </b-form-radio-group>
+          </b-form-group>
+          <b-button
+            type="submit"
+            variant="primary"
+            data-test-id="keyClear-button-submit"
+          >
+            {{ $t('pageKeyClear.form.clear') }}
+          </b-button>
+        </b-col>
+      </b-row>
+    </b-form>
+  </b-container>
+</template>
+
+<script>
+import PageTitle from '@/components/Global/PageTitle';
+import BVToastMixin from '@/components/Mixins/BVToastMixin';
+import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
+import Alert from '@/components/Global/Alert';
+
+export default {
+  name: 'KeyClear',
+  components: { PageTitle, Alert },
+  mixins: [LoadingBarMixin, BVToastMixin],
+  data() {
+    return {
+      keyOption: 'NONE',
+      username: this.$store.getters['global/username'],
+    };
+  },
+  created() {
+    this.hideLoader();
+  },
+  methods: {
+    onKeyClearSubmit(valueSelected) {
+      this.$bvModal
+        .msgBoxConfirm(this.$t('pageKeyClear.modal.clearAllMessage'), {
+          title: this.$t('pageKeyClear.modal.clearAllTitle'),
+          okTitle: this.$t('pageKeyClear.modal.clear'),
+          okVariant: 'danger',
+          cancelTitle: this.$t('global.action.cancel'),
+        })
+        .then((clearConfirmed) => {
+          if (clearConfirmed) {
+            this.$store
+              .dispatch('keyClear/clearEncryptionKeys', valueSelected)
+              .then((message) => this.successToast(message))
+              .catch(({ message }) => this.errorToast(message));
+          }
+        });
+    },
+  },
+};
+</script>
diff --git a/src/views/Operations/KeyClear/index.js b/src/views/Operations/KeyClear/index.js
new file mode 100644
index 0000000..56de8c4
--- /dev/null
+++ b/src/views/Operations/KeyClear/index.js
@@ -0,0 +1,2 @@
+import KeyClear from './KeyClear.vue';
+export default KeyClear;
diff --git a/tests/unit/__snapshots__/AppNavigation.spec.js.snap b/tests/unit/__snapshots__/AppNavigation.spec.js.snap
index 37609d3..9862818 100644
--- a/tests/unit/__snapshots__/AppNavigation.spec.js.snap
+++ b/tests/unit/__snapshots__/AppNavigation.spec.js.snap
@@ -314,6 +314,15 @@
                 </a>
                 <a
                   class="nav-link"
+                  data-test-id="nav-item-key-clear"
+                  href="#/operations/key-clear"
+                >
+                  
+                  appNavigation.keyClear
+                
+                </a>
+                <a
+                  class="nav-link"
                   data-test-id="nav-item-firmware"
                   href="#/operations/firmware"
                 >
@@ -975,6 +984,15 @@
                 </a>
                 <a
                   class="nav-link"
+                  data-test-id="nav-item-key-clear"
+                  href="#/operations/key-clear"
+                >
+                  
+                  appNavigation.keyClear
+                
+                </a>
+                <a
+                  class="nav-link"
                   data-test-id="nav-item-firmware"
                   href="#/operations/firmware"
                 >