Skip to content

Commit 28c3302

Browse files
committed
Split Auth & Permission meta guards
1 parent 2f378e3 commit 28c3302

File tree

4 files changed

+39
-16
lines changed

4 files changed

+39
-16
lines changed

packages/sprinkle-account/app/assets/guards/authGuard.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ export function useAuthGuard(router: Router) {
1212
return router.currentRoute.value.meta.auth ?? null
1313
}
1414

15+
/**
16+
* Return the auth RouteGuard
17+
*/
18+
const getRoutePermission = () => {
19+
return router.currentRoute.value.meta.permission ?? null
20+
}
21+
1522
/**
1623
* Return the guest RouteGuard
1724
*/
@@ -34,9 +41,9 @@ export function useAuthGuard(router: Router) {
3441
* Apply permission route guard
3542
*/
3643
const applyPermissionGuard = () => {
37-
const authGuard = getRouteAuth()
38-
if (authGuard?.permission !== undefined && !auth.checkAccess(authGuard.permission)) {
39-
const redirectTo = authGuard.redirect ?? getErrorRoute('Forbidden')
44+
const permissionGuard = getRoutePermission()
45+
if (permissionGuard?.slug !== undefined && !auth.checkAccess(permissionGuard.slug)) {
46+
const redirectTo = permissionGuard.redirect ?? getErrorRoute('Forbidden')
4047
redirect(redirectTo)
4148
}
4249
}

packages/sprinkle-account/app/assets/interfaces/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export type { UserInterface } from './models/userInterface'
22
export type { GroupInterface } from './models/groupInterface'
33
export type { RoleInterface } from './models/roleInterface'
44
export type { PermissionInterface, UserPermissionsMapInterface } from './models/permissionInterface'
5-
export type { RouteAuthGuard, RouteGuestGuard } from './routes'
5+
export type { RouteGuard, RoutePermissionGuard } from './routes'
66
export type { AuthCheckResponse } from './AuthCheckApi'
77
export type { ProfileEditRequest } from './ProfileEditApi'
88
export type { PasswordEditRequest } from './PasswordEditApi'

packages/sprinkle-account/app/assets/interfaces/routes.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@
99
*/
1010
import 'vue-router'
1111

12-
export interface RouteAuthGuard {
12+
export interface RouteGuard {
1313
redirect?: string | { name: string }
14-
permission?: string
1514
}
1615

17-
export interface RouteGuestGuard {
18-
redirect?: string | { name: string }
16+
export interface RoutePermissionGuard extends RouteGuard {
17+
slug: string
1918
}
2019

2120
declare module 'vue-router' {
2221
interface RouteMeta {
23-
auth?: RouteAuthGuard
24-
guest?: RouteGuestGuard
22+
auth?: RouteGuard
23+
guest?: RouteGuard
24+
permission?: RoutePermissionGuard
2525
}
2626
}

packages/sprinkle-account/app/assets/tests/guards/authGuard.test.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
33
import { useAuthGuard } from '../../guards/authGuard'
44
import * as Auth from '../../stores/auth'
5-
import type { RouteAuthGuard, RouteGuestGuard } from 'app/assets/interfaces'
5+
import type { RouteGuard, RoutePermissionGuard } from 'app/assets/interfaces'
66

77
// Default mock for the auth store and router
88
const mockAuthStore = {
@@ -15,8 +15,9 @@ const mockRouter = {
1515
value: {
1616
path: '/foo/bar',
1717
meta: {
18-
auth: undefined as RouteAuthGuard | undefined,
19-
guest: undefined as RouteGuestGuard | undefined
18+
auth: undefined as RouteGuard | undefined,
19+
guest: undefined as RouteGuard | undefined,
20+
permission: undefined as RoutePermissionGuard | undefined
2021
}
2122
}
2223
},
@@ -45,6 +46,8 @@ describe('authGuard useAuthGuard() method', () => {
4546
test('should redirect to login if route requires auth and user is not authenticated', () => {
4647
// Arrange
4748
mockRouter.currentRoute.value.meta.auth = { redirect: '/login' }
49+
mockRouter.currentRoute.value.meta.permission = undefined
50+
mockRouter.currentRoute.value.meta.guest = undefined
4851
mockAuthStore.isAuthenticated = false
4952

5053
// Act
@@ -58,6 +61,8 @@ describe('authGuard useAuthGuard() method', () => {
5861
test('should not redirect if route requires auth and user is authenticated', () => {
5962
// Arrange
6063
mockRouter.currentRoute.value.meta.auth = { redirect: '/login' }
64+
mockRouter.currentRoute.value.meta.permission = undefined
65+
mockRouter.currentRoute.value.meta.guest = undefined
6166
mockAuthStore.isAuthenticated = true
6267

6368
// Act
@@ -69,7 +74,9 @@ describe('authGuard useAuthGuard() method', () => {
6974

7075
test('should not redirect if route requires permission and user does not have it', () => {
7176
// Arrange
72-
mockRouter.currentRoute.value.meta.auth = { permission: 'foo.bar', redirect: '/login' }
77+
mockRouter.currentRoute.value.meta.auth = undefined
78+
mockRouter.currentRoute.value.meta.permission = { slug: 'foo.bar', redirect: '/login' }
79+
mockRouter.currentRoute.value.meta.guest = undefined
7380
mockAuthStore.isAuthenticated = true
7481

7582
// Act
@@ -82,6 +89,7 @@ describe('authGuard useAuthGuard() method', () => {
8289
test('should not redirect if route requires guests and user is not authenticated', () => {
8390
// Arrange
8491
mockRouter.currentRoute.value.meta.auth = undefined
92+
mockRouter.currentRoute.value.meta.permission = undefined
8593
mockRouter.currentRoute.value.meta.guest = { redirect: '/' }
8694
mockAuthStore.isAuthenticated = false
8795

@@ -94,6 +102,8 @@ describe('authGuard useAuthGuard() method', () => {
94102

95103
test('should redirect to home if route is for guests and user is authenticated', () => {
96104
// Arrange
105+
mockRouter.currentRoute.value.meta.auth = undefined
106+
mockRouter.currentRoute.value.meta.permission = undefined
97107
mockRouter.currentRoute.value.meta.guest = { redirect: '/' }
98108
mockAuthStore.isAuthenticated = true
99109

@@ -107,6 +117,8 @@ describe('authGuard useAuthGuard() method', () => {
107117
test('should use default redirect for auth guard if no redirect specified', () => {
108118
// Arrange
109119
mockRouter.currentRoute.value.meta.auth = {}
120+
mockRouter.currentRoute.value.meta.permission = undefined
121+
mockRouter.currentRoute.value.meta.guest = undefined
110122
mockAuthStore.isAuthenticated = false
111123

112124
// Act
@@ -122,7 +134,9 @@ describe('authGuard useAuthGuard() method', () => {
122134

123135
test('should use default redirect for permission guard if no redirect specified', () => {
124136
// Arrange
125-
mockRouter.currentRoute.value.meta.auth = { permission: 'foo.bar' }
137+
mockRouter.currentRoute.value.meta.auth = undefined
138+
mockRouter.currentRoute.value.meta.permission = { slug: 'foo.bar' }
139+
mockRouter.currentRoute.value.meta.guest = undefined
126140
mockAuthStore.isAuthenticated = false
127141

128142
// Act
@@ -131,13 +145,15 @@ describe('authGuard useAuthGuard() method', () => {
131145
// Assert
132146
expect(mockRouter.replace).toHaveBeenCalledWith(
133147
expect.objectContaining({
134-
name: 'Unauthorized'
148+
name: 'Forbidden'
135149
})
136150
)
137151
})
138152

139153
test('should use default redirect for guest guard if no redirect specified', () => {
140154
// Arrange
155+
mockRouter.currentRoute.value.meta.auth = undefined
156+
mockRouter.currentRoute.value.meta.permission = undefined
141157
mockRouter.currentRoute.value.meta.guest = {}
142158
mockAuthStore.isAuthenticated = true
143159

0 commit comments

Comments
 (0)