From 34efde291781c01c78e4363d919cdf4d5c90ae43 Mon Sep 17 00:00:00 2001 From: Sukanya Pandey Date: Wed, 2 Dec 2020 19:04:09 +0530 Subject: Add client sessions page - This page will show the list of sessions that are currently connected to the BMC. APIs used: - To get all the sessions API used is `/redfish/v1/SessionService/Sessions` - To delete the sessions API used is `/redfish/v1/SessionService/Sessions/` Signed-off-by: Sukanya Pandey Change-Id: Ia81f62cbbea749809b9b7f7e62356cfe2db7fc18 --- src/components/AppNavigation/AppNavigationMixin.js | 5 + src/locales/en-US.json | 21 ++ src/router/routes.js | 9 + src/store/index.js | 2 + .../modules/AccessControl/ClientSessionsStore.js | 80 ++++++ .../ClientSessions/ClientSessions.vue | 292 +++++++++++++++++++++ src/views/AccessControl/ClientSessions/index.js | 2 + 7 files changed, 411 insertions(+) create mode 100644 src/store/modules/AccessControl/ClientSessionsStore.js create mode 100644 src/views/AccessControl/ClientSessions/ClientSessions.vue create mode 100644 src/views/AccessControl/ClientSessions/index.js diff --git a/src/components/AppNavigation/AppNavigationMixin.js b/src/components/AppNavigation/AppNavigationMixin.js index b163d75e..7fe63a0a 100644 --- a/src/components/AppNavigation/AppNavigationMixin.js +++ b/src/components/AppNavigation/AppNavigationMixin.js @@ -124,6 +124,11 @@ const AppNavigationMixin = { label: this.$t('appNavigation.accessControl'), icon: 'iconAccessControl', children: [ + { + id: 'client-sessions', + label: this.$t('appNavigation.clientSessions'), + route: '/access-control/client-sessions', + }, { id: 'ldap', label: this.$t('appNavigation.ldap'), diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 0e28de51..dcb52a68 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -95,6 +95,7 @@ }, "appNavigation": { "accessControl": "Access control", + "clientSessions": "@:appPageTitle.clientSessions", "configuration": "Configuration", "control": "Control", "dateTimeSettings": "@:appPageTitle.dateTimeSettings", @@ -121,6 +122,7 @@ }, "appPageTitle": { "changePassword": "Change password", + "clientSessions": "Client sessions", "dateTimeSettings": "Date and time settings", "eventLogs": "Event logs", "firmware": "Firmware", @@ -153,6 +155,25 @@ "newPassword": "New password", "username": "Username" }, + "pageClientSessions" : { + "action": { + "disconnect" : "Disconnect" + }, + "modal": { + "disconnectTitle": "Disconnect session| Disconnect sessions", + "disconnectMessage": "Are you sure you want to disconnect %{count} session? This action cannot be undone. | Are you sure you want to disconnect %{count} sessions? This action cannot be undone." + }, + "table": { + "clientID": "Client ID", + "username": "Username", + "ipAddress": "IP address", + "searchSessions": "Search sessions" + }, + "toast": { + "errorDelete": "Error disconnecting %{count} session. | Error disconnecting %{count} sessions.", + "successDelete": "Successfully disconnected %{count} session. | Successfully disconnected %{count} sessions." + } + }, "pageDateTimeSettings": { "alert": { "message": "To change how date and time are displayed (either UTC or browser offset) throughout the application, visit ", diff --git a/src/router/routes.js b/src/router/routes.js index a82833ad..9a9b7137 100644 --- a/src/router/routes.js +++ b/src/router/routes.js @@ -7,6 +7,7 @@ import Firmware from '@/views/Configuration/Firmware'; import HardwareStatus from '@/views/Health/HardwareStatus'; import Kvm from '@/views/Control/Kvm'; import KvmConsole from '@/views/Control/Kvm/KvmConsole'; +import ClientSessions from '../views/AccessControl/ClientSessions'; import Ldap from '@/views/AccessControl/Ldap'; import LocalUserManagement from '@/views/AccessControl/LocalUserManagement'; import Login from '@/views/Login'; @@ -123,6 +124,14 @@ const routes = [ title: i18n.t('appPageTitle.sensors'), }, }, + { + path: '/access-control/client-sessions', + name: 'client-sessions', + component: ClientSessions, + meta: { + title: i18n.t('appPageTitle.clientSessions'), + }, + }, { path: '/access-control/ldap', name: 'ldap', diff --git a/src/store/index.js b/src/store/index.js index b4a77d82..151eb68c 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -3,6 +3,7 @@ import Vuex from 'vuex'; import GlobalStore from './modules/GlobalStore'; import AuthenticationStore from './modules/Authentication/AuthenticanStore'; +import ClientSessions from './modules/AccessControl/ClientSessionsStore'; import LdapStore from './modules/AccessControl/LdapStore'; import LocalUserManagementStore from './modules/AccessControl/LocalUserMangementStore'; import SslCertificatesStore from './modules/AccessControl/SslCertificatesStore'; @@ -36,6 +37,7 @@ export default new Vuex.Store({ modules: { global: GlobalStore, authentication: AuthenticationStore, + clientSessions: ClientSessions, dateTime: DateTimeStore, ldap: LdapStore, localUsers: LocalUserManagementStore, diff --git a/src/store/modules/AccessControl/ClientSessionsStore.js b/src/store/modules/AccessControl/ClientSessionsStore.js new file mode 100644 index 00000000..a09f766e --- /dev/null +++ b/src/store/modules/AccessControl/ClientSessionsStore.js @@ -0,0 +1,80 @@ +import api, { getResponseCount } from '@/store/api'; +import i18n from '@/i18n'; + +const ClientSessionsStore = { + namespaced: true, + state: { + allConnections: [], + }, + getters: { + allConnections: (state) => state.allConnections, + }, + mutations: { + setAllConnections: (state, allConnections) => + (state.allConnections = allConnections), + }, + actions: { + async getClientSessionsData({ commit }) { + return await api + .get('/redfish/v1/SessionService/Sessions') + .then((response) => + response.data.Members.map((sessionLogs) => sessionLogs['@odata.id']) + ) + .then((sessionUris) => + api.all(sessionUris.map((sessionUri) => api.get(sessionUri))) + ) + .then((sessionUris) => { + const allConnectionsData = sessionUris.map((sessionUri) => { + return { + clientID: sessionUri.data?.Id, + username: sessionUri.data?.UserName, + ipAddress: sessionUri.data?.Oem?.OpenBMC.ClientID.slice(2), + uri: sessionUri.data['@odata.id'], + }; + }); + commit('setAllConnections', allConnectionsData); + }) + .catch((error) => { + console.log('Client Session Data:', error); + }); + }, + async disconnectSessions({ dispatch }, uris = []) { + const promises = uris.map((uri) => + api.delete(uri).catch((error) => { + console.log(error); + return error; + }) + ); + return await api + .all(promises) + .then((response) => { + dispatch('getClientSessionsData'); + return response; + }) + .then( + api.spread((...responses) => { + const { successCount, errorCount } = getResponseCount(responses); + const toastMessages = []; + + if (successCount) { + const message = i18n.tc( + 'pageClientSessions.toast.successDelete', + successCount + ); + toastMessages.push({ type: 'success', message }); + } + + if (errorCount) { + const message = i18n.tc( + 'pageClientSessions.toast.errorDelete', + errorCount + ); + toastMessages.push({ type: 'error', message }); + } + return toastMessages; + }) + ); + }, + }, +}; +export default ClientSessionsStore; diff --git a/src/views/AccessControl/ClientSessions/ClientSessions.vue b/src/views/AccessControl/ClientSessions/ClientSessions.vue new file mode 100644 index 00000000..04dd052f --- /dev/null +++ b/src/views/AccessControl/ClientSessions/ClientSessions.vue @@ -0,0 +1,292 @@ + + + + diff --git a/src/views/AccessControl/ClientSessions/index.js b/src/views/AccessControl/ClientSessions/index.js new file mode 100644 index 00000000..6000ab75 --- /dev/null +++ b/src/views/AccessControl/ClientSessions/index.js @@ -0,0 +1,2 @@ +import ClientSessions from './ClientSessions.vue'; +export default ClientSessions; -- cgit v1.2.3