diff --git a/package.json b/package.json
index 96a3916..56834b8 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,7 @@
"build": "microbundle build --tsconfig ./tsconfig.json --name VueBrowserAcl",
"build:watch": "microbundle watch --tsconfig ./tsconfig.json --name VueBrowserAcl",
"test": "jest --config jest.config.json",
- "test:watch": "jest jest --config jest.config.json --watchAll",
+ "test:watch": "jest --config jest.config.json --watchAll",
"version": "npm run build && git add -A ./dist",
"postversion": "git push && git push --tags"
},
@@ -37,19 +37,18 @@
"browser-acl": "^0.9.1"
},
"devDependencies": {
- "@babel/core": "^7.9.6",
- "@babel/preset-env": "^7.9.6",
- "@nuxt/types": "^0.7.6",
- "@types/jest": "^25.2.3",
- "@vue/test-utils": "^1.0.3",
- "babel-jest": "^26.0.1",
- "jest": "^26.0.1",
- "microbundle": "^0.12.0",
- "ts-jest": "^26.0.0",
- "typescript": "^3.9.3",
- "vue": "^2.6.11",
- "vue-router": "^3.2.0",
- "vue-template-compiler": "^2.6.11"
+ "@babel/core": "^7.12.13",
+ "@babel/preset-env": "^7.12.13",
+ "@types/jest": "^26.0.20",
+ "@vue/test-utils": "^1.1.3",
+ "babel-jest": "^26.6.3",
+ "jest": "^26.6.3",
+ "microbundle": "^0.13.0",
+ "ts-jest": "^26.5.0",
+ "typescript": "^4.1.3",
+ "vue": "^2.6.12",
+ "vue-router": "^3.5.1",
+ "vue-template-compiler": "^2.6.12"
},
"prettier": {
"semi": false,
diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts
index 750f698..5a37d96 100644
--- a/src/__tests__/index.test.ts
+++ b/src/__tests__/index.test.ts
@@ -3,6 +3,7 @@ import { User } from '../../types'
import Acl from 'browser-acl'
import { Verb } from '../../types'
import VueAcl from '../index'
+import VueRouter, { RouteConfig } from 'vue-router'
let _user: User | null
@@ -26,7 +27,7 @@ describe('Bad setup', () => {
beforeEach(() => {
jest.spyOn(console, 'error')
// @ts-ignore
- console.error.mockImplementation(() => {})
+ console.error.mockImplementation(() => { })
})
afterEach(() => {
@@ -54,6 +55,110 @@ describe('Bad setup', () => {
})
})
+
+const routes: RouteConfig[] = [
+ {
+ path: "*",
+ redirect: '/home'
+ },
+ {
+ path: '/home',
+ component: {
+ render: (c) => c('div', "Normal Route")
+ },
+ meta: {
+ can: 'see-home'
+ }
+ },
+ {
+ path: '/nocanroute',
+ component: {
+ render: (c) => c('div', "Shouldn't be here in strict mode")
+ }
+ },
+ {
+ path: '/fallback',
+ component: {
+ render: (c) => c('div', "Fallback Route")
+ },
+ meta: {
+ can: true
+ }
+
+ }
+]
+
+describe('Router integration', () => {
+ test('Strict mode directs to fallback route with no meta', async () => {
+ const localVue = createLocalVue()
+ localVue.use(VueRouter)
+
+ const router = new VueRouter({ routes: routes, mode: 'hash' })
+
+ router.push("");
+ localVue.use(VueAcl, getUser, (acl: Acl) => {
+ acl.rule('see-home', true)
+ }, { router: router, failRoute: '/fallback', strict: true, assumeGlobal: true })
+
+ const wrapper = mount(
+ {
+ template: `
+
+ `
+ },
+ { localVue, router },
+ )
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.html()).toContain('Normal Route')
+
+ router.push('/nocanroute').catch((err) => {
+ expect(err).toBe('[Error: Redirected when going from "/home" to "/nocanroute" via a navigation guard.]')
+ })
+
+ await wrapper.vm.$nextTick();
+
+ const html = wrapper.html();
+
+ expect(html).toContain('Fallback Route')
+
+ }),
+ test('Normal mode passes route with no meta', async () => {
+ const localVue = createLocalVue()
+ localVue.use(VueRouter)
+
+ const router = new VueRouter({ routes: routes, mode: 'hash'})
+
+ router.push("");
+ localVue.use(VueAcl, getUser, (acl: Acl) => {
+ acl.rule('see-home', true)
+ }, { router: router, failRoute: '/fallback'})
+
+ const wrapper = mount(
+ {
+ template: `
+
+ `
+ },
+ { localVue, router },
+ )
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.html()).toContain('Normal Route')
+
+ router.push('/nocanroute');
+
+ await wrapper.vm.$nextTick();
+
+ const html = wrapper.html();
+
+ expect(html).toContain("Shouldn't be here in strict mode")
+
+ })
+})
+
describe('Global rules', () => {
test('True for all', () => {
const localVue = createLocalVue()
diff --git a/src/index.ts b/src/index.ts
index e9ac3c8..c5c58c8 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -148,10 +148,20 @@ const VueAcl: VueAcl = {
}
router.beforeEach((to: Route, from: Route, next: any) => {
+ //prevent infinite loop if the fallback route contains no can meta
+ if(opt.strict && to.path === opt.failRoute) {
+ return next();
+ }
+
const metas = to.matched
.filter((route) => route.meta && findCan(route.meta))
.map((route) => route.meta)
-
+
+ // enforce strict mode
+ if(metas.length === 0 && opt.strict) {
+ next(opt.failRoute)
+ }
+
const chain = chainCans(metas, to, from)
chain.then((result) => {