From bf02015dc70c57b14d1ac2b02ae2d85ea0c8cde4 Mon Sep 17 00:00:00 2001 From: Aarnav Tale Date: Sat, 29 Mar 2025 14:12:15 -0400 Subject: [PATCH] feat: begin working on user auth --- app/components/Header.tsx | 49 +++---- app/layouts/shell.tsx | 21 ++- app/routes/users/components/user-row.tsx | 83 +++++++++++ app/routes/users/overview.tsx | 56 +++++++- app/server/README.md | 1 + app/server/config/schema.ts | 1 + app/server/index.ts | 15 +- app/server/web/roles.ts | 144 +++++++++++++++++++ app/server/web/sessions.ts | 140 ++++++++++++++++++- app/utils/log.ts | 2 +- config.example.yaml | 168 ++++++++++++----------- 11 files changed, 562 insertions(+), 118 deletions(-) create mode 100644 app/routes/users/components/user-row.tsx create mode 100644 app/server/web/roles.ts diff --git a/app/components/Header.tsx b/app/components/Header.tsx index c9b561a..1288e9a 100644 --- a/app/components/Header.tsx +++ b/app/components/Header.tsx @@ -15,6 +15,7 @@ import cn from '~/utils/cn'; interface Props { configAvailable: boolean; + uiAccess: boolean; user?: AuthSession['user']; } @@ -135,29 +136,31 @@ export default function Header(data: Props) { ) : undefined} - + {data.uiAccess ? ( + + ) : undefined} ); } diff --git a/app/layouts/shell.tsx b/app/layouts/shell.tsx index 996ea0e..52edaca 100644 --- a/app/layouts/shell.tsx +++ b/app/layouts/shell.tsx @@ -1,12 +1,15 @@ +import { BanIcon } from 'lucide-react'; import { LoaderFunctionArgs, Outlet, redirect, useLoaderData, } from 'react-router'; +import Card from '~/components/Card'; import Footer from '~/components/Footer'; import Header from '~/components/Header'; import type { LoadContext } from '~/server'; +import { Capabilities } from '~/server/web/roles'; // This loads the bare minimum for the application to function // So we know that if context fails to load then well, oops? @@ -25,12 +28,14 @@ export async function loader({ }); } + const check = await context.sessions.check(request, Capabilities.ui_access); return { config: context.hs.c, url: context.config.headscale.public_url ?? context.config.headscale.url, configAvailable: context.hs.readable(), debug: context.config.debug, user: session.get('user'), + uiAccess: check, }; } catch { // No session, so we can just return @@ -40,10 +45,24 @@ export async function loader({ export default function Shell() { const data = useLoaderData(); + return ( <>
- + {data.uiAccess ? ( + + ) : ( + +
+ Access Denied + +
+ + Your account does not have access to the UI. Please contact your + administrator. + +
+ )}