Skip to content

Commit c2b179d

Browse files
committed
switch to load at main
1 parent 7f7f0bc commit c2b179d

File tree

5 files changed

+45
-42
lines changed

5 files changed

+45
-42
lines changed

MyApp.Client/src/layouts/default.vue

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
<script setup lang="ts">
22
import NavHeader from '@/components/NavHeader.vue'
33
import NavFooter from '@/components/NavFooter.vue'
4-
import { useApp } from "@/lib/gateway"
5-
6-
let app = useApp()
7-
app.load()
84
</script>
95

106
<template>

MyApp.Client/src/lib/auth.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@ const { user, hasRole, hasPermission, signIn, signOut } = useAuth()
3131

3232
export { user, hasRole, hasPermission }
3333

34-
checkAuth().then(auth => {
35-
if (auth) signIn(auth)
36-
else signOut()
37-
})
38-
3934
export async function revalidate() {
4035
loading.value = true
4136
const auth = await checkAuth()
@@ -55,25 +50,15 @@ export const signout = async (router:any, redirectTo?: string) => {
5550
await router.replace({ path: redirectTo ?? router?.currentRoute?.value.path, force: true })
5651
}
5752

58-
59-
// Use Route Guards to guard against access to pages
60-
type RouteGuard = { path:string, attr:string }
61-
const routes:RouteGuard[] = [
62-
{ path:'/profile', attr:'auth' },
63-
{ path:'/admin', attr:'role:Admin' },
64-
{ path:'/bookings', attr:'role:Employee' },
65-
{ path:'/bookings-crud', attr:'role:Employee' },
66-
]
67-
6853
export function configRouter(router:Router) {
69-
const invalidAttrRedirect = (to:RouteLocationNormalized, guardAttr:string, userAttrs:string[]) => userAttrs.indexOf('auth') === -1
54+
const invalidAttrRedirect = (to:RouteLocationNormalized, _:string, userAttrs:string[]) => userAttrs.indexOf('auth') === -1
7055
? Routes.signin(to.path)
7156
: Routes.forbidden()
7257

7358
// Validate Route guards against Authenticated User's Attributes
7459
const validateRoute = (to:RouteLocationNormalized, next:NavigationGuardNext, attrs:string[]) => {
75-
for (let i=0; i<routes.length; i++) {
76-
const route = routes[i]
60+
for (let i=0; i<Routes.guards.length; i++) {
61+
const route = Routes.guards[i]
7762
if (!route) continue
7863
const { path, attr } = route
7964
if (!to.path.startsWith(path)) continue
@@ -82,6 +67,7 @@ export function configRouter(router:Router) {
8267
const allowAdmin = isAdmin && (attr.startsWith('role:') || attr.startsWith('perm:'))
8368
if (!allowAdmin) {
8469
const goTo = invalidAttrRedirect(to, attr, attrs)
70+
console.debug(`Redirecting to ${goTo} as missing required '${attr}' to access '${to.path}'`)
8571
next(goTo)
8672
return
8773
}
@@ -90,7 +76,7 @@ export function configRouter(router:Router) {
9076
next()
9177
}
9278

93-
router.beforeEach((to:RouteLocationNormalized,from:RouteLocationNormalized,next:NavigationGuardNext) => {
79+
router.beforeEach((to:RouteLocationNormalized,_:RouteLocationNormalized,next:NavigationGuardNext) => {
9480
if (loading) {
9581
const stop = watchEffect(() => {
9682
validateRoute(to, next, attrs.value)

MyApp.Client/src/lib/gateway.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { JsonServiceClient } from "@servicestack/client"
2-
import { useMetadata } from "@servicestack/vue"
2+
import { useAuth, initMetadata } from "@servicestack/vue"
33
import type { Router } from "vue-router"
4+
import { checkAuth } from "./auth"
45

56
const serverRoutePaths = [
67
'/Identity',
@@ -17,18 +18,34 @@ export function isServerRoute(path:string) {
1718
return serverRoutePaths.some(x => path.startsWith(x))
1819
}
1920

21+
type RouteGuard = { path:string, attr:string }
22+
const Requires = {
23+
auth: (path:string):RouteGuard => ({ path, attr: 'auth' }),
24+
role: (path:string, role:string):RouteGuard => ({ path, attr: `role:${role}` })
25+
}
26+
2027
// Typed Routes used in Components
2128
export const Routes = {
2229
signin: (redirectTo?:string) => redirectTo ? `/signin?redirect=${redirectTo}` : `/signin`,
2330
forbidden: () => '/forbidden',
31+
32+
// Use Route Guards to guard against access to pages
33+
guards: [
34+
Requires.auth('/profile'),
35+
Requires.role('/admin', 'Admin'),
36+
Requires.role('/bookings-auto', 'Employee'),
37+
Requires.role('/bookings-crud', 'Employee'),
38+
],
2439
}
2540

2641
export const client = new JsonServiceClient()
2742

2843
export function useApp() {
29-
async function load (force?:boolean) {
30-
const { loadMetadata } = useMetadata()
31-
await loadMetadata({ olderThan: 0 })
44+
async function load() {
45+
const { signIn } = useAuth()
46+
initMetadata({ client })
47+
const auth = await checkAuth()
48+
if (auth) signIn(auth)
3249
}
3350
return {
3451
load,

MyApp.Client/src/main.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { createHead } from '@unhead/vue/client'
66
import App from './App.vue'
77

88
import ServiceStackVue from "@servicestack/vue"
9-
import { createRouter, createWebHistory } from 'vue-router'
9+
import { createRouter, createWebHistory, RouterLink } from 'vue-router'
1010
import type { RouteLocationNormalized } from 'vue-router'
1111
import { routes } from 'vue-router/auto-routes'
1212
import { setupLayouts } from 'virtual:generated-layouts'
@@ -16,8 +16,7 @@ import { Icon } from '@iconify/vue'
1616

1717
import LiteYoutube from "@/components/LiteYouTube"
1818
import { configRouter } from "@/lib/auth"
19-
import { isServerRoute } from "@/lib/gateway"
20-
import { client } from "@/lib/gateway"
19+
import { isServerRoute, useApp } from "@/lib/gateway"
2120

2221
const app = createApp(App)
2322
const head = createHead()
@@ -58,15 +57,20 @@ router.beforeEach((to, _from, next) => {
5857
else next()
5958
})
6059

60+
ServiceStackVue.component('RouterLink', RouterLink)
61+
const { client, load } = useApp()
62+
6163
const pinia = createPinia()
6264

63-
app
64-
.use(head)
65-
.use(router)
66-
.use(pinia)
67-
.use(ServiceStackVue)
68-
.provide('client', client)
69-
.provide('press', press)
70-
.component('LiteYouTube', LiteYoutube)
71-
.component('Iconify', Icon)
72-
.mount('#app')
65+
load().then(() => {
66+
app
67+
.use(head)
68+
.use(router)
69+
.use(pinia)
70+
.use(ServiceStackVue)
71+
.provide('client', client)
72+
.provide('press', press)
73+
.component('LiteYouTube', LiteYoutube)
74+
.component('Iconify', Icon)
75+
.mount('#app')
76+
})

MyApp.Client/src/pages/profile.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
<PrimaryButton class="mt-8" href="/Identity/Account/Manage">
1818
Identity Auth Account
1919
</PrimaryButton>
20-
<TextLink class="mt-8" href="/">
20+
<SecondaryButton class="mt-8" href="/">
2121
🏠 Home
22-
</TextLink>
22+
</SecondaryButton>
2323
</div>
2424
</template>
2525

0 commit comments

Comments
 (0)