Skip to content

Commit

Permalink
feat: enhance route matching logic with support for exact, parameter,…
Browse files Browse the repository at this point in the history
… and wildcard routes
  • Loading branch information
typeWolffo committed Jan 8, 2025
1 parent 5ea9efc commit 08fe5b9
Showing 1 changed file with 48 additions and 3 deletions.
51 changes: 48 additions & 3 deletions apps/web/app/config/navigationConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,63 @@ export const adminNavigationConfig: NavigationItem[] = [
},
];

/**
* Finds matching route access roles for a given path by checking different types of routes in order:
* 1. Exact matches (e.g., "courses/new" matches "courses/new")
* 2. Parameter routes (e.g., "teachers/123" matches "teachers/:id")
* 3. Wildcard routes (e.g., "teachers/123/settings" matches "teachers/*")
*
* @param path - The actual URL path to match (e.g., "teachers/123")
* @returns UserRole[] | undefined - Array of user roles that can access this path, or undefined if no match
*
* @example
* // Exact match
* findMatchingRoute("courses/new") // matches "courses/new" in config
*
* // Parameter match
* findMatchingRoute("teachers/123") // matches "teachers/:id" in config
* findMatchingRoute("course/456/lesson/789") // matches "course/:courseId/lesson/:lessonId"
*
* // Wildcard match
* findMatchingRoute("teachers/123/settings") // matches "teachers/*"
*
* How matching works:
* 1. First, tries to find an exact match in routeAccessConfig
* 2. If no exact match, looks for parameter routes (:id)
* - Splits both paths into segments
* - Segments with ":" are treated as valid matches for any value
* - All other segments must match exactly
* 3. If still no match, checks wildcard routes (*)
* - Matches if path starts with the part before "*"
*/
export const findMatchingRoute = (path: string) => {
if (routeAccessConfig[path]) {
console.log("mariusz ->", routeAccessConfig[path]);
return routeAccessConfig[path];
}

const paramRoutes = Object.entries(routeAccessConfig).filter(
([route]) => route.includes(":") && !route.includes("*"),
);

for (const [route, roles] of paramRoutes) {
const routeParts = route.split("/");
const pathParts = path.split("/");

if (routeParts.length !== pathParts.length) continue;

const matches = routeParts.every((part, index) => {
if (part.startsWith(":")) return true;
return part === pathParts[index];
});

if (matches) return roles;
}

const wildcardRoutes = Object.entries(routeAccessConfig).filter(([route]) => route.includes("*"));

for (const [route, roles] of wildcardRoutes) {
const routeWithoutWildcard = route.replace("/*", "");
console.log({ routeWithoutWildcard });
if (path.startsWith(routeWithoutWildcard)) {
console.log({ roles });
return roles;
}
}
Expand Down

0 comments on commit 08fe5b9

Please sign in to comment.