Support async route permissions in guards (#7700)

#### What type of PR is this?

/area ui
/kind bug
/milestone 2.21.x

#### What this PR does / why we need it:

Fix routing navigation issue with async route permission functions

Caused by https://github.com/halo-dev/halo/pull/7688

#### Does this PR introduce a user-facing change?

```release-note
None
```
pull/7711/head
Ryan Wang 2025-08-19 15:01:15 +08:00 committed by GitHub
parent 3487132154
commit 157a8eb42d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 24 deletions

View File

@ -7,7 +7,7 @@ import type { Role } from "@halo-dev/api-client";
import type { RouteLocationNormalized, Router } from "vue-router";
export function setupPermissionGuard(router: Router) {
router.beforeEach((to, _, next) => {
router.beforeEach(async (to, _, next) => {
const userStore = useUserStore();
const roleStore = useRoleStore();
@ -16,7 +16,7 @@ export function setupPermissionGuard(router: Router) {
return;
}
if (checkRoutePermissions(to, roleStore.permissions.uiPermissions)) {
if (await checkRoutePermissions(to, roleStore.permissions.uiPermissions)) {
next();
} else {
next({ name: "Forbidden" });
@ -38,17 +38,31 @@ function isConsoleAccessDisallowed(currentRoles?: Role[]): boolean {
);
}
function checkRoutePermissions(
async function checkRoutePermissions(
to: RouteLocationNormalized,
uiPermissions: string[]
): boolean {
): Promise<boolean> {
const { meta } = to;
if (meta?.permissions) {
return hasPermission(
Array.from(uiPermissions),
meta.permissions as string[],
true
);
if (!meta?.permissions) {
return true;
}
return true;
if (typeof meta.permissions === "function") {
try {
return await meta.permissions(uiPermissions);
} catch (e) {
console.error(
`Error checking permissions for route ${String(to.name)}:`,
e
);
return false;
}
}
return hasPermission(
Array.from(uiPermissions),
meta.permissions as string[],
true
);
}

View File

@ -1,22 +1,44 @@
import { useRoleStore } from "@/stores/role";
import { hasPermission } from "@/utils/permission";
import type { Router } from "vue-router";
import type { RouteLocationNormalized, Router } from "vue-router";
export function setupPermissionGuard(router: Router) {
router.beforeEach((to, _from, next) => {
router.beforeEach(async (to, _from, next) => {
const roleStore = useRoleStore();
const { uiPermissions } = roleStore.permissions;
const { meta } = to;
if (meta && meta.permissions) {
const flag = hasPermission(
Array.from(uiPermissions),
meta.permissions as string[],
true
);
if (!flag) {
next({ name: "Forbidden" });
}
if (await checkRoutePermissions(to, uiPermissions)) {
next();
} else {
next({ name: "Forbidden" });
}
next();
});
}
async function checkRoutePermissions(
to: RouteLocationNormalized,
uiPermissions: string[]
): Promise<boolean> {
const { meta } = to;
if (!meta?.permissions) {
return true;
}
if (typeof meta.permissions === "function") {
try {
return await meta.permissions(uiPermissions);
} catch (e) {
console.error(
`Error checking permissions for route ${String(to.name)}:`,
e
);
return false;
}
}
return hasPermission(
Array.from(uiPermissions),
meta.permissions as string[],
true
);
}