Replies: 2 comments
-
|
Define your route permissions in a single shared object, then reference it from both the route's // src/permissions.ts
export const routePermissions = {
admin: ["write:admin"],
billing: ["read:billing", "write:billing"],
// ...
} as const;In your route: // src/routes/admin.tsx
import { routePermissions } from "../permissions";
export const Route = createFileRoute("/admin")({
beforeLoad: ({ context }) => {
const missing = routePermissions.admin.filter(
(p) => !context.auth.scopes.includes(p)
);
if (missing.length) throw redirect({ to: "/unauthorized" });
},
});In your links page: import { routePermissions } from "../permissions";
function NavLinks() {
const { scopes } = useAuth();
const hasAdmin = routePermissions.admin.every((p) => scopes.includes(p));
return (
<nav>
{hasAdmin && <Link to="/admin">Admin Panel</Link>}
</nav>
);
}The key is that If you want to go further, you could write a small helper that takes a permissions key and returns both a |
Beta Was this translation helpful? Give feedback.
-
|
Here's a complete, wired-up implementation using TanStack Router's router context — this is the cleanest pattern for exactly your use case. Step 1: Define permissions as a single source of truth// src/lib/permissions.ts
export const permissions = {
admin: ['write:admin'] as const,
billing: ['read:billing', 'write:billing'] as const,
} as const;
export type PermissionScope = (typeof permissions)[keyof typeof permissions][number];
export function hasScope(userScopes: string[], required: readonly string[]): boolean {
return required.every((scope) => userScopes.includes(scope));
}Step 2: Put user scopes in the router context// src/router.ts
import { createRouter } from '@tanstack/react-router';
import { routeTree } from './routeTree.gen';
export interface RouterContext {
auth: {
user: User | null;
scopes: string[];
isAuthenticated: boolean;
};
}
export const router = createRouter({
routeTree,
context: {
auth: { user: null, scopes: [], isAuthenticated: false }, // populated at app boot
},
});Step 3: Protect routes with
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi!
I was looking at docs about creating RBAC based routes, and I see that permission scopes are defined in multiple places rather than shared.
Example scenario -
<Admin />page that requireswrite:adminscope. The check happens in thebeforeLoadof the route.I have another route, not a child of
<Admin />, open to all users that shown a list of links. For admins I want to show the link to the admin panel based on whether they have thewrite:adminscope.I don't want to inline the scope in both checks as that may cause a drift in the future. What is the best way to share this scope information?
Beta Was this translation helpful? Give feedback.
All reactions