diff options
author | Yoshie Muranaka <yoshiemuranaka@gmail.com> | 2020-04-17 19:39:41 +0300 |
---|---|---|
committer | Derick Montague <derick.montague@ibm.com> | 2020-05-01 19:08:33 +0300 |
commit | dc3d5411a7bd2afd84ed5d4b8f1e86a48f0fc962 (patch) | |
tree | d1788233eab6134df54361b1b5551aa9e3b7c607 /src/views | |
parent | f7aa7f9c8abe8480edfdf758ec25b26032e759a2 (diff) | |
download | webui-vue-dc3d5411a7bd2afd84ed5d4b8f1e86a48f0fc962.tar.xz |
Add LDAP role groups table
Adds ability to add, edit, and delete RemoteRoleMapping
objects from the GUI.
Role group table functionality includes sort, single row
edit and delete, and batch delete.
Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Change-Id: Id9168c90b78a6f4090ab0ab3e37e74b8cd821d54
Diffstat (limited to 'src/views')
-rw-r--r-- | src/views/AccessControl/Ldap/Ldap.vue | 87 | ||||
-rw-r--r-- | src/views/AccessControl/Ldap/ModalAddRoleGroup.vue | 164 | ||||
-rw-r--r-- | src/views/AccessControl/Ldap/TableRoleGroups.vue | 240 |
3 files changed, 449 insertions, 42 deletions
diff --git a/src/views/AccessControl/Ldap/Ldap.vue b/src/views/AccessControl/Ldap/Ldap.vue index c2d0e347..3ae4784f 100644 --- a/src/views/AccessControl/Ldap/Ldap.vue +++ b/src/views/AccessControl/Ldap/Ldap.vue @@ -8,14 +8,11 @@ <b-form-group class="mb-3" :label="$t('pageLdap.form.ldapAuthentication')" + label-for="enable-ldap-auth" > - <b-form-text id="enable-ldap-auth-help-block"> - {{ $t('pageLdap.form.ldapAuthenticationHelper') }} - </b-form-text> <b-form-checkbox id="enable-ldap-auth" v-model="form.ldapAuthenticationEnabled" - aria-describedby="enable-ldap-auth-help-block" @change="onChangeldapAuthenticationEnabled" > {{ $t('global.action.enable') }} @@ -193,7 +190,7 @@ </b-row> </b-form-group> </div> - <b-row class="mt-4"> + <b-row class="mt-4 mb-5"> <b-col> <b-btn variant="primary" @@ -206,6 +203,11 @@ </b-row> </b-form> </page-section> + + <!-- Role groups --> + <page-section :section-title="$t('pageLdap.roleGroups')"> + <table-role-groups /> + </page-section> </b-container> </template> @@ -220,17 +222,26 @@ import PageTitle from '@/components/Global/PageTitle'; import PageSection from '@/components/Global/PageSection'; import InfoTooltip from '@/components/Global/InfoTooltip'; import InputPasswordToggle from '@/components/Global/InputPasswordToggle'; +import TableRoleGroups from './TableRoleGroups'; export default { name: 'Ldap', - components: { InfoTooltip, InputPasswordToggle, PageTitle, PageSection }, + components: { + InfoTooltip, + InputPasswordToggle, + PageTitle, + PageSection, + TableRoleGroups + }, mixins: [BVToastMixin, VuelidateMixin], data() { return { form: { - ldapAuthenticationEnabled: false, + ldapAuthenticationEnabled: this.$store.getters['ldap/isServiceEnabled'], secureLdapEnabled: false, - activeDirectoryEnabled: false, + activeDirectoryEnabled: this.$store.getters[ + 'ldap/isActiveDirectoryEnabled' + ], serverUri: '', bindDn: '', bindPassword: '', @@ -241,7 +252,12 @@ export default { }; }, computed: { - ...mapGetters('ldap', ['isServiceEnabled', 'ldap', 'activeDirectory']), + ...mapGetters('ldap', [ + 'isServiceEnabled', + 'isActiveDirectoryEnabled', + 'ldap', + 'activeDirectory' + ]), sslCertificates() { return this.$store.getters['sslCertificates/allCertificates']; }, @@ -267,22 +283,9 @@ export default { isServiceEnabled: function(value) { this.form.ldapAuthenticationEnabled = value; }, - ldap: { - handler: function(value) { - if (value.serviceEnabled || !this.form.activeDirectoryEnabled) { - this.setFormValues(value); - } - }, - deep: true - }, - activeDirectory: { - handler: function(value) { - if (value.serviceEnabled) { - this.form.activeDirectoryEnabled = true; - this.setFormValues(value); - } - }, - deep: true + isActiveDirectoryEnabled: function(value) { + this.form.activeDirectoryEnabled = value; + this.setFormValues(); } }, validations: { @@ -321,20 +324,22 @@ export default { created() { this.$store.dispatch('ldap/getAccountSettings'); this.$store.dispatch('sslCertificates/getCertificates'); - if (this.form.activeDirectoryEnabled) { - this.setFormValues(this.activeDirectory); - } else { - this.setFormValues(this.ldap); - } + this.setFormValues(); }, methods: { - setFormValues({ - serviceAddress = '', - bindDn = '', - baseDn = '', - userAttribute = '', - groupsAttribute = '' - }) { + setFormValues(serviceType) { + if (!serviceType) { + serviceType = this.isActiveDirectoryEnabled + ? this.activeDirectory + : this.ldap; + } + const { + serviceAddress = '', + bindDn = '', + baseDn = '', + userAttribute = '', + groupsAttribute = '' + } = serviceType; const secureLdap = serviceAddress && serviceAddress.includes('ldaps://') ? true : false; const serverUri = serviceAddress @@ -377,6 +382,8 @@ export default { const serviceType = isActiveDirectoryEnabled ? this.activeDirectory : this.ldap; + // Set form values according to user selected + // service type this.setFormValues(serviceType); }, onChangeldapAuthenticationEnabled(isServiceEnabled) { @@ -387,11 +394,7 @@ export default { // when the service is enabled. This is to prevent // an error if a user clears any properties then // disables the service. - if (this.form.activeDirectoryEnabled) { - this.setFormValues(this.activeDirectory); - } else { - this.setFormValues(this.ldap); - } + this.setFormValues(); } } } diff --git a/src/views/AccessControl/Ldap/ModalAddRoleGroup.vue b/src/views/AccessControl/Ldap/ModalAddRoleGroup.vue new file mode 100644 index 00000000..e2da1eb1 --- /dev/null +++ b/src/views/AccessControl/Ldap/ModalAddRoleGroup.vue @@ -0,0 +1,164 @@ +<template> + <b-modal id="modal-role-group" ref="modal" @ok="onOk" @hidden="resetForm"> + <template v-slot:modal-title> + <template v-if="roleGroup"> + {{ $t('pageLdap.modal.editRoleGroup') }} + </template> + <template v-else> + {{ $t('pageLdap.modal.addNewRoleGroup') }} + </template> + </template> + <b-container> + <b-row> + <b-col sm="8"> + <b-form id="role-group"> + <!-- Edit role group --> + <template v-if="roleGroup !== null"> + <dl class="mb-4"> + <dt>{{ $t('pageLdap.modal.groupName') }}</dt> + <dd>{{ form.groupName }}</dd> + </dl> + </template> + + <!-- Add new role group --> + <template v-else> + <b-form-group + :label="$t('pageLdap.modal.groupName')" + label-for="role-group-name" + > + <b-form-input + id="role-group-name" + v-model="form.groupName" + :state="getValidationState($v.form.groupName)" + @input="$v.form.groupName.$touch()" + /> + <b-form-invalid-feedback role="alert"> + {{ $t('global.form.fieldRequired') }} + </b-form-invalid-feedback> + </b-form-group> + </template> + + <b-form-group + :label="$t('pageLdap.modal.groupPrivilege')" + label-for="privilege" + > + <b-form-select + id="privilege" + v-model="form.groupPrivilege" + :options="accountRoles" + :state="getValidationState($v.form.groupPrivilege)" + @input="$v.form.groupPrivilege.$touch()" + > + <template v-if="!roleGroup" v-slot:first> + <b-form-select-option :value="null" disabled> + {{ $t('global.form.selectAnOption') }} + </b-form-select-option> + </template> + </b-form-select> + <b-form-invalid-feedback role="alert"> + {{ $t('global.form.fieldRequired') }} + </b-form-invalid-feedback> + </b-form-group> + </b-form> + </b-col> + </b-row> + </b-container> + <template v-slot:modal-footer="{ ok, cancel }"> + <b-button variant="secondary" @click="cancel()"> + {{ $t('global.action.cancel') }} + </b-button> + <b-button form="role-group" type="submit" variant="primary" @click="ok()"> + <template v-if="roleGroup"> + {{ $t('global.action.save') }} + </template> + <template v-else> + {{ $t('global.action.add') }} + </template> + </b-button> + </template> + </b-modal> +</template> + +<script> +import { required, requiredIf } from 'vuelidate/lib/validators'; +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; + +export default { + mixins: [VuelidateMixin], + props: { + roleGroup: { + type: Object, + default: null, + validator: prop => { + if (prop === null) return true; + return ( + prop.hasOwnProperty('groupName') && + prop.hasOwnProperty('groupPrivilege') + ); + } + } + }, + data() { + return { + form: { + groupName: null, + groupPrivilege: null + } + }; + }, + computed: { + accountRoles() { + return this.$store.getters['localUsers/accountRoles']; + } + }, + watch: { + roleGroup: function(value) { + if (value === null) return; + this.form.groupName = value.groupName; + this.form.groupPrivilege = value.groupPrivilege; + } + }, + validations() { + return { + form: { + groupName: { + required: requiredIf(function() { + return !this.roleGroup; + }) + }, + groupPrivilege: { + required + } + } + }; + }, + methods: { + handleSubmit() { + this.$v.$touch(); + if (this.$v.$invalid) return; + this.$emit('ok', { + addNew: !this.roleGroup, + groupName: this.form.groupName, + groupPrivilege: this.form.groupPrivilege + }); + this.closeModal(); + }, + closeModal() { + this.$nextTick(() => { + this.$refs.modal.hide(); + }); + }, + resetForm() { + this.form.groupName = null; + this.form.groupPrivilege = null; + this.$v.$reset(); + this.$emit('hidden'); + }, + onOk(bvModalEvt) { + // prevent modal close + bvModalEvt.preventDefault(); + this.handleSubmit(); + } + } +}; +</script> diff --git a/src/views/AccessControl/Ldap/TableRoleGroups.vue b/src/views/AccessControl/Ldap/TableRoleGroups.vue new file mode 100644 index 00000000..a851a033 --- /dev/null +++ b/src/views/AccessControl/Ldap/TableRoleGroups.vue @@ -0,0 +1,240 @@ +<template> + <div> + <b-row> + <b-col md="9"> + <alert :show="isServiceEnabled === false" variant="info"> + {{ $t('pageLdap.tableRoleGroups.alertContent') }} + </alert> + </b-col> + </b-row> + <b-row> + <b-col class="text-right" md="9"> + <b-btn + variant="primary" + :disabled="!isServiceEnabled" + @click="initRoleGroupModal(null)" + > + <icon-add /> + {{ $t('pageLdap.addRoleGroup') }} + </b-btn> + </b-col> + </b-row> + <b-row> + <b-col md="9"> + <table-toolbar + ref="toolbar" + :selected-items-count="selectedRows.length" + :actions="batchActions" + @clearSelected="clearSelectedRows($refs.table)" + @batchAction="onBatchAction" + /> + <b-table + ref="table" + selectable + no-select-on-click + no-sort-reset + sort-icon-left + :items="tableItems" + :fields="fields" + @row-selected="onRowSelected($event, tableItems.length)" + > + <!-- Checkbox column --> + <template v-slot:head(checkbox)> + <b-form-checkbox + v-model="tableHeaderCheckboxModel" + :indeterminate="tableHeaderCheckboxIndeterminate" + :disabled="!isServiceEnabled" + @change="onChangeHeaderCheckbox($refs.table)" + /> + </template> + <template v-slot:cell(checkbox)="row"> + <b-form-checkbox + v-model="row.rowSelected" + :disabled="!isServiceEnabled" + @change="toggleSelectRow($refs.table, row.index)" + /> + </template> + + <!-- table actions column --> + <template v-slot:cell(actions)="{ item }"> + <table-row-action + v-for="(action, index) in item.actions" + :key="index" + :value="action.value" + :enabled="action.enabled" + :title="action.title" + @click:tableAction="onTableRowAction($event, item)" + > + <template v-slot:icon> + <icon-edit v-if="action.value === 'edit'" /> + <icon-trashcan v-if="action.value === 'delete'" /> + </template> + </table-row-action> + </template> + </b-table> + </b-col> + </b-row> + <modal-add-role-group + :role-group="activeRoleGroup" + @ok="saveRoleGroup" + @hidden="activeRoleGroup = null" + /> + </div> +</template> + +<script> +import IconEdit from '@carbon/icons-vue/es/edit/20'; +import IconTrashcan from '@carbon/icons-vue/es/trash-can/20'; +import IconAdd from '@carbon/icons-vue/es/add--alt/20'; +import { mapGetters } from 'vuex'; + +import Alert from '@/components/Global/Alert'; +import TableToolbar from '@/components/Global/TableToolbar'; +import TableRowAction from '@/components/Global/TableRowAction'; +import BVTableSelectableMixin from '@/components/Mixins/BVTableSelectableMixin'; +import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import ModalAddRoleGroup from './ModalAddRoleGroup'; + +export default { + components: { + Alert, + IconAdd, + IconEdit, + IconTrashcan, + ModalAddRoleGroup, + TableRowAction, + TableToolbar + }, + mixins: [BVTableSelectableMixin, BVToastMixin], + data() { + return { + activeRoleGroup: null, + fields: [ + { + key: 'checkbox', + sortable: false + }, + { + key: 'groupName', + sortable: true, + label: this.$t('pageLdap.tableRoleGroups.groupName') + }, + { + key: 'groupPrivilege', + sortable: true, + label: this.$t('pageLdap.tableRoleGroups.groupPrivilege') + }, + { + key: 'actions', + sortable: false, + label: '', + tdClass: 'text-right' + } + ], + batchActions: [ + { + value: 'delete', + label: this.$t('global.action.delete') + } + ] + }; + }, + computed: { + ...mapGetters('ldap', ['isServiceEnabled', 'enabledRoleGroups']), + tableItems() { + return this.enabledRoleGroups.map(({ LocalRole, RemoteGroup }) => { + return { + groupName: RemoteGroup, + groupPrivilege: LocalRole, + actions: [ + { + value: 'edit', + title: this.$t('global.action.edit'), + enabled: this.isServiceEnabled + }, + { + value: 'delete', + title: this.$t('global.action.delete'), + enabled: this.isServiceEnabled + } + ] + }; + }); + } + }, + created() { + this.$store.dispatch('localUsers/getAccountRoles'); + }, + methods: { + onBatchAction() { + this.$bvModal + .msgBoxConfirm( + this.$tc( + 'pageLdap.modal.deleteRoleGroupBatchConfirmMessage', + this.selectedRows.length + ), + { + title: this.$t('pageLdap.modal.deleteRoleGroup'), + okTitle: this.$t('global.action.delete') + } + ) + .then(deleteConfirmed => { + if (deleteConfirmed) { + this.$store + .dispatch('ldap/deleteRoleGroup', { + roleGroups: this.selectedRows + }) + .then(success => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)); + } + }); + }, + onTableRowAction(action, row) { + switch (action) { + case 'edit': + this.initRoleGroupModal(row); + break; + case 'delete': + this.$bvModal + .msgBoxConfirm( + this.$t('pageLdap.modal.deleteRoleGroupConfirmMessage', { + groupName: row.groupName + }), + { + title: this.$t('pageLdap.modal.deleteRoleGroup'), + okTitle: this.$t('global.action.delete') + } + ) + .then(deleteConfirmed => { + if (deleteConfirmed) { + this.$store + .dispatch('ldap/deleteRoleGroup', { roleGroups: [row] }) + .then(success => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)); + } + }); + break; + } + }, + initRoleGroupModal(roleGroup) { + this.activeRoleGroup = roleGroup; + this.$bvModal.show('modal-role-group'); + }, + saveRoleGroup({ addNew, groupName, groupPrivilege }) { + this.activeRoleGroup = null; + const data = { groupName, groupPrivilege }; + if (addNew) { + this.$store + .dispatch('ldap/addNewRoleGroup', data) + .then(success => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)); + } else { + this.$store + .dispatch('ldap/saveRoleGroup', data) + .then(success => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)); + } + } + } +}; +</script> |