From 8d10b744e9cd11eefc9f0abaaf7d84f4aca60f10 Mon Sep 17 00:00:00 2001 From: Markus Thielker Date: Sun, 6 Apr 2025 11:14:22 +0200 Subject: [PATCH] NORY-59: add permission checks to identity action UI --- dashboard/src/app/(inside)/user/[id]/page.tsx | 41 ++++++++++++++--- .../components/identity/identity-actions.tsx | 44 +++++++++++++++---- 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/dashboard/src/app/(inside)/user/[id]/page.tsx b/dashboard/src/app/(inside)/user/[id]/page.tsx index 83cc3b3..98a578a 100644 --- a/dashboard/src/app/(inside)/user/[id]/page.tsx +++ b/dashboard/src/app/(inside)/user/[id]/page.tsx @@ -11,6 +11,9 @@ import { Badge } from '@/components/ui/badge'; import { Check, X } from 'lucide-react'; import { IdentityActions } from '@/components/identity/identity-actions'; import { IdentityCredentials } from '@/components/identity/identity-credentials'; +import { checkPermission, requirePermission, requireSession } from '@/lib/action/authentication'; +import { permission, relation } from '@/lib/permission'; +import { redirect } from 'next/navigation'; interface MergedAddress { recovery_id?: string; @@ -76,19 +79,35 @@ function mergeAddresses( export default async function UserDetailsPage({ params }: { params: Promise<{ id: string }> }) { - const identityId = (await params).id; + const session = await requireSession(); + const identityId = session.identity!.id; + + await requirePermission(permission.stack.dashboard, relation.access, identityId); + + const pmAccessUser = await checkPermission(permission.user.it, relation.access, identityId); + if (!pmAccessUser) { + return redirect('/user'); + } + + const pmEditUser = await checkPermission(permission.user.it, relation.edit, identityId); + const pmDeleteUser = await checkPermission(permission.user.it, relation.delete, identityId); + const pmEditUserState = await checkPermission(permission.user.state, relation.edit, identityId); + const pmDeleteUserSession = await checkPermission(permission.user.session, relation.delete, identityId); + const pmCreateUserCode = await checkPermission(permission.user.code, relation.create, identityId); + const pmCreateUserLink = await checkPermission(permission.user.link, relation.create, identityId); + + const detailIdentityId = (await params).id; const identityApi = await getIdentityApi(); - const identity = await identityApi.getIdentity({ id: identityId }) + const identity = await identityApi.getIdentity({ id: detailIdentityId }) .then((response) => { - console.log('identity', response.data); return response.data; }) .catch(() => { console.log('Identity not found'); }); - const sessions = await identityApi.listIdentitySessions({ id: identityId }) + const sessions = await identityApi.listIdentitySessions({ id: detailIdentityId }) .then((response) => response.data) .catch(() => { console.log('No sessions found'); @@ -97,7 +116,7 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id if (!identity) { return ; + message={`The requested identity with id ${detailIdentityId} does not exist`}/>; } if (!identity.verifiable_addresses || !identity.verifiable_addresses[0]) { @@ -137,7 +156,17 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id Quick actions to manage the identity - + diff --git a/dashboard/src/components/identity/identity-actions.tsx b/dashboard/src/components/identity/identity-actions.tsx index 0ddcf32..b6a48ca 100644 --- a/dashboard/src/components/identity/identity-actions.tsx +++ b/dashboard/src/components/identity/identity-actions.tsx @@ -28,12 +28,22 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; interface IdentityActionProps { - identity: Identity; + identity: Identity, + permissions: { + pmEditUser: boolean; + pmDeleteUser: boolean; + pmEditUserState: boolean; + pmDeleteUserSession: boolean; + pmCreateUserCode: boolean; + pmCreateUserLink: boolean; + } } -export function IdentityActions({ identity }: IdentityActionProps, +export function IdentityActions({ identity, permissions }: IdentityActionProps, ) { + console.log('IdentityActions', 'Permissions', permissions); + const router = useRouter(); const [dialogVisible, setDialogVisible] = useState(false); @@ -122,7 +132,10 @@ export function IdentityActions({ identity }: IdentityActionProps, dialogDescription="Are you sure you want to create a recovery code for this identity?" dialogButtonSubmit="Create code" > - @@ -142,7 +155,10 @@ export function IdentityActions({ identity }: IdentityActionProps, dialogDescription="Are you sure you want to create a recovery link for this identity?" dialogButtonSubmit="Create link" > - @@ -160,7 +176,10 @@ export function IdentityActions({ identity }: IdentityActionProps, dialogDescription="Are you sure you want to deactivate this identity? The user will not be able to sign-in or use any active session until re-activation!" dialogButtonSubmit="Deactivate" > - @@ -176,7 +195,10 @@ export function IdentityActions({ identity }: IdentityActionProps, dialogDescription="Are you sure you want to activate this identity?" dialogButtonSubmit="Activate" > - @@ -194,7 +216,10 @@ export function IdentityActions({ identity }: IdentityActionProps, dialogButtonSubmit="Invalidate sessions" dialogButtonSubmitProps={{ variant: 'destructive' }} > - @@ -214,7 +239,10 @@ export function IdentityActions({ identity }: IdentityActionProps, dialogButtonSubmit="Delete identity" dialogButtonSubmitProps={{ variant: 'destructive' }} > -