summaryrefslogtreecommitdiff
path: root/src/store/modules/SecurityAndAccess
diff options
context:
space:
mode:
authorSandeepa Singh <sandeepa.singh@ibm.com>2021-07-26 12:35:39 +0300
committerDerick Montague <derick.montague@ibm.com>2021-08-10 22:20:42 +0300
commitb440616c23b61166ae6d87839a70eec31bdca235 (patch)
treed72769d4aa425e96e47419515b85a8631d8e99d7 /src/store/modules/SecurityAndAccess
parentf67f769f2304bca64d2b9758e22c21203960eef9 (diff)
downloadwebui-vue-b440616c23b61166ae6d87839a70eec31bdca235.tar.xz
IA update: Update access and control section
This is the fifth commit of the information architecture changes and has the following changes: - The icon for access and control has been updated - Access and control section has been updated to security and access section - Security settings page has been updated to policies page and moved to security and access section - Client sessions page has been updated to sessions page - Local user management page has been updated to user management page - SSL certificates page has been updated to certificates page Signed-off-by: Sandeepa Singh <sandeepa.singh@ibm.com> Change-Id: Ie93cee9002742ecf7d33615636f4f159f4395fc4
Diffstat (limited to 'src/store/modules/SecurityAndAccess')
-rw-r--r--src/store/modules/SecurityAndAccess/CertificatesStore.js202
-rw-r--r--src/store/modules/SecurityAndAccess/LdapStore.js275
-rw-r--r--src/store/modules/SecurityAndAccess/PoliciesStore.js87
-rw-r--r--src/store/modules/SecurityAndAccess/SessionsStore.js80
-rw-r--r--src/store/modules/SecurityAndAccess/UserManagementStore.js318
5 files changed, 962 insertions, 0 deletions
diff --git a/src/store/modules/SecurityAndAccess/CertificatesStore.js b/src/store/modules/SecurityAndAccess/CertificatesStore.js
new file mode 100644
index 00000000..97241f34
--- /dev/null
+++ b/src/store/modules/SecurityAndAccess/CertificatesStore.js
@@ -0,0 +1,202 @@
+import api from '@/store/api';
+import i18n from '@/i18n';
+
+export const CERTIFICATE_TYPES = [
+ {
+ type: 'HTTPS Certificate',
+ location: '/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/',
+ label: i18n.t('pageCertificates.httpsCertificate'),
+ },
+ {
+ type: 'LDAP Certificate',
+ location: '/redfish/v1/AccountService/LDAP/Certificates/',
+ label: i18n.t('pageCertificates.ldapCertificate'),
+ },
+ {
+ type: 'TrustStore Certificate',
+ location: '/redfish/v1/Managers/bmc/Truststore/Certificates/',
+ // Web UI will show 'CA Certificate' instead of
+ // 'TrustStore Certificate' after user testing revealed
+ // the term 'TrustStore Certificate' wasn't recognized/was unfamilar
+ label: i18n.t('pageCertificates.caCertificate'),
+ },
+];
+
+const getCertificateProp = (type, prop) => {
+ const certificate = CERTIFICATE_TYPES.find(
+ (certificate) => certificate.type === type
+ );
+ return certificate ? certificate[prop] : null;
+};
+
+const CertificatesStore = {
+ namespaced: true,
+ state: {
+ allCertificates: [],
+ availableUploadTypes: [],
+ },
+ getters: {
+ allCertificates: (state) => state.allCertificates,
+ availableUploadTypes: (state) => state.availableUploadTypes,
+ },
+ mutations: {
+ setCertificates(state, certificates) {
+ state.allCertificates = certificates;
+ },
+ setAvailableUploadTypes(state, availableUploadTypes) {
+ state.availableUploadTypes = availableUploadTypes;
+ },
+ },
+ actions: {
+ async getCertificates({ commit }) {
+ return await api
+ .get('/redfish/v1/CertificateService/CertificateLocations')
+ .then(({ data: { Links: { Certificates } } }) =>
+ Certificates.map((certificate) => certificate['@odata.id'])
+ )
+ .then((certificateLocations) => {
+ const promises = certificateLocations.map((location) =>
+ api.get(location)
+ );
+ api.all(promises).then(
+ api.spread((...responses) => {
+ const certificates = responses.map(({ data }) => {
+ const {
+ Name,
+ ValidNotAfter,
+ ValidNotBefore,
+ Issuer = {},
+ Subject = {},
+ } = data;
+ return {
+ type: Name,
+ location: data['@odata.id'],
+ certificate: getCertificateProp(Name, 'label'),
+ issuedBy: Issuer.CommonName,
+ issuedTo: Subject.CommonName,
+ validFrom: new Date(ValidNotBefore),
+ validUntil: new Date(ValidNotAfter),
+ };
+ });
+ const availableUploadTypes = CERTIFICATE_TYPES.filter(
+ ({ type }) =>
+ !certificates
+ .map((certificate) => certificate.type)
+ .includes(type)
+ );
+
+ commit('setCertificates', certificates);
+ commit('setAvailableUploadTypes', availableUploadTypes);
+ })
+ );
+ });
+ },
+ async addNewCertificate({ dispatch }, { file, type }) {
+ return await api
+ .post(getCertificateProp(type, 'location'), file, {
+ headers: { 'Content-Type': 'application/x-pem-file' },
+ })
+ .then(() => dispatch('getCertificates'))
+ .then(() =>
+ i18n.t('pageCertificates.toast.successAddCertificate', {
+ certificate: getCertificateProp(type, 'label'),
+ })
+ )
+ .catch((error) => {
+ console.log(error);
+ throw new Error(i18n.t('pageCertificates.toast.errorAddCertificate'));
+ });
+ },
+ async replaceCertificate(
+ { dispatch },
+ { certificateString, location, type }
+ ) {
+ const data = {};
+ data.CertificateString = certificateString;
+ data.CertificateType = 'PEM';
+ data.CertificateUri = { '@odata.id': location };
+
+ return await api
+ .post(
+ '/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate',
+ data
+ )
+ .then(() => dispatch('getCertificates'))
+ .then(() =>
+ i18n.t('pageCertificates.toast.successReplaceCertificate', {
+ certificate: getCertificateProp(type, 'label'),
+ })
+ )
+ .catch((error) => {
+ console.log(error);
+ throw new Error(
+ i18n.t('pageCertificates.toast.errorReplaceCertificate')
+ );
+ });
+ },
+ async deleteCertificate({ dispatch }, { type, location }) {
+ return await api
+ .delete(location)
+ .then(() => dispatch('getCertificates'))
+ .then(() =>
+ i18n.t('pageCertificates.toast.successDeleteCertificate', {
+ certificate: getCertificateProp(type, 'label'),
+ })
+ )
+ .catch((error) => {
+ console.log(error);
+ throw new Error(
+ i18n.t('pageCertificates.toast.errorDeleteCertificate')
+ );
+ });
+ },
+ async generateCsr(_, userData) {
+ const {
+ certificateType,
+ country,
+ state,
+ city,
+ companyName,
+ companyUnit,
+ commonName,
+ keyPairAlgorithm,
+ keyBitLength,
+ keyCurveId,
+ challengePassword,
+ contactPerson,
+ emailAddress,
+ alternateName,
+ } = userData;
+ const data = {};
+
+ data.CertificateCollection = {
+ '@odata.id': getCertificateProp(certificateType, 'location'),
+ };
+ data.Country = country;
+ data.State = state;
+ data.City = city;
+ data.Organization = companyName;
+ data.OrganizationalUnit = companyUnit;
+ data.CommonName = commonName;
+ data.KeyPairAlgorithm = keyPairAlgorithm;
+ data.AlternativeNames = alternateName;
+
+ if (keyCurveId) data.KeyCurveId = keyCurveId;
+ if (keyBitLength) data.KeyBitLength = keyBitLength;
+ if (challengePassword) data.ChallengePassword = challengePassword;
+ if (contactPerson) data.ContactPerson = contactPerson;
+ if (emailAddress) data.Email = emailAddress;
+
+ return await api
+ .post(
+ '/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR',
+ data
+ )
+ //TODO: Success response also throws error so
+ // can't accurately show legitimate error in UI
+ .catch((error) => console.log(error));
+ },
+ },
+};
+
+export default CertificatesStore;
diff --git a/src/store/modules/SecurityAndAccess/LdapStore.js b/src/store/modules/SecurityAndAccess/LdapStore.js
new file mode 100644
index 00000000..5aa31c2d
--- /dev/null
+++ b/src/store/modules/SecurityAndAccess/LdapStore.js
@@ -0,0 +1,275 @@
+import api from '@/store/api';
+import i18n from '@/i18n';
+import { find } from 'lodash';
+
+const LdapStore = {
+ namespaced: true,
+ state: {
+ isServiceEnabled: null,
+ ldap: {
+ serviceEnabled: null,
+ serviceAddress: null,
+ bindDn: null,
+ baseDn: null,
+ userAttribute: null,
+ groupsAttribute: null,
+ roleGroups: [],
+ },
+ activeDirectory: {
+ serviceEnabled: null,
+ serviceAddress: null,
+ bindDn: null,
+ baseDn: null,
+ userAttribute: null,
+ groupsAttribute: null,
+ roleGroups: [],
+ },
+ },
+ getters: {
+ isServiceEnabled: (state) => state.isServiceEnabled,
+ ldap: (state) => state.ldap,
+ activeDirectory: (state) => state.activeDirectory,
+ isActiveDirectoryEnabled: (state) => {
+ return state.activeDirectory.serviceEnabled;
+ },
+ enabledRoleGroups: (state, getters) => {
+ const serviceType = getters.isActiveDirectoryEnabled
+ ? 'activeDirectory'
+ : 'ldap';
+ return state[serviceType].roleGroups;
+ },
+ },
+ mutations: {
+ setServiceEnabled: (state, serviceEnabled) =>
+ (state.isServiceEnabled = serviceEnabled),
+ setLdapProperties: (
+ state,
+ {
+ ServiceEnabled,
+ ServiceAddresses = [],
+ Authentication = {},
+ LDAPService: {
+ SearchSettings: {
+ BaseDistinguishedNames = [],
+ UsernameAttribute,
+ GroupsAttribute,
+ } = {},
+ } = {},
+ RemoteRoleMapping = [],
+ }
+ ) => {
+ state.ldap.serviceAddress = ServiceAddresses[0];
+ state.ldap.serviceEnabled = ServiceEnabled;
+ state.ldap.baseDn = BaseDistinguishedNames[0];
+ state.ldap.bindDn = Authentication.Username;
+ state.ldap.userAttribute = UsernameAttribute;
+ state.ldap.groupsAttribute = GroupsAttribute;
+ state.ldap.roleGroups = RemoteRoleMapping;
+ },
+ setActiveDirectoryProperties: (
+ state,
+ {
+ ServiceEnabled,
+ ServiceAddresses = [],
+ Authentication = {},
+ LDAPService: {
+ SearchSettings: {
+ BaseDistinguishedNames = [],
+ UsernameAttribute,
+ GroupsAttribute,
+ } = {},
+ } = {},
+ RemoteRoleMapping = [],
+ }
+ ) => {
+ state.activeDirectory.serviceEnabled = ServiceEnabled;
+ state.activeDirectory.serviceAddress = ServiceAddresses[0];
+ state.activeDirectory.bindDn = Authentication.Username;
+ state.activeDirectory.baseDn = BaseDistinguishedNames[0];
+ state.activeDirectory.userAttribute = UsernameAttribute;
+ state.activeDirectory.groupsAttribute = GroupsAttribute;
+ state.activeDirectory.roleGroups = RemoteRoleMapping;
+ },
+ },
+ actions: {
+ async getAccountSettings({ commit }) {
+ return await api
+ .get('/redfish/v1/AccountService')
+ .then(({ data: { LDAP = {}, ActiveDirectory = {} } }) => {
+ const ldapEnabled = LDAP.ServiceEnabled;
+ const activeDirectoryEnabled = ActiveDirectory.ServiceEnabled;
+
+ commit('setServiceEnabled', ldapEnabled || activeDirectoryEnabled);
+ commit('setLdapProperties', LDAP);
+ commit('setActiveDirectoryProperties', ActiveDirectory);
+ })
+ .catch((error) => console.log(error));
+ },
+ async saveLdapSettings({ state, dispatch }, properties) {
+ const data = { LDAP: properties };
+ if (state.activeDirectory.serviceEnabled) {
+ // Disable Active Directory service if enabled
+ await api.patch('/redfish/v1/AccountService', {
+ ActiveDirectory: { ServiceEnabled: false },
+ });
+ }
+ return await api
+ .patch('/redfish/v1/AccountService', data)
+ .then(() => dispatch('getAccountSettings'))
+ .then(() => i18n.t('pageLdap.toast.successSaveLdapSettings'))
+ .catch((error) => {
+ console.log(error);
+ throw new Error(i18n.t('pageLdap.toast.errorSaveLdapSettings'));
+ });
+ },
+ async saveActiveDirectorySettings({ state, dispatch }, properties) {
+ const data = { ActiveDirectory: properties };
+ if (state.ldap.serviceEnabled) {
+ // Disable LDAP service if enabled
+ await api.patch('/redfish/v1/AccountService', {
+ LDAP: { ServiceEnabled: false },
+ });
+ }
+ return await api
+ .patch('/redfish/v1/AccountService', data)
+ .then(() => dispatch('getAccountSettings'))
+ .then(() => i18n.t('pageLdap.toast.successSaveActiveDirectorySettings'))
+ .catch((error) => {
+ console.log(error);
+ throw new Error(
+ i18n.t('pageLdap.toast.errorSaveActiveDirectorySettings')
+ );
+ });
+ },
+ async saveAccountSettings(
+ { dispatch },
+ {
+ serviceEnabled,
+ serviceAddress,
+ activeDirectoryEnabled,
+ bindDn,
+ bindPassword,
+ baseDn,
+ userIdAttribute,
+ groupIdAttribute,
+ }
+ ) {
+ const data = {
+ ServiceEnabled: serviceEnabled,
+ ServiceAddresses: [serviceAddress],
+ Authentication: {
+ Username: bindDn,
+ Password: bindPassword,
+ },
+ LDAPService: {
+ SearchSettings: {
+ BaseDistinguishedNames: [baseDn],
+ },
+ },
+ };
+ if (groupIdAttribute)
+ data.LDAPService.SearchSettings.GroupsAttribute = groupIdAttribute;
+ if (userIdAttribute)
+ data.LDAPService.SearchSettings.UsernameAttribute = userIdAttribute;
+
+ if (activeDirectoryEnabled) {
+ return await dispatch('saveActiveDirectorySettings', data);
+ } else {
+ return await dispatch('saveLdapSettings', data);
+ }
+ },
+ async addNewRoleGroup(
+ { dispatch, getters },
+ { groupName, groupPrivilege }
+ ) {
+ const data = {};
+ const enabledRoleGroups = getters['enabledRoleGroups'];
+ const isActiveDirectoryEnabled = getters['isActiveDirectoryEnabled'];
+ const RemoteRoleMapping = [
+ ...enabledRoleGroups,
+ {
+ LocalRole: groupPrivilege,
+ RemoteGroup: groupName,
+ },
+ ];
+ if (isActiveDirectoryEnabled) {
+ data.ActiveDirectory = { RemoteRoleMapping };
+ } else {
+ data.LDAP = { RemoteRoleMapping };
+ }
+ return await api
+ .patch('/redfish/v1/AccountService', data)
+ .then(() => dispatch('getAccountSettings'))
+ .then(() =>
+ i18n.t('pageLdap.toast.successAddRoleGroup', {
+ groupName,
+ })
+ )
+ .catch((error) => {
+ console.log(error);
+ throw new Error(i18n.t('pageLdap.toast.errorAddRoleGroup'));
+ });
+ },
+ async saveRoleGroup({ dispatch, getters }, { groupName, groupPrivilege }) {
+ const data = {};
+ const enabledRoleGroups = getters['enabledRoleGroups'];
+ const isActiveDirectoryEnabled = getters['isActiveDirectoryEnabled'];
+ const RemoteRoleMapping = enabledRoleGroups.map((group) => {
+ if (group.RemoteGroup === groupName) {
+ return {
+ RemoteGroup: groupName,
+ LocalRole: groupPrivilege,
+ };
+ } else {
+ return {};
+ }
+ });
+ if (isActiveDirectoryEnabled) {
+ data.ActiveDirectory = { RemoteRoleMapping };
+ } else {
+ data.LDAP = { RemoteRoleMapping };
+ }
+ return await api
+ .patch('/redfish/v1/AccountService', data)
+ .then(() => dispatch('getAccountSettings'))
+ .then(() =>
+ i18n.t('pageLdap.toast.successSaveRoleGroup', { groupName })
+ )
+ .catch((error) => {
+ console.log(error);
+ throw new Error(i18n.t('pageLdap.toast.errorSaveRoleGroup'));
+ });
+ },
+ async deleteRoleGroup({ dispatch, getters }, { roleGroups = [] }) {
+ const data = {};
+ const enabledRoleGroups = getters['enabledRoleGroups'];
+ const isActiveDirectoryEnabled = getters['isActiveDirectoryEnabled'];
+ const RemoteRoleMapping = enabledRoleGroups.map((group) => {
+ if (find(roleGroups, { groupName: group.RemoteGroup })) {
+ return null;
+ } else {
+ return {};
+ }
+ });
+ if (isActiveDirectoryEnabled) {
+ data.ActiveDirectory = { RemoteRoleMapping };
+ } else {
+ data.LDAP = { RemoteRoleMapping };
+ }
+ return await api
+ .patch('/redfish/v1/AccountService', data)
+ .then(() => dispatch('getAccountSettings'))
+ .then(() =>
+ i18n.tc('pageLdap.toast.successDeleteRoleGroup', roleGroups.length)
+ )
+ .catch((error) => {
+ console.log(error);
+ throw new Error(
+ i18n.tc('pageLdap.toast.errorDeleteRoleGroup', roleGroups.length)
+ );
+ });
+ },
+ },
+};
+
+export default LdapStore;
diff --git a/src/store/modules/SecurityAndAccess/PoliciesStore.js b/src/store/modules/SecurityAndAccess/PoliciesStore.js
new file mode 100644
index 00000000..1e195527
--- /dev/null
+++ b/src/store/modules/SecurityAndAccess/PoliciesStore.js
@@ -0,0 +1,87 @@
+import api from '@/store/api';
+import i18n from '@/i18n';
+
+const PoliciesStore = {
+ namespaced: true,
+ state: {
+ sshProtocolEnabled: false,
+ ipmiProtocolEnabled: false,
+ },
+ getters: {
+ sshProtocolEnabled: (state) => state.sshProtocolEnabled,
+ ipmiProtocolEnabled: (state) => state.ipmiProtocolEnabled,
+ },
+ mutations: {
+ setSshProtocolEnabled: (state, sshProtocolEnabled) =>
+ (state.sshProtocolEnabled = sshProtocolEnabled),
+ setIpmiProtocolEnabled: (state, ipmiProtocolEnabled) =>
+ (state.ipmiProtocolEnabled = ipmiProtocolEnabled),
+ },
+ actions: {
+ async getNetworkProtocolStatus({ commit }) {
+ return await api
+ .get('/redfish/v1/Managers/bmc/NetworkProtocol')
+ .then((response) => {
+ const sshProtocol = response.data.SSH.ProtocolEnabled;
+ const ipmiProtocol = response.data.IPMI.ProtocolEnabled;
+ commit('setSshProtocolEnabled', sshProtocol);
+ commit('setIpmiProtocolEnabled', ipmiProtocol);
+ })
+ .catch((error) => console.log(error));
+ },
+ async saveIpmiProtocolState({ commit }, protocolEnabled) {
+ commit('setIpmiProtocolEnabled', protocolEnabled);
+ const ipmi = {
+ IPMI: {
+ ProtocolEnabled: protocolEnabled,
+ },
+ };
+ return await api
+ .patch('/redfish/v1/Managers/bmc/NetworkProtocol', ipmi)
+ .then(() => {
+ if (protocolEnabled) {
+ return i18n.t('pagePolicies.toast.successIpmiEnabled');
+ } else {
+ return i18n.t('pagePolicies.toast.successIpmiDisabled');
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ commit('setIpmiProtocolEnabled', !protocolEnabled);
+ if (protocolEnabled) {
+ throw new Error(i18n.t('pagePolicies.toast.errorIpmiEnabled'));
+ } else {
+ throw new Error(i18n.t('pagePolicies.toast.errorIpmiDisabled'));
+ }
+ });
+ },
+ async saveSshProtocolState({ commit }, protocolEnabled) {
+ commit('setSshProtocolEnabled', protocolEnabled);
+ const ssh = {
+ SSH: {
+ ProtocolEnabled: protocolEnabled,
+ },
+ };
+ return await api
+ .patch('/redfish/v1/Managers/bmc/NetworkProtocol', ssh)
+ .then(() => {
+ if (protocolEnabled) {
+ return i18n.t('pagePolicies.toast.successSshEnabled');
+ } else {
+ return i18n.t('pagePolicies.toast.successSshDisabled');
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ commit('setSshProtocolEnabled', !protocolEnabled);
+ if (protocolEnabled) {
+ throw new Error(i18n.t('pagePolicies.toast.errorSshEnabled'));
+ } else {
+ throw new Error(i18n.t('pagePolicies.toast.errorSshDisabled'));
+ }
+ });
+ },
+ },
+};
+
+export default PoliciesStore;
diff --git a/src/store/modules/SecurityAndAccess/SessionsStore.js b/src/store/modules/SecurityAndAccess/SessionsStore.js
new file mode 100644
index 00000000..54607ab6
--- /dev/null
+++ b/src/store/modules/SecurityAndAccess/SessionsStore.js
@@ -0,0 +1,80 @@
+import api, { getResponseCount } from '@/store/api';
+import i18n from '@/i18n';
+
+const SessionsStore = {
+ namespaced: true,
+ state: {
+ allConnections: [],
+ },
+ getters: {
+ allConnections: (state) => state.allConnections,
+ },
+ mutations: {
+ setAllConnections: (state, allConnections) =>
+ (state.allConnections = allConnections),
+ },
+ actions: {
+ async getSessionsData({ 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?.Oem?.OpenBMC.ClientID,
+ username: sessionUri.data?.UserName,
+ ipAddress: sessionUri.data?.ClientOriginIPAddress,
+ 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('getSessionsData');
+ return response;
+ })
+ .then(
+ api.spread((...responses) => {
+ const { successCount, errorCount } = getResponseCount(responses);
+ const toastMessages = [];
+
+ if (successCount) {
+ const message = i18n.tc(
+ 'pageSessions.toast.successDelete',
+ successCount
+ );
+ toastMessages.push({ type: 'success', message });
+ }
+
+ if (errorCount) {
+ const message = i18n.tc(
+ 'pageSessions.toast.errorDelete',
+ errorCount
+ );
+ toastMessages.push({ type: 'error', message });
+ }
+ return toastMessages;
+ })
+ );
+ },
+ },
+};
+export default SessionsStore;
diff --git a/src/store/modules/SecurityAndAccess/UserManagementStore.js b/src/store/modules/SecurityAndAccess/UserManagementStore.js
new file mode 100644
index 00000000..362f3f64
--- /dev/null
+++ b/src/store/modules/SecurityAndAccess/UserManagementStore.js
@@ -0,0 +1,318 @@
+import api, { getResponseCount } from '@/store/api';
+import i18n from '@/i18n';
+
+const UserManagementStore = {
+ namespaced: true,
+ state: {
+ allUsers: [],
+ accountRoles: [],
+ accountLockoutDuration: null,
+ accountLockoutThreshold: null,
+ accountMinPasswordLength: null,
+ accountMaxPasswordLength: null,
+ },
+ getters: {
+ allUsers(state) {
+ return state.allUsers;
+ },
+ accountRoles(state) {
+ return state.accountRoles;
+ },
+ accountSettings(state) {
+ return {
+ lockoutDuration: state.accountLockoutDuration,
+ lockoutThreshold: state.accountLockoutThreshold,
+ };
+ },
+ accountPasswordRequirements(state) {
+ return {
+ minLength: state.accountMinPasswordLength,
+ maxLength: state.accountMaxPasswordLength,
+ };
+ },
+ },
+ mutations: {
+ setUsers(state, allUsers) {
+ state.allUsers = allUsers;
+ },
+ setAccountRoles(state, accountRoles) {
+ state.accountRoles = accountRoles;
+ },
+ setLockoutDuration(state, lockoutDuration) {
+ state.accountLockoutDuration = lockoutDuration;
+ },
+ setLockoutThreshold(state, lockoutThreshold) {
+ state.accountLockoutThreshold = lockoutThreshold;
+ },
+ setAccountMinPasswordLength(state, minPasswordLength) {
+ state.accountMinPasswordLength = minPasswordLength;
+ },
+ setAccountMaxPasswordLength(state, maxPasswordLength) {
+ state.accountMaxPasswordLength = maxPasswordLength;
+ },
+ },
+ actions: {
+ async getUsers({ commit }) {
+ return await api
+ .get('/redfish/v1/AccountService/Accounts')
+ .then((response) =>
+ response.data.Members.map((user) => user['@odata.id'])
+ )
+ .then((userIds) => api.all(userIds.map((user) => api.get(user))))
+ .then((users) => {
+ const userData = users.map((user) => user.data);
+ commit('setUsers', userData);
+ })
+ .catch((error) => {
+ console.log(error);
+ const message = i18n.t('pageUserManagement.toast.errorLoadUsers');
+ throw new Error(message);
+ });
+ },
+ getAccountSettings({ commit }) {
+ api
+ .get('/redfish/v1/AccountService')
+ .then(({ data }) => {
+ commit('setLockoutDuration', data.AccountLockoutDuration);
+ commit('setLockoutThreshold', data.AccountLockoutThreshold);
+ commit('setAccountMinPasswordLength', data.MinPasswordLength);
+ commit('setAccountMaxPasswordLength', data.MaxPasswordLength);
+ })
+ .catch((error) => {
+ console.log(error);
+ const message = i18n.t(
+ 'pageUserManagement.toast.errorLoadAccountSettings'
+ );
+ throw new Error(message);
+ });
+ },
+ getAccountRoles({ commit }) {
+ api
+ .get('/redfish/v1/AccountService/Roles')
+ .then(({ data: { Members = [] } = {} }) => {
+ const roles = Members.map((role) => {
+ return role['@odata.id'].split('/').pop();
+ });
+ commit('setAccountRoles', roles);
+ })
+ .catch((error) => console.log(error));
+ },
+ async createUser({ dispatch }, { username, password, privilege, status }) {
+ const data = {
+ UserName: username,
+ Password: password,
+ RoleId: privilege,
+ Enabled: status,
+ };
+ return await api
+ .post('/redfish/v1/AccountService/Accounts', data)
+ .then(() => dispatch('getUsers'))
+ .then(() =>
+ i18n.t('pageUserManagement.toast.successCreateUser', {
+ username,
+ })
+ )
+ .catch((error) => {
+ console.log(error);
+ const message = i18n.t('pageUserManagement.toast.errorCreateUser', {
+ username,
+ });
+ throw new Error(message);
+ });
+ },
+ async updateUser(
+ { dispatch },
+ { originalUsername, username, password, privilege, status, locked }
+ ) {
+ const data = {};
+ if (username) data.UserName = username;
+ if (password) data.Password = password;
+ if (privilege) data.RoleId = privilege;
+ if (status !== undefined) data.Enabled = status;
+ if (locked !== undefined) data.Locked = locked;
+ return await api
+ .patch(`/redfish/v1/AccountService/Accounts/${originalUsername}`, data)
+ .then(() => dispatch('getUsers'))
+ .then(() =>
+ i18n.t('pageUserManagement.toast.successUpdateUser', {
+ username: originalUsername,
+ })
+ )
+ .catch((error) => {
+ console.log(error);
+ const message = i18n.t('pageUserManagement.toast.errorUpdateUser', {
+ username: originalUsername,
+ });
+ throw new Error(message);
+ });
+ },
+ async deleteUser({ dispatch }, username) {
+ return await api
+ .delete(`/redfish/v1/AccountService/Accounts/${username}`)
+ .then(() => dispatch('getUsers'))
+ .then(() =>
+ i18n.t('pageUserManagement.toast.successDeleteUser', {
+ username,
+ })
+ )
+ .catch((error) => {
+ console.log(error);
+ const message = i18n.t('pageUserManagement.toast.errorDeleteUser', {
+ username,
+ });
+ throw new Error(message);
+ });
+ },
+ async deleteUsers({ dispatch }, users) {
+ const promises = users.map(({ username }) => {
+ return api
+ .delete(`/redfish/v1/AccountService/Accounts/${username}`)
+ .catch((error) => {
+ console.log(error);
+ return error;
+ });
+ });
+ return await api
+ .all(promises)
+ .then((response) => {
+ dispatch('getUsers');
+ return response;
+ })
+ .then(
+ api.spread((...responses) => {
+ const { successCount, errorCount } = getResponseCount(responses);
+ let toastMessages = [];
+
+ if (successCount) {
+ const message = i18n.tc(
+ 'pageUserManagement.toast.successBatchDelete',
+ successCount
+ );
+ toastMessages.push({ type: 'success', message });
+ }
+
+ if (errorCount) {
+ const message = i18n.tc(
+ 'pageUserManagement.toast.errorBatchDelete',
+ errorCount
+ );
+ toastMessages.push({ type: 'error', message });
+ }
+
+ return toastMessages;
+ })
+ );
+ },
+ async enableUsers({ dispatch }, users) {
+ const data = {
+ Enabled: true,
+ };
+ const promises = users.map(({ username }) => {
+ return api
+ .patch(`/redfish/v1/AccountService/Accounts/${username}`, data)
+ .catch((error) => {
+ console.log(error);
+ return error;
+ });
+ });
+ return await api
+ .all(promises)
+ .then((response) => {
+ dispatch('getUsers');
+ return response;
+ })
+ .then(
+ api.spread((...responses) => {
+ const { successCount, errorCount } = getResponseCount(responses);
+ let toastMessages = [];
+
+ if (successCount) {
+ const message = i18n.tc(
+ 'pageUserManagement.toast.successBatchEnable',
+ successCount
+ );
+ toastMessages.push({ type: 'success', message });
+ }
+
+ if (errorCount) {
+ const message = i18n.tc(
+ 'pageUserManagement.toast.errorBatchEnable',
+ errorCount
+ );
+ toastMessages.push({ type: 'error', message });
+ }
+
+ return toastMessages;
+ })
+ );
+ },
+ async disableUsers({ dispatch }, users) {
+ const data = {
+ Enabled: false,
+ };
+ const promises = users.map(({ username }) => {
+ return api
+ .patch(`/redfish/v1/AccountService/Accounts/${username}`, data)
+ .catch((error) => {
+ console.log(error);
+ return error;
+ });
+ });
+ return await api
+ .all(promises)
+ .then((response) => {
+ dispatch('getUsers');
+ return response;
+ })
+ .then(
+ api.spread((...responses) => {
+ const { successCount, errorCount } = getResponseCount(responses);
+ let toastMessages = [];
+
+ if (successCount) {
+ const message = i18n.tc(
+ 'pageUserManagement.toast.successBatchDisable',
+ successCount
+ );
+ toastMessages.push({ type: 'success', message });
+ }
+
+ if (errorCount) {
+ const message = i18n.tc(
+ 'pageUserManagement.toast.errorBatchDisable',
+ errorCount
+ );
+ toastMessages.push({ type: 'error', message });
+ }
+
+ return toastMessages;
+ })
+ );
+ },
+ async saveAccountSettings(
+ { dispatch },
+ { lockoutThreshold, lockoutDuration }
+ ) {
+ const data = {};
+ if (lockoutThreshold !== undefined) {
+ data.AccountLockoutThreshold = lockoutThreshold;
+ }
+ if (lockoutDuration !== undefined) {
+ data.AccountLockoutDuration = lockoutDuration;
+ }
+
+ return await api
+ .patch('/redfish/v1/AccountService', data)
+ //GET new settings to update view
+ .then(() => dispatch('getAccountSettings'))
+ .then(() => i18n.t('pageUserManagement.toast.successSaveSettings'))
+ .catch((error) => {
+ console.log(error);
+ const message = i18n.t('pageUserManagement.toast.errorSaveSettings');
+ throw new Error(message);
+ });
+ },
+ },
+};
+
+export default UserManagementStore;