MT#60623 Hide features not covered by the license

Following the changes about the licenses, some API will now
return a "403 - License not available" error when the needed
license is not available to the user. In the frontend we handle
the licenses with two levels of protection:
1) We hide menus of missing licenses from the sidebar
2) We add a guard in boot/routes.js that would redirect to the
homepage any attempts to access the mentioned menus, in case
they are mistakenly shown.

Change-Id: I9e88473ee90935db9b2a234ff03aef1b3a44a97b
(cherry picked from commit 2d1ec7c499)
(cherry picked from commit 1c1f7b5ee3)
mr12.5.1
Debora Crescenzo 9 months ago committed by Crescenzo Debora
parent adec1e280f
commit e7aee799c4

@ -34,7 +34,14 @@ export default ({ app, router, store }) => {
break
default:
if (to.meta?.profileAttribute) {
store.getters['user/hasSubscriberProfileAttribute'](to.meta.profileAttribute) ? next() : next('/')
const hasSubscriberProfileAttribute = store.getters['user/hasSubscriberProfileAttribute'](to.meta.profileAttribute)
if (to.meta.license && hasSubscriberProfileAttribute) {
// Guard to assure that users cannot click on menu if
// it is mistakenly visible when the license is inactive
store.getters['user/isLicenseActive'](to.meta.profileAttribute) ? next() : next('/')
}
hasSubscriberProfileAttribute ? next() : next('/')
} else if (to.meta?.profileAttributes) {
store.getters['user/hasSubscriberProfileAttributes'](to.meta.profileAttributes) ? next() : next('/')
} else {

@ -5,11 +5,9 @@
</template>
<script>
import {
mapGetters
} from 'vuex'
import { mapGetters } from 'vuex'
import CscMainMenu from 'components/CscMainMenu'
import { PROFILE_ATTRIBUTE_MAP, PROFILE_ATTRIBUTES_MAP } from 'src/constants'
import { LICENSES, PROFILE_ATTRIBUTE_MAP, PROFILE_ATTRIBUTES_MAP } from 'src/constants'
export default {
name: 'CscMainMenuTop',
@ -47,12 +45,13 @@ export default {
},
computed: {
...mapGetters('user', [
'isPbxEnabled',
'getCustomerId',
'hasFaxCapability',
'hasSubscriberProfileAttribute',
'hasSubscriberProfileAttributes',
'getCustomerId',
'isOldCSCProxyingAllowed'
'isLicenseActive',
'isOldCSCProxyingAllowed',
'isPbxEnabled'
]),
items () {
return [
@ -67,7 +66,7 @@ export default {
icon: 'call',
label: this.callStateTitle,
sublabel: this.callStateSubtitle,
visible: this.hasSubscriberProfileAttribute(PROFILE_ATTRIBUTE_MAP.cscCalls)
visible: this.hasSubscriberProfileAttribute(PROFILE_ATTRIBUTE_MAP.cscCalls) && this.isLicenseActive(LICENSES.csc_calls)
},
{
to: '/user/conversations',
@ -80,7 +79,7 @@ export default {
to: '/user/subscriber-phonebook',
icon: 'fas fa-user',
label: this.$t('Subscriber Phonebook'),
visible: true
visible: this.isLicenseActive(LICENSES.phonebook)
},
{
icon: 'settings_phone',
@ -139,7 +138,7 @@ export default {
to: '/user/recordings',
icon: 'play_circle',
label: this.$t('Recordings'),
visible: this.hasSubscriberProfileAttribute(PROFILE_ATTRIBUTE_MAP.recordings)
visible: this.hasSubscriberProfileAttribute(PROFILE_ATTRIBUTE_MAP.recordings) && this.isLicenseActive(LICENSES.call_recording)
}
]
},
@ -147,12 +146,15 @@ export default {
to: '/user/fax-settings',
icon: 'fas fa-fax',
label: this.$t('Fax Settings'),
visible: this.hasFaxCapability && this.hasSubscriberProfileAttribute(PROFILE_ATTRIBUTE_MAP.faxServer)
visible: this.hasFaxCapability &&
this.hasSubscriberProfileAttribute(PROFILE_ATTRIBUTE_MAP.faxServer) &&
this.isLicenseActive(LICENSES.fax)
},
{
icon: 'fas fa-chart-line',
label: this.$t('PBX Statistics'),
visible: this.isPbxAdmin,
visible: this.isPbxAdmin && this.isLicenseActive(LICENSES.pbx),
opened: this.isPbxConfiguration,
children: [
{
@ -166,7 +168,7 @@ export default {
{
icon: 'miscellaneous_services',
label: this.$t('PBX Configuration'),
visible: this.isPbxAdmin,
visible: this.isPbxAdmin && this.isLicenseActive(LICENSES.pbx),
opened: this.isPbxConfiguration,
children: [
{
@ -185,7 +187,7 @@ export default {
to: '/user/pbx-configuration/devices',
icon: 'fas fa-fax',
label: this.$t('Devices'),
visible: this.hasSubscriberProfileAttribute(PROFILE_ATTRIBUTE_MAP.deviceProvisioning)
visible: this.hasSubscriberProfileAttribute(PROFILE_ATTRIBUTE_MAP.deviceProvisioning) && this.isLicenseActive(LICENSES.device_provisioning)
},
{
to: '/user/pbx-configuration/call-queues',
@ -215,7 +217,7 @@ export default {
to: '/user/pbx-configuration/customer-phonebook',
icon: 'person',
label: this.$t('Customer Phonebook'),
visible: true
visible: this.isLicenseActive(LICENSES.phonebook)
},
{
to: '/user/pbx-configuration/customer-preferences',
@ -228,7 +230,9 @@ export default {
{
icon: 'settings',
label: this.$t('Extension Settings'),
visible: this.isPbxEnabled && this.hasSubscriberProfileAttributes(PROFILE_ATTRIBUTES_MAP.pbxSettings),
visible: this.isPbxEnabled &&
this.hasSubscriberProfileAttributes(PROFILE_ATTRIBUTES_MAP.pbxSettings) &&
this.isLicenseActive(LICENSES.pbx),
children: [
{
to: '/user/extension-settings/call-queues',

@ -32,3 +32,12 @@ export const PROFILE_ATTRIBUTES_MAP = {
pbxSettings: ['auto_attendant', 'cloud_pbx_callqueue', 'max_queue_length', 'queue_wrap_up_time', 'manager_secretary'],
pbxSettingsCallQueue: ['cloud_pbx_callqueue', 'max_queue_length', 'queue_wrap_up_time']
}
export const LICENSES = {
csc_calls: 'csc_calls',
device_provisioning: 'device_provisioning',
fax: 'fax',
pbx: 'pbx',
phonebook: 'phonebook',
call_recording: 'call_recording'
}

@ -123,6 +123,7 @@ import CscConversationsFilter from 'components/pages/Conversations/CscConversati
import CscConversationsCallsFilter from 'components/pages/Conversations/CscConversationsCallsFilter'
import CscRemoveDialog from 'components/CscRemoveDialog'
import { mapWaitingActions } from 'vue-wait'
import { LICENSES } from 'src/constants'
export default {
name: 'CscPageConversations',
components: {
@ -146,6 +147,20 @@ export default {
}
},
computed: {
...mapGetters('user', [
'isLicenseActive'
]),
...mapState('conversations', [
'reachedLastPage'
]),
...mapGetters('conversations', [
'items',
'isNumberIncomingBlocked',
'isNumberOutgoingBlocked'
]),
...mapGetters('call', [
'isCallEnabled'
]),
tabs () {
return [
{
@ -163,24 +178,15 @@ export default {
value: 'voicemail',
icon: 'voicemail'
},
{
label: this.$t('Faxes'),
value: 'fax',
icon: 'description'
}
]
this.isLicenseActive(LICENSES.fax)
? {
label: this.$t('Faxes'),
value: 'fax',
icon: 'description'
}
: null
].filter((label) => label !== null)
},
...mapState('conversations', [
'reachedLastPage'
]),
...mapGetters('conversations', [
'items',
'isNumberIncomingBlocked',
'isNumberOutgoingBlocked'
]),
...mapGetters('call', [
'isCallEnabled'
]),
pageStyle () {
return {
paddingTop: this.topMargin + 'px'

@ -4,7 +4,7 @@
class="row justify-center"
>
<csc-card-dashboard
v-if="showConvList"
v-if="showConversationsCard"
:title="$t('Voicebox Messages')"
:count="voicemailsCount"
:count-title="$t('Messages')"
@ -18,7 +18,7 @@
@action="downloadVoicemail"
/>
<csc-card-dashboard
v-if="showConvList"
v-if="showConversationsCard"
:title="$t('Call List')"
:count="callsCount"
:count-title="$t('Calls')"
@ -100,7 +100,7 @@ export default {
...mapGetters('user', [
'hasSubscriberProfileAttribute'
]),
showConvList () {
showConversationsCard () {
return this.hasSubscriberProfileAttribute(PROFILE_ATTRIBUTE_MAP.conversations)
},
showRegDevices () {

@ -1,4 +1,4 @@
import { PROFILE_ATTRIBUTE_MAP, PROFILE_ATTRIBUTES_MAP } from 'src/constants'
import { LICENSES, PROFILE_ATTRIBUTE_MAP, PROFILE_ATTRIBUTES_MAP } from 'src/constants'
import CscLayoutLogin from 'src/layouts/CscLayoutLogin'
import CscLayoutMain from 'src/layouts/CscLayoutMain'
@ -99,7 +99,8 @@ const routes = [
meta: {
get title () {
return i18n.global.tc('Subscriber Phonebook')
}
},
license: LICENSES.phonebook
}
},
{
@ -217,7 +218,8 @@ const routes = [
get subtitle () {
return i18n.global.tc('CDR')
}
}
},
license: LICENSES.pbx
},
{
path: 'pbx-configuration/groups',
@ -431,7 +433,8 @@ const routes = [
get subtitle () {
return i18n.global.tc('Set your fax settings')
},
profileAttribute: PROFILE_ATTRIBUTE_MAP.faxServer
profileAttribute: PROFILE_ATTRIBUTE_MAP.faxServer,
license: LICENSES.phonebook
}
},
{

@ -196,6 +196,9 @@ export default {
isOldCSCProxyingAllowed (state, getters) {
return getters.isAdmin && state.platformInfo?.csc_v2_mode === 'mixed' && !!getters.getCustomerId
},
isLicenseActive: (state) => (license) => {
return state?.platformInfo.licenses.includes(license)
},
isPbxPilot (state) {
return !!state.subscriber?.is_pbx_pilot
},

Loading…
Cancel
Save