Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(projects): refactor router guard. fix #655 #667

Merged
merged 1 commit into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 73 additions & 96 deletions src/router/guard/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,54 +36,34 @@ export function createRouteGuard(router: Router) {
const routeRoles = to.meta.roles || [];

const hasRole = authStore.userInfo.roles.some(role => routeRoles.includes(role));

const hasAuth = authStore.isStaticSuper || !routeRoles.length || hasRole;

const routeSwitches: CommonType.StrategicPattern[] = [
// if it is login route when logged in, then switch to the root page
{
condition: isLogin && to.name === loginRoute,
callback: () => {
next({ name: rootRoute });
}
},
// if it is constant route, then it is allowed to access directly
{
condition: !needLogin,
callback: () => {
handleRouteSwitch(to, from, next);
}
},
// if the route need login but the user is not logged in, then switch to the login page
{
condition: !isLogin && needLogin,
callback: () => {
next({ name: loginRoute, query: { redirect: to.fullPath } });
}
},
// if the user is logged in and has authorization, then it is allowed to access
{
condition: isLogin && needLogin && hasAuth,
callback: () => {
handleRouteSwitch(to, from, next);
}
},
// if the user is logged in but does not have authorization, then switch to the 403 page
{
condition: isLogin && needLogin && !hasAuth,
callback: () => {
next({ name: noAuthorizationRoute });
}
}
];

routeSwitches.some(({ condition, callback }) => {
if (condition) {
callback();
}

return condition;
});
// if it is login route when logged in, then switch to the root page
if (to.name === loginRoute && isLogin) {
next({ name: rootRoute });
return;
}

// if the route does not need login, then it is allowed to access directly
if (!needLogin) {
handleRouteSwitch(to, from, next);
return;
}

// the route need login but the user is not logged in, then switch to the login page
if (!isLogin) {
next({ name: loginRoute, query: { redirect: to.fullPath } });
return;
}

// if the user is logged in but does not have authorization, then switch to the 403 page
if (!hasAuth) {
next({ name: noAuthorizationRoute });
return;
}

// switch route normally
handleRouteSwitch(to, from, next);
});
}

Expand All @@ -93,7 +73,6 @@ export function createRouteGuard(router: Router) {
* @param to to route
*/
async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw | null> {
const authStore = useAuthStore();
const routeStore = useRouteStore();

const notFoundRoute: RouteKey = 'not-found';
Expand All @@ -105,50 +84,28 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw

// the route is captured by the "not-found" route because the constant route is not initialized
// after the constant route is initialized, redirect to the original route
if (isNotFoundRoute) {
const path = to.fullPath;

const location: RouteLocationRaw = {
path,
replace: true,
query: to.query,
hash: to.hash
};

return location;
}
}
const path = to.fullPath;
const location: RouteLocationRaw = {
path,
replace: true,
query: to.query,
hash: to.hash
};

// if the route is the constant route but is not the "not-found" route, then it is allowed to access.
if (to.meta.constant && !isNotFoundRoute) {
return null;
return location;
}

// the auth route is initialized
// it is not the "not-found" route, then it is allowed to access
if (routeStore.isInitAuthRoute && !isNotFoundRoute) {
return null;
}
// it is captured by the "not-found" route, then check whether the route exists
if (routeStore.isInitAuthRoute && isNotFoundRoute) {
const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath);
const noPermissionRoute: RouteKey = '403';
const isLogin = Boolean(localStg.get('token'));

if (exist) {
const location: RouteLocationRaw = {
name: noPermissionRoute
};
if (!isLogin) {
// if the user is not logged in and the route is a constant route but not the "not-found" route, then it is allowed to access.
if (to.meta.constant && !isNotFoundRoute) {
routeStore.onRouteSwitchWhenNotLoggedIn();

return location;
return null;
}

return null;
}

// if the auth route is not initialized, then initialize the auth route
const isLogin = Boolean(localStg.get('token'));
// initialize the auth route requires the user to be logged in, if not, redirect to the login page
if (!isLogin) {
// if the user is not logged in, then switch to the login page
const loginRoute: RouteKey = 'login';
const query = getRouteQueryOfLoginRoute(to, routeStore.routeHome);

Expand All @@ -160,22 +117,42 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
return location;
}

await authStore.initUserInfo();
if (!routeStore.isInitAuthRoute) {
// initialize the auth route
await routeStore.initAuthRoute();

// initialize the auth route
await routeStore.initAuthRoute();
// the route is captured by the "not-found" route because the auth route is not initialized
// after the auth route is initialized, redirect to the original route
if (isNotFoundRoute) {
const rootRoute: RouteKey = 'root';
const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath;

// the route is captured by the "not-found" route because the auth route is not initialized
// after the auth route is initialized, redirect to the original route
if (isNotFoundRoute) {
const rootRoute: RouteKey = 'root';
const path = to.redirectedFrom?.name === rootRoute ? '/' : to.fullPath;
const location: RouteLocationRaw = {
path,
replace: true,
query: to.query,
hash: to.hash
};

return location;
}
}

// the auth route is initialized
// it is not the "not-found" route, then it is allowed to access
if (!isNotFoundRoute) {
routeStore.onRouteSwitchWhenLoggedIn();

return null;
}

// it is captured by the "not-found" route, then check whether the route exists
const exist = await routeStore.getIsAuthRouteExist(to.path as RoutePath);
const noPermissionRoute: RouteKey = '403';

if (exist) {
const location: RouteLocationRaw = {
path,
replace: true,
query: to.query,
hash: to.hash
name: noPermissionRoute
};

return location;
Expand Down
12 changes: 11 additions & 1 deletion src/store/modules/route/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,14 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
return getSelectedMenuKeyPathByKey(selectedKey, menus.value);
}

async function onRouteSwitchWhenLoggedIn() {
authStore.initUserInfo();
}

async function onRouteSwitchWhenNotLoggedIn() {
// some global init logic if it does not need to be logged in
}

return {
resetStore,
routeHome,
Expand All @@ -326,6 +334,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
isInitAuthRoute,
setIsInitAuthRoute,
getIsAuthRouteExist,
getSelectedMenuKeyPath
getSelectedMenuKeyPath,
onRouteSwitchWhenLoggedIn,
onRouteSwitchWhenNotLoggedIn
};
});
Loading