fix: Allow users to login even if they have access to more than 15 accounts (#4475)
This commit is contained in:
@@ -92,7 +92,6 @@ export default {
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('setCurrentAccountId', this.$route.params.accountId);
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
this.handleResize();
|
||||
bus.$on(BUS_EVENTS.TOGGLE_SIDEMENU, this.toggleSidebar);
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
import VueRouter from 'vue-router';
|
||||
|
||||
import auth from '../api/auth';
|
||||
import login from './login/login.routes';
|
||||
import dashboard from './dashboard/dashboard.routes';
|
||||
import authRoute from './auth/auth.routes';
|
||||
import { frontendURL } from '../helper/URLHelper';
|
||||
import { clearBrowserSessionCookies } from '../store/utils/api';
|
||||
import authRoute from './auth/auth.routes';
|
||||
import dashboard from './dashboard/dashboard.routes';
|
||||
import login from './login/login.routes';
|
||||
import store from '../store';
|
||||
|
||||
const routes = [
|
||||
...login.routes,
|
||||
...dashboard.routes,
|
||||
...authRoute.routes,
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/app',
|
||||
},
|
||||
];
|
||||
const routes = [...login.routes, ...dashboard.routes, ...authRoute.routes];
|
||||
|
||||
window.roleWiseRoutes = {
|
||||
agent: [],
|
||||
@@ -63,8 +55,8 @@ const routeValidators = [
|
||||
{
|
||||
protected: false,
|
||||
loggedIn: true,
|
||||
handler: () => {
|
||||
const user = auth.getCurrentUser();
|
||||
handler: (_, getters) => {
|
||||
const user = getters.getCurrentUser;
|
||||
return `accounts/${user.account_id}/dashboard`;
|
||||
},
|
||||
},
|
||||
@@ -76,8 +68,8 @@ const routeValidators = [
|
||||
{
|
||||
protected: true,
|
||||
loggedIn: true,
|
||||
handler: to => {
|
||||
const user = auth.getCurrentUser();
|
||||
handler: (to, getters) => {
|
||||
const user = getters.getCurrentUser;
|
||||
const userRole = getUserRole(user, Number(to.params.accountId));
|
||||
const isAccessible = routeIsAccessibleFor(to.name, userRole);
|
||||
return isAccessible ? null : `accounts/${to.params.accountId}/dashboard`;
|
||||
@@ -90,15 +82,20 @@ const routeValidators = [
|
||||
},
|
||||
];
|
||||
|
||||
export const validateAuthenticateRoutePermission = (to, from, next) => {
|
||||
const isLoggedIn = auth.isLoggedIn();
|
||||
export const validateAuthenticateRoutePermission = (
|
||||
to,
|
||||
from,
|
||||
next,
|
||||
{ getters }
|
||||
) => {
|
||||
const isLoggedIn = getters.isLoggedIn;
|
||||
const isProtectedRoute = !unProtectedRoutes.includes(to.name);
|
||||
const strategy = routeValidators.find(
|
||||
validator =>
|
||||
validator.protected === isProtectedRoute &&
|
||||
validator.loggedIn === isLoggedIn
|
||||
);
|
||||
const nextRoute = strategy.handler(to);
|
||||
const nextRoute = strategy.handler(to, getters);
|
||||
return nextRoute ? next(frontendURL(nextRoute)) : next();
|
||||
};
|
||||
|
||||
@@ -109,38 +106,47 @@ const validateSSOLoginParams = to => {
|
||||
return isLoginRoute && hasValidSSOParams;
|
||||
};
|
||||
|
||||
const validateRouteAccess = (to, from, next) => {
|
||||
export const validateRouteAccess = (to, from, next, { getters }) => {
|
||||
// Disable navigation to signup page if signups are disabled
|
||||
// Signup route has an attribute (requireSignupEnabled)
|
||||
// defined in it's route definition
|
||||
if (
|
||||
window.chatwootConfig.signupEnabled !== 'true' &&
|
||||
to.meta &&
|
||||
to.meta.requireSignupEnabled
|
||||
) {
|
||||
const user = auth.getCurrentUser();
|
||||
next(frontendURL(`accounts/${user.account_id}/dashboard`));
|
||||
}
|
||||
|
||||
if (validateSSOLoginParams(to)) {
|
||||
clearBrowserSessionCookies();
|
||||
return next();
|
||||
return next(frontendURL('login'));
|
||||
}
|
||||
|
||||
// For routes which doesn't care about authentication, skip validation
|
||||
if (authIgnoreRoutes.includes(to.name)) {
|
||||
return next();
|
||||
}
|
||||
return validateAuthenticateRoutePermission(to, from, next);
|
||||
|
||||
return validateAuthenticateRoutePermission(to, from, next, { getters });
|
||||
};
|
||||
|
||||
// protecting routes
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (!to.name) {
|
||||
const user = auth.getCurrentUser();
|
||||
if (user) {
|
||||
return next(frontendURL(`accounts/${user.account_id}/dashboard`));
|
||||
export const initalizeRouter = () => {
|
||||
const userAuthentication = store.dispatch('setUser');
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (validateSSOLoginParams(to)) {
|
||||
clearBrowserSessionCookies();
|
||||
next();
|
||||
return;
|
||||
}
|
||||
return next('/app/login');
|
||||
}
|
||||
|
||||
return validateRouteAccess(to, from, next);
|
||||
});
|
||||
userAuthentication.then(() => {
|
||||
if (!to.name) {
|
||||
const { isLoggedIn, getCurrentUser: user } = store.getters;
|
||||
if (isLoggedIn) {
|
||||
return next(frontendURL(`accounts/${user.account_id}/dashboard`));
|
||||
}
|
||||
return next('/app/login');
|
||||
}
|
||||
|
||||
return validateRouteAccess(to, from, next, store);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'expect-more-jest';
|
||||
import { validateAuthenticateRoutePermission } from './index';
|
||||
import auth from '../api/auth';
|
||||
import {
|
||||
validateAuthenticateRoutePermission,
|
||||
validateRouteAccess,
|
||||
} from './index';
|
||||
|
||||
jest.mock('./dashboard/dashboard.routes', () => ({
|
||||
routes: [],
|
||||
@@ -11,94 +13,119 @@ jest.mock('./auth/auth.routes', () => ({
|
||||
jest.mock('./login/login.routes', () => ({
|
||||
routes: [],
|
||||
}));
|
||||
jest.mock('../constants', () => {
|
||||
return {
|
||||
GRAVATAR_URL: 'https://www.gravatar.com/avatar',
|
||||
CHANNELS: {
|
||||
FACEBOOK: 'facebook',
|
||||
},
|
||||
ASSIGNEE_TYPE: {
|
||||
ME: 'me',
|
||||
UNASSIGNED: 'unassigned',
|
||||
ALL: 'all',
|
||||
},
|
||||
STATUS_TYPE: {
|
||||
OPEN: 'open',
|
||||
RESOLVED: 'resolved',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
window.roleWiseRoutes = {};
|
||||
|
||||
describe(`behavior`, () => {
|
||||
describe('#validateAuthenticateRoutePermission', () => {
|
||||
describe(`when route is not protected`, () => {
|
||||
it(`should go to the dashboard when user is logged in`, () => {
|
||||
// Arrange
|
||||
spyOn(auth, 'isLoggedIn').and.returnValue(true);
|
||||
spyOn(auth, 'getCurrentUser').and.returnValue({
|
||||
account_id: 1,
|
||||
accounts: [{ id: 1, role: 'agent' }],
|
||||
});
|
||||
const to = { name: 'login' };
|
||||
const to = { name: 'login', params: { accountId: 1 } };
|
||||
const from = { name: '', params: { accountId: 1 } };
|
||||
const next = jest.fn();
|
||||
// Act
|
||||
validateAuthenticateRoutePermission(to, from, next);
|
||||
// Assert
|
||||
const getters = {
|
||||
isLoggedIn: true,
|
||||
getCurrentUser: {
|
||||
account_id: 1,
|
||||
id: 1,
|
||||
accounts: [{ id: 1, role: 'admin' }],
|
||||
},
|
||||
};
|
||||
validateAuthenticateRoutePermission(to, from, next, { getters });
|
||||
expect(next).toHaveBeenCalledWith('/app/accounts/1/dashboard');
|
||||
});
|
||||
it(`should go there when user is not logged in`, () => {
|
||||
const to = { name: 'login', params: {} };
|
||||
const from = { name: '', params: {} };
|
||||
const next = jest.fn();
|
||||
const getters = { isLoggedIn: false };
|
||||
validateAuthenticateRoutePermission(to, from, next, { getters });
|
||||
expect(next).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
describe(`when route is protected`, () => {
|
||||
describe(`when user not logged in`, () => {
|
||||
it(`should redirect to login`, () => {
|
||||
// Arrange
|
||||
spyOn(auth, 'isLoggedIn').and.returnValue(false);
|
||||
spyOn(auth, 'getCurrentUser').and.returnValue(null);
|
||||
const to = { name: 'some-protected-route', params: { accountId: 1 } };
|
||||
const from = { name: '' };
|
||||
const next = jest.fn();
|
||||
// Act
|
||||
validateAuthenticateRoutePermission(to, from, next);
|
||||
// Assert
|
||||
const getters = {
|
||||
isLoggedIn: false,
|
||||
getCurrentUser: {
|
||||
account_id: null,
|
||||
id: null,
|
||||
accounts: [],
|
||||
},
|
||||
};
|
||||
validateAuthenticateRoutePermission(to, from, next, { getters });
|
||||
expect(next).toHaveBeenCalledWith('/app/login');
|
||||
});
|
||||
});
|
||||
describe(`when user is logged in`, () => {
|
||||
describe(`when route is not accessible to current user`, () => {
|
||||
it(`should redirect to dashboard`, () => {
|
||||
// Arrange
|
||||
spyOn(auth, 'isLoggedIn').and.returnValue(true);
|
||||
spyOn(auth, 'getCurrentUser').and.returnValue({
|
||||
accounts: [{ id: 1, role: 'agent' }],
|
||||
});
|
||||
window.roleWiseRoutes.agent = ['dashboard'];
|
||||
const to = { name: 'admin', params: { accountId: 1 } };
|
||||
const from = { name: '' };
|
||||
const next = jest.fn();
|
||||
// Act
|
||||
validateAuthenticateRoutePermission(to, from, next);
|
||||
// Assert
|
||||
const getters = {
|
||||
isLoggedIn: true,
|
||||
getCurrentUser: {
|
||||
account_id: 1,
|
||||
id: 1,
|
||||
accounts: [{ id: 1, role: 'agent' }],
|
||||
},
|
||||
};
|
||||
validateAuthenticateRoutePermission(to, from, next, { getters });
|
||||
expect(next).toHaveBeenCalledWith('/app/accounts/1/dashboard');
|
||||
});
|
||||
});
|
||||
describe(`when route is accessible to current user`, () => {
|
||||
it(`should go there`, () => {
|
||||
// Arrange
|
||||
spyOn(auth, 'isLoggedIn').and.returnValue(true);
|
||||
spyOn(auth, 'getCurrentUser').and.returnValue({
|
||||
accounts: [{ id: 1, role: 'agent' }],
|
||||
});
|
||||
window.roleWiseRoutes.agent = ['dashboard', 'admin'];
|
||||
const to = { name: 'admin', params: { accountId: 1 } };
|
||||
const from = { name: '' };
|
||||
const next = jest.fn();
|
||||
// Act
|
||||
validateAuthenticateRoutePermission(to, from, next);
|
||||
// Assert
|
||||
const getters = {
|
||||
isLoggedIn: true,
|
||||
getCurrentUser: {
|
||||
account_id: 1,
|
||||
id: 1,
|
||||
accounts: [{ id: 1, role: 'agent' }],
|
||||
},
|
||||
};
|
||||
validateAuthenticateRoutePermission(to, from, next, { getters });
|
||||
expect(next).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#validateRouteAccess', () => {
|
||||
it('returns to login if signup is disabled', () => {
|
||||
window.chatwootConfig = { signupEnabled: 'false' };
|
||||
const to = { name: 'auth_signup', meta: { requireSignupEnabled: true } };
|
||||
const from = { name: '' };
|
||||
const next = jest.fn();
|
||||
validateRouteAccess(to, from, next, {});
|
||||
expect(next).toHaveBeenCalledWith('/app/login');
|
||||
});
|
||||
|
||||
it('returns next for an auth ignore route ', () => {
|
||||
const to = { name: 'auth_confirmation' };
|
||||
const from = { name: '' };
|
||||
const next = jest.fn();
|
||||
|
||||
validateRouteAccess(to, from, next, {});
|
||||
expect(next).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('returns route validation for everything else ', () => {
|
||||
const to = { name: 'login' };
|
||||
const from = { name: '' };
|
||||
const next = jest.fn();
|
||||
|
||||
validateRouteAccess(to, from, next, { getters: { isLoggedIn: false } });
|
||||
expect(next).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user