fix(router): check system permissions against target project

This commit is contained in:
Cheng Zhou
2026-06-08 11:08:23 +08:00
parent 8cd8c38900
commit 30e2398400
9 changed files with 283 additions and 82 deletions
+22 -6
View File
@@ -4,7 +4,7 @@ import { useStudyStore } from "../store/study";
import { isSystemAdmin } from "../utils/roles";
import { isApiPermissionAllowed } from "../utils/apiPermissionValue";
import { findFirstAccessibleProjectPath, getProjectRoutePermission, hasProjectPermission } from "../utils/projectRoutePermissions";
import { fetchStudyDetail } from "../api/studies";
import { fetchStudies, fetchStudyDetail } from "../api/studies";
import { fetchApiEndpointPermissions } from "../api/projectPermissions";
import Layout from "../components/Layout.vue";
import Login from "../views/Login.vue";
@@ -419,16 +419,32 @@ const SYSTEM_PERMISSION_ROLES: Record<string, string[]> = {
[SYSTEM_PERMISSION_MONITORING_METRICS]: ["ADMIN", "PM"],
};
const hasSystemPermissionAccess = async (permissionKey: string, isAdmin: boolean) => {
const getTargetProjectId = (to: any) => {
const queryProjectId = typeof to.query?.projectId === "string" ? to.query.projectId : "";
const paramProjectId = typeof to.params?.projectId === "string" ? to.params.projectId : "";
const paramId = typeof to.params?.id === "string" ? to.params.id : "";
return queryProjectId || paramProjectId || paramId;
};
const hasSystemPermissionAccess = async (permissionKey: string, isAdmin: boolean, to: any) => {
const roles = SYSTEM_PERMISSION_ROLES[permissionKey] || [];
if (isAdmin) return roles.includes("ADMIN");
if (!roles.includes("PM")) return false;
const studyStore = useStudyStore();
const hasPmProject = studyStore.currentStudyRole === "PM" || (studyStore.currentStudy as any)?.role_in_study === "PM";
if (!hasPmProject) {
await studyStore.ensureDefaultPmStudy().catch(() => {});
const targetProjectId = getTargetProjectId(to);
if (targetProjectId) {
if (studyStore.currentStudy?.id === targetProjectId) {
return studyStore.currentStudyRole === "PM" || (studyStore.currentStudy as any)?.role_in_study === "PM";
}
const { data } = await fetchStudies();
const items = (data as any).items || [];
const matchedProject = items.find((study: any) => study.id === targetProjectId);
return matchedProject?.role_in_study === "PM";
}
const hasPmProject = studyStore.currentStudyRole === "PM" || (studyStore.currentStudy as any)?.role_in_study === "PM";
if (!hasPmProject) await studyStore.ensureDefaultPmStudy().catch(() => {});
return studyStore.currentStudyRole === "PM" || (studyStore.currentStudy as any)?.role_in_study === "PM";
};
@@ -555,7 +571,7 @@ router.beforeEach(async (to, _from, next) => {
}
}
if (to.meta.systemPermission) {
const allowed = await hasSystemPermissionAccess(to.meta.systemPermission as string, isAdmin);
const allowed = await hasSystemPermissionAccess(to.meta.systemPermission as string, isAdmin, to);
if (!allowed) {
next({ path: isAdmin ? "/admin/users" : "/admin/projects" });
return;