generated from alphane/template
38 lines
1.1 KiB
TypeScript
38 lines
1.1 KiB
TypeScript
import { type RouteLocationNormalized } from "vue-router"
|
|
import { isEmpty, isNil } from "lodash"
|
|
|
|
import useCurrentUser, { type UserAsShow } from "@/use/use-current-user"
|
|
|
|
export async function authorizationGuard(to: RouteLocationNormalized) {
|
|
const guardGroups = to.matched
|
|
.map((record) => record.meta.guards as ((user: UserAsShow) => boolean)[] | undefined)
|
|
.filter((g): g is ((user: UserAsShow) => boolean)[] => !isNil(g) && !isEmpty(g))
|
|
|
|
if (guardGroups.length === 0) return true
|
|
|
|
const { currentUser, fetch } = useCurrentUser()
|
|
if (isNil(currentUser.value)) {
|
|
await fetch()
|
|
}
|
|
|
|
if (isNil(currentUser.value)) {
|
|
throw new Error("No current user")
|
|
}
|
|
|
|
// AND across matched records (every level must pass), OR within each
|
|
// record's guards array (any guard at that level satisfies it).
|
|
for (const guards of guardGroups) {
|
|
const passes = guards.some((guard) => {
|
|
if (typeof guard !== "function") {
|
|
throw new Error(`Guard ${guard} is not a function`)
|
|
}
|
|
return guard(currentUser.value as UserAsShow)
|
|
})
|
|
if (!passes) return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
export default authorizationGuard
|