mirror of
https://github.com/mosh-hamedani/helpdesk.git
synced 2026-05-21 11:58:19 +02:00
Implement role-based access
This commit is contained in:
parent
6715c2073e
commit
e37142221f
|
|
@ -47,5 +47,6 @@ The client proxies `/api/*` requests to the server via Vite config.
|
|||
- **Client config**: `client/src/lib/auth-client.ts` — exports `signIn`, `signOut`, `useSession`
|
||||
- **Middleware**: `server/src/middleware/require-auth.ts` — `requireAuth` guard that sets `req.user` and `req.session`
|
||||
- **Route protection (client)**: `ProtectedRoute` component wraps authenticated routes; redirects to `/login` if unauthenticated
|
||||
- **Admin route protection (client)**: `AdminRoute` component wraps admin-only routes; redirects non-admins to `/`
|
||||
- **Sign-up is disabled** — users are seeded via `prisma/seed.ts`
|
||||
- **User roles**: `admin` and `agent` (defined as Prisma enum, default `agent`)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { Navigate, Route, Routes } from "react-router";
|
||||
import ProtectedRoute from "./components/ProtectedRoute";
|
||||
import AdminRoute from "./components/AdminRoute";
|
||||
import Layout from "./components/Layout";
|
||||
import LoginPage from "./pages/LoginPage";
|
||||
import HomePage from "./pages/HomePage";
|
||||
import UsersPage from "./pages/UsersPage";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
|
@ -11,6 +13,9 @@ function App() {
|
|||
<Route element={<ProtectedRoute />}>
|
||||
<Route element={<Layout />}>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
<Route element={<AdminRoute />}>
|
||||
<Route path="/users" element={<UsersPage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
|
|
|
|||
20
client/src/components/AdminRoute.tsx
Normal file
20
client/src/components/AdminRoute.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { Navigate, Outlet } from "react-router";
|
||||
import { useSession } from "../lib/auth-client";
|
||||
|
||||
export default function AdminRoute() {
|
||||
const { data: session, isPending } = useSession();
|
||||
|
||||
if (isPending) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-screen text-lg text-muted-foreground">
|
||||
Loading...
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (session?.user?.role !== "admin") {
|
||||
return <Navigate to="/" replace />;
|
||||
}
|
||||
|
||||
return <Outlet />;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Outlet, useNavigate } from "react-router";
|
||||
import { Link, Outlet, useNavigate } from "react-router";
|
||||
import { signOut, useSession } from "../lib/auth-client";
|
||||
|
||||
export default function Layout() {
|
||||
|
|
@ -13,7 +13,14 @@ export default function Layout() {
|
|||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<nav className="flex items-center justify-between bg-background border-b px-6 h-14">
|
||||
<div className="flex items-center gap-6">
|
||||
<span className="text-lg font-bold">Helpdesk</span>
|
||||
{session?.user?.role === "admin" && (
|
||||
<Link to="/users" className="text-sm text-muted-foreground hover:text-foreground transition-colors">
|
||||
Users
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm text-muted-foreground">{session?.user?.name}</span>
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
import { createAuthClient } from "better-auth/react";
|
||||
import { inferAdditionalFields } from "better-auth/client/plugins";
|
||||
import type { auth } from "../../../server/src/lib/auth";
|
||||
|
||||
export const { signIn, signOut, useSession } = createAuthClient();
|
||||
export const { signIn, signOut, useSession } = createAuthClient({
|
||||
plugins: [inferAdditionalFields<typeof auth>()],
|
||||
});
|
||||
|
|
|
|||
7
client/src/pages/UsersPage.tsx
Normal file
7
client/src/pages/UsersPage.tsx
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export default function UsersPage() {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold">Users</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue