Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Certificates and ModalUploadCertificate pages #295

Open
wants to merge 1 commit into
base: 1060-vue3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/assets/styles/bmc/custom/_forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,12 @@ div[role='group'] {
background-color: $gray-900;
border-color: $gray-900;
}
.form-control-file {
opacity: 0;
height: 0;
&:focus + span {
box-shadow:
inset 0 0 0 3px $primary,
inset 0 0 0 5px $white;
}
}
10 changes: 4 additions & 6 deletions src/components/Global/FormFile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,14 @@ const props = defineProps({
},
});

const file = ref(null);

const isSecondary = computed(() => {
return props.variant === 'secondary';
});

function clearFile() {
file.value = null;
emit('input', file.value);
}
const file = ref(null);
const isSecondary = computed(() => {
return props.variant === 'secondary';
});
</script>

<style lang="scss" scoped>
Expand Down
9 changes: 9 additions & 0 deletions src/router/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import IBMiServiceFunctions from '@/views/Logs/IBMiServiceFunctions';
import Notices from '@/views/Notices/Notices.vue';
import Sessions from '@/views/SecurityAndAccess/Sessions';
import Firmware from '@/views/Operations/Firmware';
import Certificates from '@/views/SecurityAndAccess/Certificates';

const roles = {
administrator: 'Administrator',
Expand Down Expand Up @@ -170,6 +171,14 @@ export const routes = [
title: i18n.global.t('appPageTitle.sessions'),
},
},
{
path: '/security-and-access/certificates',
name: 'certificates',
component: Certificates,
meta: {
title: i18n.global.t('appPageTitle.certificates'),
},
},
{
path: '/:pathMatch(.*)*',
name: 'page-not-found',
Expand Down
4 changes: 4 additions & 0 deletions src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import AuditLogsStore from './modules/Logs/AuditLogsStore';
import SessionsStore from './modules/SecurityAndAccess/SessionsStore.js';
import LicenseStore from './modules/ResourceManagement/LicenseStore';
import BmcStore from './modules/HardwareStatus/BmcStore';
import CertificatesStore from './modules/SecurityAndAccess/CertificatesStore';
import UserManagementStore from './modules/SecurityAndAccess/UserManagementStore';

// ... (export use other stores)
export {
Expand All @@ -40,4 +42,6 @@ export {
SessionsStore,
LicenseStore,
BmcStore,
CertificatesStore,
UserManagementStore,
};
1 change: 0 additions & 1 deletion src/store/modules/GlobalStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export const GlobalStore = defineStore('global', {
const bmcDateTime = response.data.DateTime;
const date = new Date(bmcDateTime);
this.bmcTime = date;
this.isAuthorized = false;
})
.catch((error) => console.log(error));
},
Expand Down
118 changes: 60 additions & 58 deletions src/store/modules/SecurityAndAccess/CertificatesStore.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import api from '@/store/api';
import i18n from '@/i18n';
import { defineStore } from 'pinia';

export const CERTIFICATE_TYPES = [
{
type: 'HTTPS Certificate',
location: '/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/',
label: i18n.t('pageCertificates.httpsCertificate'),
label: i18n.global.t('pageCertificates.httpsCertificate'),
limit: 1,
},
{
type: 'LDAP Certificate',
location: '/redfish/v1/AccountService/LDAP/Certificates/',
label: i18n.t('pageCertificates.ldapCertificate'),
label: i18n.global.t('pageCertificates.ldapCertificate'),
limit: 1,
},
{
Expand All @@ -19,13 +21,13 @@ export const CERTIFICATE_TYPES = [
// 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'),
label: i18n.global.t('pageCertificates.caCertificate'),
limit: 10,
},
{
type: 'ServiceLogin Certificate',
location: '/redfish/v1/AccountService/Accounts/service',
label: i18n.t('pageCertificates.serviceLoginCertificate'),
label: i18n.global.t('pageCertificates.serviceLoginCertificate'),
limit: 1,
},
];
Expand All @@ -42,31 +44,22 @@ const convertFileToBase64 = (file) =>
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
const CertificatesStore = {
export const CertificatesStore = defineStore('certificates', {
namespaced: true,
state: {
allCertificates: [],
acfCertificate: [],
availableUploadTypes: [],
state: () => {
return {
allCertificates: [],
acfCertificate: [],
availableUploadTypes: [],
};
},
getters: {
allCertificates: (state) => state.allCertificates,
acfCertificate: (state) => state.acfCertificate,
availableUploadTypes: (state) => state.availableUploadTypes,
},
mutations: {
setCertificates(state, certificates) {
state.allCertificates = certificates;
},
setAcfCertificate(state, certificate) {
state.acfCertificate = certificate;
},
setAvailableUploadTypes(state, availableUploadTypes) {
state.availableUploadTypes = availableUploadTypes;
},
allCertificatesGetter: (state) => state.allCertificates,
acfCertificateGetter: (state) => state.acfCertificate,
availableUploadTypesGetter: (state) => state.availableUploadTypes,
},
actions: {
async getAcfCertificate({ commit }) {
async getAcfCertificate() {
return await api
.get('/redfish/v1/AccountService/Accounts/service')
.then(
Expand All @@ -87,15 +80,15 @@ const CertificatesStore = {
validFrom: '',
validUntil: new Date(ACF.ExpirationDate),
};
commit('setAcfCertificate', [acfCertificate]);
this.acfCertificate = [acfCertificate];
} else {
commit('setAcfCertificate', []);
this.acfCertificate = [];
}
},
)
.catch((error) => console.log(error));
},
async getCertificates({ commit, dispatch }) {
async getCertificates() {
return await api
.get('/redfish/v1/CertificateService/CertificateLocations')
.then(
Expand Down Expand Up @@ -129,18 +122,15 @@ const CertificatesStore = {
validUntil: new Date(ValidNotAfter),
};
});
commit('setCertificates', certificates);
dispatch('getAvailableCertificates');
this.allCertificates = certificates;
this.getAvailableCertificates();
}),
);
});
},
async getAvailableCertificates({ commit, state }) {
async getAvailableCertificates() {
const availableUploadTypes = [];
const allCertificates = [
...state.acfCertificate,
...state.allCertificates,
];
const allCertificates = [...this.acfCertificate, ...this.allCertificates];
CERTIFICATE_TYPES.map((certificateType) => {
const certificateCount = allCertificates.filter((certificate) => {
return (
Expand All @@ -154,7 +144,7 @@ const CertificatesStore = {
availableUploadTypes.push(certificateType);
}
});
commit('setAvailableUploadTypes', availableUploadTypes);
this.availableUploadTypes = availableUploadTypes;
},
async addNewACFCertificate({ dispatch }, { file, type }) {
const base64File = await convertFileToBase64(file);
Expand All @@ -176,13 +166,15 @@ const CertificatesStore = {
dispatch('getCertificates');
})
.then(() => {
return i18n.t('pageCertificates.toast.successAddCertificate', {
return i18n.global.t('pageCertificates.toast.successAddCertificate', {
certificate: getCertificateProp(type, 'label'),
});
})
.catch((error) => {
console.log(error);
throw new Error(i18n.t('pageCertificates.toast.errorAddCertificate'));
throw new Error(
i18n.global.t('pageCertificates.toast.errorAddCertificate'),
);
});
},
async addNewACFCertificateOnLoginPage(_, { file, type }) {
Expand All @@ -201,13 +193,15 @@ const CertificatesStore = {
headers: { 'Content-Type': 'application/octet-stream' },
})
.then(() =>
i18n.t('pageCertificates.toast.successAddCertificate', {
i18n.global.t('pageCertificates.toast.successAddCertificate', {
certificate: getCertificateProp(type, 'label'),
}),
)
.catch((error) => {
console.log(error);
throw new Error(i18n.t('pageCertificates.toast.errorAddCertificate'));
throw new Error(
i18n.global.t('pageCertificates.toast.errorAddCertificate'),
);
});
},
async addNewCertificate({ dispatch }, { file, type }) {
Expand All @@ -219,21 +213,26 @@ const CertificatesStore = {
.then(() => dispatch('getCertificates'))
.then(() => {
if (typeOfCertificate === 'HTTPS Certificate') {
return i18n.t(
return i18n.global.t(
'pageCertificates.toast.successAddedHTTPCertificate',
{
certificate: getCertificateProp(type, 'label'),
},
);
} else {
return i18n.t('pageCertificates.toast.successAddCertificate', {
certificate: getCertificateProp(type, 'label'),
});
return i18n.global.t(
'pageCertificates.toast.successAddCertificate',
{
certificate: getCertificateProp(type, 'label'),
},
);
}
})
.catch((error) => {
console.log(error);
throw new Error(i18n.t('pageCertificates.toast.errorAddCertificate'));
throw new Error(
i18n.global.t('pageCertificates.toast.errorAddCertificate'),
);
});
},
async replaceACFCertificate({ dispatch }, { file, type, location }) {
Expand All @@ -256,14 +255,14 @@ const CertificatesStore = {
dispatch('getCertificates');
})
.then(() =>
i18n.t('pageCertificates.toast.successReplaceCertificate', {
i18n.global.t('pageCertificates.toast.successReplaceCertificate', {
certificate: getCertificateProp(type, 'label'),
}),
)
.catch((error) => {
console.log(error);
throw new Error(
i18n.t('pageCertificates.toast.errorReplaceCertificate'),
i18n.global.t('pageCertificates.toast.errorReplaceCertificate'),
);
});
},
Expand All @@ -287,22 +286,25 @@ const CertificatesStore = {
})
.then(() => {
if (typeOfCertificate === 'HTTPS Certificate') {
return i18n.t(
return i18n.global.t(
'pageCertificates.toast.successReplacedHTTPCertificate',
{
certificate: getCertificateProp(type, 'label'),
},
);
} else {
return i18n.t('pageCertificates.toast.successReplaceCertificate', {
certificate: getCertificateProp(type, 'label'),
});
return i18n.global.t(
'pageCertificates.toast.successReplaceCertificate',
{
certificate: getCertificateProp(type, 'label'),
},
);
}
})
.catch((error) => {
console.log(error);
throw new Error(
i18n.t('pageCertificates.toast.errorReplaceCertificate'),
i18n.global.t('pageCertificates.toast.errorReplaceCertificate'),
);
});
},
Expand All @@ -320,14 +322,14 @@ const CertificatesStore = {
.patch(location, data)
.then(() => dispatch('getCertificates'))
.then(() =>
i18n.t('pageCertificates.toast.successDeleteCertificate', {
i18n.global.t('pageCertificates.toast.successDeleteCertificate', {
certificate: getCertificateProp(type, 'label'),
}),
)
.catch((error) => {
console.log(error);
throw new Error(
i18n.t('pageCertificates.toast.errorDeleteCertificate'),
i18n.global.t('pageCertificates.toast.errorDeleteCertificate'),
);
});
},
Expand All @@ -336,18 +338,18 @@ const CertificatesStore = {
.delete(location)
.then(() => dispatch('getCertificates'))
.then(() =>
i18n.t('pageCertificates.toast.successDeleteCertificate', {
i18n.global.t('pageCertificates.toast.successDeleteCertificate', {
certificate: getCertificateProp(type, 'label'),
}),
)
.catch((error) => {
console.log(error);
throw new Error(
i18n.t('pageCertificates.toast.errorDeleteCertificate'),
i18n.global.t('pageCertificates.toast.errorDeleteCertificate'),
);
});
},
async generateCsr(_, userData) {
async generateCsr(userData) {
const {
certificateType,
country,
Expand Down Expand Up @@ -376,7 +378,7 @@ const CertificatesStore = {
data.KeyPairAlgorithm = keyPairAlgorithm;
data.AlternativeNames = alternateName;
if (keyCurveId) data.KeyCurveId = keyCurveId;
if (keyBitLength) data.KeyBitLength = keyBitLength;
if (keyBitLength) data.KeyBitLength = parseInt(keyBitLength);
if (contactPerson) data.ContactPerson = contactPerson;
if (emailAddress) data.Email = emailAddress;
return await api
Expand All @@ -389,5 +391,5 @@ const CertificatesStore = {
.catch((error) => console.log(error));
},
},
};
});
export default CertificatesStore;
Loading