From 3e94384cdeb7609171be9e313450baca2683eea7 Mon Sep 17 00:00:00 2001 From: miloschwartz Date: Thu, 17 Apr 2025 21:21:41 -0400 Subject: [PATCH] add info box to admin users table --- src/app/admin/idp/create/page.tsx | 502 +++++++++++++++--------------- src/app/admin/users/page.tsx | 9 + src/components/Layout.tsx | 4 +- src/components/Settings.tsx | 66 +++- 4 files changed, 310 insertions(+), 271 deletions(-) diff --git a/src/app/admin/idp/create/page.tsx b/src/app/admin/idp/create/page.tsx index 15b6da75..74567dc6 100644 --- a/src/app/admin/idp/create/page.tsx +++ b/src/app/admin/idp/create/page.tsx @@ -6,6 +6,7 @@ import { SettingsSectionBody, SettingsSectionDescription, SettingsSectionForm, + SettingsSectionGrid, SettingsSectionHeader, SettingsSectionTitle } from "@app/components/Settings"; @@ -229,269 +230,258 @@ export default function Page() { {form.watch("type") === "oidc" && ( - <> -
- - - - OAuth2/OIDC Configuration - - - Configure the OAuth2/OIDC provider - endpoints and credentials - - - -
- + + + + OAuth2/OIDC Configuration + + + Configure the OAuth2/OIDC provider endpoints + and credentials + + + + + + ( + + + Client ID + + + + + + The OAuth2 client ID + from your identity + provider + + + )} - > - ( - - - Client ID - - - - - - The OAuth2 client ID - from your identity - provider - - - - )} - /> + /> - ( - - - Client Secret - - - - - - The OAuth2 client - secret from your - identity provider - - - - )} - /> - - ( - - - Authorization URL - - - - - - The OAuth2 - authorization - endpoint URL - - - - )} - /> - - ( - - - Token URL - - - - - - The OAuth2 token - endpoint URL - - - - )} - /> - - - - - - - Important Information - - - After creating the identity - provider, you will need to configure - the callback URL in your identity - provider's settings. The callback - URL will be provided after - successful creation. - - - -
- - - - - Token Configuration - - - Configure how to extract user - information from the ID token - - - -
- ( + + + Client Secret + + + + + + The OAuth2 client secret + from your identity + provider + + + )} - > - - - - About JMESPath - - - The paths below use JMESPath - syntax to extract values - from the ID token. - - Learn more about - JMESPath{" "} - - - - + /> - ( - - - Identifier Path - - - - - - The JMESPath to the - user identifier in - the ID token - - - - )} - /> + ( + + + Authorization URL + + + + + + The OAuth2 authorization + endpoint URL + + + + )} + /> - ( - - - Email Path - (Optional) - - - - - - The JMESPath to the - user's email in the - ID token - - - - )} - /> + ( + + + Token URL + + + + + + The OAuth2 token + endpoint URL + + + + )} + /> + + - ( - - - Name Path (Optional) - - - - - - The JMESPath to the - user's name in the - ID token - - - - )} - /> + + + + Important Information + + + After creating the identity provider, + you will need to configure the callback + URL in your identity provider's + settings. The callback URL will be + provided after successful creation. + + +
+
- ( - - - Scopes - - - - - - Space-separated list - of OAuth2 scopes to - request - - - - )} - /> - - -
-
-
- + + + + Token Configuration + + + Configure how to extract user information + from the ID token + + + +
+ + + + + About JMESPath + + + The paths below use JMESPath + syntax to extract values from + the ID token. + + Learn more about JMESPath{" "} + + + + + + ( + + + Identifier Path + + + + + + The JMESPath to the user + identifier in the ID + token + + + + )} + /> + + ( + + + Email Path (Optional) + + + + + + The JMESPath to the + user's email in the ID + token + + + + )} + /> + + ( + + + Name Path (Optional) + + + + + + The JMESPath to the + user's name in the ID + token + + + + )} + /> + + ( + + + Scopes + + + + + + Space-separated list of + OAuth2 scopes to request + + + + )} + /> + + +
+
+ )} diff --git a/src/app/admin/users/page.tsx b/src/app/admin/users/page.tsx index 877d1494..6e2290cb 100644 --- a/src/app/admin/users/page.tsx +++ b/src/app/admin/users/page.tsx @@ -4,6 +4,8 @@ import { AxiosResponse } from "axios"; import SettingsSectionTitle from "@app/components/SettingsSectionTitle"; import { AdminListUsersResponse } from "@server/routers/user/adminListUsers"; import UsersTable, { GlobalUserRow } from "./AdminUsersTable"; +import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert"; +import { InfoIcon } from "lucide-react"; type PageProps = { params: Promise<{ orgId: string }>; @@ -43,6 +45,13 @@ export default async function UsersPage(props: PageProps) { title="Manage All Users" description="View and manage all users in the system" /> + + + About User Management + + This table displays all root user objects in the system. Each user may belong to multiple organizations. Removing a user from an organization does not delete their root user object - they will remain in the system. To completely remove a user from the system, you must delete their root user object using the delete action in this table. + + ); diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index ae95d4c6..870d9b64 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -22,6 +22,7 @@ import { useEnvContext } from "@app/hooks/useEnvContext"; import { Breadcrumbs } from "@app/components/Breadcrumbs"; import Link from "next/link"; import { usePathname } from "next/navigation"; +import { useUserContext } from "@app/hooks/useUserContext"; interface LayoutProps { children: React.ReactNode; @@ -57,6 +58,7 @@ export function Layout({ const { env } = useEnvContext(); const pathname = usePathname(); const isAdminPage = pathname?.startsWith("/admin"); + const { user } = useUserContext(); return (
@@ -135,7 +137,7 @@ export function Layout({
- {!isAdminPage && ( + {!isAdminPage && user.serverAdmin && (
{children}
+ return
{children}
; } export function SettingsSection({ children }: { children: React.ReactNode }) { - return
{children}
+ return
{children}
; } -export function SettingsSectionHeader({ children }: { children: React.ReactNode }) { - return
{children}
+export function SettingsSectionHeader({ + children +}: { + children: React.ReactNode; +}) { + return
{children}
; } -export function SettingsSectionForm({ children }: { children: React.ReactNode }) { - return
{children}
+export function SettingsSectionForm({ + children +}: { + children: React.ReactNode; +}) { + return
{children}
; } -export function SettingsSectionTitle({ children }: { children: React.ReactNode }) { - return

{children}

+export function SettingsSectionTitle({ + children +}: { + children: React.ReactNode; +}) { + return ( +

+ {children} +

+ ); } -export function SettingsSectionDescription({ children }: { children: React.ReactNode }) { - return

{children}

+export function SettingsSectionDescription({ + children +}: { + children: React.ReactNode; +}) { + return

{children}

; } -export function SettingsSectionBody({ children }: { children: React.ReactNode }) { - return
{children}
+export function SettingsSectionBody({ + children +}: { + children: React.ReactNode; +}) { + return
{children}
; } -export function SettingsSectionFooter({ children }: { children: React.ReactNode }) { - return
{children}
+export function SettingsSectionFooter({ + children +}: { + children: React.ReactNode; +}) { + return
{children}
; +} + +export function SettingsSectionGrid({ + children, + cols +}: { + children: React.ReactNode; + cols: number; +}) { + return
{children}
; }