Update permissions on the frontend
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
:teams="teams"
|
||||
:custom-views="customViews"
|
||||
:menu-config="activeSecondaryMenu"
|
||||
:current-role="currentRole"
|
||||
:current-user="currentUser"
|
||||
:is-on-chatwoot-cloud="isOnChatwootCloud"
|
||||
@add-label="showAddLabelPopup"
|
||||
@toggle-accounts="toggleAccountModal"
|
||||
|
||||
@@ -60,9 +60,9 @@ export default {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
currentRole: {
|
||||
type: String,
|
||||
default: '',
|
||||
currentUser: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
isOnChatwootCloud: {
|
||||
type: Boolean,
|
||||
@@ -83,13 +83,16 @@ export default {
|
||||
if (!this.currentRole) {
|
||||
return [];
|
||||
}
|
||||
const menuItemsFilteredByRole = this.menuConfig.menuItems.filter(
|
||||
menuItem =>
|
||||
window.roleWiseRoutes[this.currentRole].indexOf(
|
||||
menuItem.toStateName
|
||||
) > -1
|
||||
const menuItemsFilteredByPermissions = this.menuConfig.menuItems.filter(
|
||||
menuItem => {
|
||||
const { meta: { menuPermissions = [] } = {} } = menuItem;
|
||||
const { permissions: userPermissions = [] } = this.currentUser;
|
||||
return menuPermissions.some(permission =>
|
||||
userPermissions.includes(permission)
|
||||
);
|
||||
}
|
||||
);
|
||||
return menuItemsFilteredByRole.filter(item => {
|
||||
return menuItemsFilteredByPermissions.filter(item => {
|
||||
if (item.showOnlyOnCloud) {
|
||||
return this.isOnChatwootCloud;
|
||||
}
|
||||
|
||||
@@ -65,27 +65,29 @@
|
||||
:show-child-count="showChildCount(child.count)"
|
||||
:child-item-count="child.count"
|
||||
/>
|
||||
<router-link
|
||||
v-if="showItem(menuItem)"
|
||||
v-slot="{ href, navigate }"
|
||||
:to="menuItem.toState"
|
||||
custom
|
||||
>
|
||||
<li class="pl-1">
|
||||
<a :href="href">
|
||||
<woot-button
|
||||
size="tiny"
|
||||
variant="clear"
|
||||
color-scheme="secondary"
|
||||
icon="add"
|
||||
:data-testid="menuItem.dataTestid"
|
||||
@click="e => newLinkClick(e, navigate)"
|
||||
>
|
||||
{{ $t(`SIDEBAR.${menuItem.newLinkTag}`) }}
|
||||
</woot-button>
|
||||
</a>
|
||||
</li>
|
||||
</router-link>
|
||||
<Policy :permissions="['account_manage']">
|
||||
<router-link
|
||||
v-if="menuItem.newLink"
|
||||
v-slot="{ href, navigate }"
|
||||
:to="menuItem.toState"
|
||||
custom
|
||||
>
|
||||
<li class="pl-1">
|
||||
<a :href="href">
|
||||
<woot-button
|
||||
size="tiny"
|
||||
variant="clear"
|
||||
color-scheme="secondary"
|
||||
icon="add"
|
||||
:data-testid="menuItem.dataTestid"
|
||||
@click="e => newLinkClick(e, navigate)"
|
||||
>
|
||||
{{ $t(`SIDEBAR.${menuItem.newLinkTag}`) }}
|
||||
</woot-button>
|
||||
</a>
|
||||
</li>
|
||||
</router-link>
|
||||
</Policy>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
@@ -105,9 +107,10 @@ import {
|
||||
isOnMentionsView,
|
||||
isOnUnattendedView,
|
||||
} from '../../../store/modules/conversations/helpers/actionHelpers';
|
||||
import Policy from '../../policy.vue';
|
||||
|
||||
export default {
|
||||
components: { SecondaryChildNavItem },
|
||||
components: { SecondaryChildNavItem, Policy },
|
||||
mixins: [adminMixin, configMixin],
|
||||
props: {
|
||||
menuItem: {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<script setup>
|
||||
import { useStoreGetters } from 'dashboard/composables/store';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
permissions: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const getters = useStoreGetters();
|
||||
const user = getters.getCurrentUser();
|
||||
|
||||
const hasPermission = computed(() =>
|
||||
props.permissions.some(permission => user.permissions.includes(permission))
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="hasPermission">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,10 @@
|
||||
export const ACCOUNT_PERMISSIONS = {
|
||||
ACCOUNT_MANAGE: 'account_manage',
|
||||
PORTAL_MANAGE: 'portal_manage',
|
||||
CONVERSATION_MANAGE: 'conversation_manage',
|
||||
CONVERSATION_UNASSIGNED_MANAGE: 'conversation_unassigned_manage',
|
||||
CONVERSATION_PARTICIPATING_MANAGE: 'conversation_participating_manage',
|
||||
MACROS_MANAGE: 'macros_manage',
|
||||
REPORTS_MANAGE: 'reports_manage',
|
||||
CONTACTS_MANAGE: 'contacts_manage',
|
||||
};
|
||||
@@ -3,17 +3,14 @@ export const getCurrentAccount = ({ accounts } = {}, accountId) => {
|
||||
return accounts.find(account => account.id === accountId);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line default-param-last
|
||||
export const getUserRole = ({ accounts } = {}, accountId) => {
|
||||
const currentAccount = getCurrentAccount({ accounts }, accountId) || {};
|
||||
return currentAccount.role || null;
|
||||
export const routeIsAccessibleFor = (route, userPermissions = []) => {
|
||||
const { meta: { permissions: routePermissions = [] } = {} } = route;
|
||||
return routePermissions.some(permissions =>
|
||||
userPermissions.includes(permissions)
|
||||
);
|
||||
};
|
||||
|
||||
export const routeIsAccessibleFor = (route, role, roleWiseRoutes) => {
|
||||
return roleWiseRoutes[role].includes(route);
|
||||
};
|
||||
|
||||
const validateActiveAccountRoutes = (to, user, roleWiseRoutes) => {
|
||||
const validateActiveAccountRoutes = (to, user) => {
|
||||
// If the current account is active, then check for the route permissions
|
||||
const accountDashboardURL = `accounts/${to.params.accountId}/dashboard`;
|
||||
|
||||
@@ -22,15 +19,13 @@ const validateActiveAccountRoutes = (to, user, roleWiseRoutes) => {
|
||||
return accountDashboardURL;
|
||||
}
|
||||
|
||||
const userRole = getUserRole(user, Number(to.params.accountId));
|
||||
const isAccessible = routeIsAccessibleFor(to.name, userRole, roleWiseRoutes);
|
||||
const isAccessible = routeIsAccessibleFor(to, user.permissions);
|
||||
// If the route is not accessible for the user, return to dashboard screen
|
||||
return isAccessible ? null : accountDashboardURL;
|
||||
};
|
||||
|
||||
export const validateLoggedInRoutes = (to, user, roleWiseRoutes) => {
|
||||
export const validateLoggedInRoutes = (to, user) => {
|
||||
const currentAccount = getCurrentAccount(user, Number(to.params.accountId));
|
||||
|
||||
// If current account is missing, either user does not have
|
||||
// access to the account or the account is deleted, return to login screen
|
||||
if (!currentAccount) {
|
||||
@@ -40,7 +35,7 @@ export const validateLoggedInRoutes = (to, user, roleWiseRoutes) => {
|
||||
const isCurrentAccountActive = currentAccount.status === 'active';
|
||||
|
||||
if (isCurrentAccountActive) {
|
||||
return validateActiveAccountRoutes(to, user, roleWiseRoutes);
|
||||
return validateActiveAccountRoutes(to, user);
|
||||
}
|
||||
|
||||
// If the current account is not active, then redirect the user to the suspended screen
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
/* eslint arrow-body-style: 0 */
|
||||
import { ACCOUNT_PERMISSIONS } from '../../../constants/permissions';
|
||||
import { frontendURL } from '../../../helper/URLHelper';
|
||||
const ConversationView = () => import('./ConversationView');
|
||||
|
||||
const GENERIC_CONVERSATION_PERMISSIONS = [
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_MANAGE,
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_PARTICIPATING_MANAGE,
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_UNASSIGNED_MANAGE,
|
||||
];
|
||||
|
||||
export default {
|
||||
routes: [
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/dashboard'),
|
||||
name: 'home',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: () => {
|
||||
return { inboxId: 0 };
|
||||
@@ -16,7 +23,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/conversations/:conversation_id'),
|
||||
name: 'inbox_conversation',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => {
|
||||
return { inboxId: 0, conversationId: route.params.conversation_id };
|
||||
@@ -25,7 +32,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/inbox/:inbox_id'),
|
||||
name: 'inbox_dashboard',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => {
|
||||
return { inboxId: route.params.inbox_id };
|
||||
@@ -36,7 +43,7 @@ export default {
|
||||
'accounts/:accountId/inbox/:inbox_id/conversations/:conversation_id'
|
||||
),
|
||||
name: 'conversation_through_inbox',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => {
|
||||
return {
|
||||
@@ -48,7 +55,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/label/:label'),
|
||||
name: 'label_conversations',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({ label: route.params.label }),
|
||||
},
|
||||
@@ -57,7 +64,7 @@ export default {
|
||||
'accounts/:accountId/label/:label/conversations/:conversation_id'
|
||||
),
|
||||
name: 'conversations_through_label',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversation_id,
|
||||
@@ -67,7 +74,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/team/:teamId'),
|
||||
name: 'team_conversations',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({ teamId: route.params.teamId }),
|
||||
},
|
||||
@@ -76,7 +83,7 @@ export default {
|
||||
'accounts/:accountId/team/:teamId/conversations/:conversationId'
|
||||
),
|
||||
name: 'conversations_through_team',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversationId,
|
||||
@@ -86,7 +93,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/custom_view/:id'),
|
||||
name: 'folder_conversations',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({ foldersId: route.params.id }),
|
||||
},
|
||||
@@ -95,7 +102,7 @@ export default {
|
||||
'accounts/:accountId/custom_view/:id/conversations/:conversation_id'
|
||||
),
|
||||
name: 'conversations_through_folders',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversation_id,
|
||||
@@ -105,7 +112,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/mentions/conversations'),
|
||||
name: 'conversation_mentions',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: () => ({ conversationType: 'mention' }),
|
||||
},
|
||||
@@ -114,7 +121,7 @@ export default {
|
||||
'accounts/:accountId/mentions/conversations/:conversationId'
|
||||
),
|
||||
name: 'conversation_through_mentions',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversationId,
|
||||
@@ -124,7 +131,7 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/unattended/conversations'),
|
||||
name: 'conversation_unattended',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: () => ({ conversationType: 'unattended' }),
|
||||
},
|
||||
@@ -133,7 +140,7 @@ export default {
|
||||
'accounts/:accountId/unattended/conversations/:conversationId'
|
||||
),
|
||||
name: 'conversation_through_unattended',
|
||||
roles: ['administrator', 'agent'],
|
||||
meta: { permissions: GENERIC_CONVERSATION_PERMISSIONS },
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversationId,
|
||||
@@ -143,8 +150,13 @@ export default {
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/participating/conversations'),
|
||||
name: 'conversation_participating',
|
||||
roles: ['administrator', 'agent'],
|
||||
component: ConversationView,
|
||||
meta: {
|
||||
permissions: [
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_MANAGE,
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_PARTICIPATING_MANAGE,
|
||||
],
|
||||
},
|
||||
props: () => ({ conversationType: 'participating' }),
|
||||
},
|
||||
{
|
||||
@@ -152,8 +164,13 @@ export default {
|
||||
'accounts/:accountId/participating/conversations/:conversationId'
|
||||
),
|
||||
name: 'conversation_through_participating',
|
||||
roles: ['administrator', 'agent'],
|
||||
component: ConversationView,
|
||||
meta: {
|
||||
permissions: [
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_MANAGE,
|
||||
ACCOUNT_PERMISSIONS.CONVERSATION_PARTICIPATING_MANAGE,
|
||||
],
|
||||
},
|
||||
props: route => ({
|
||||
conversationId: route.params.conversationId,
|
||||
conversationType: 'participating',
|
||||
|
||||
@@ -8,29 +8,6 @@ import AnalyticsHelper from '../helper/AnalyticsHelper';
|
||||
|
||||
const routes = [...dashboard.routes];
|
||||
|
||||
window.roleWiseRoutes = {
|
||||
agent: [],
|
||||
administrator: [],
|
||||
};
|
||||
|
||||
// generateRoleWiseRoute - updates window object with agent/admin route
|
||||
const generateRoleWiseRoute = route => {
|
||||
route.forEach(element => {
|
||||
if (element.children) {
|
||||
generateRoleWiseRoute(element.children);
|
||||
}
|
||||
if (element.roles) {
|
||||
element.roles.forEach(roleEl => {
|
||||
window.roleWiseRoutes[roleEl].push(element.name);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
// Create a object of routes
|
||||
// accessible by each role.
|
||||
// returns an object with roles as keys and routeArr as values
|
||||
generateRoleWiseRoute(routes);
|
||||
|
||||
export const router = new VueRouter({ mode: 'history', routes });
|
||||
|
||||
export const validateAuthenticateRoutePermission = (to, next, { getters }) => {
|
||||
@@ -45,11 +22,7 @@ export const validateAuthenticateRoutePermission = (to, next, { getters }) => {
|
||||
return next(frontendURL(`accounts/${user.account_id}/dashboard`));
|
||||
}
|
||||
|
||||
const nextRoute = validateLoggedInRoutes(
|
||||
to,
|
||||
getters.getCurrentUser,
|
||||
window.roleWiseRoutes
|
||||
);
|
||||
const nextRoute = validateLoggedInRoutes(to, getters.getCurrentUser);
|
||||
return nextRoute ? next(frontendURL(nextRoute)) : next();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user