1
0
Fork 0
mirror of https://codeberg.org/MarkusThielker/next-ory.git synced 2025-04-13 13:08:41 +00:00

NORY-59: add permission checks to identity action UI

This commit is contained in:
Markus Thielker 2025-04-06 11:14:22 +02:00
parent 0da4158d60
commit b72a45f39d
2 changed files with 71 additions and 14 deletions

View file

@ -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 <ErrorDisplay
title="Identity not found"
message={`The requested identity with id ${identityId} does not exist`}/>;
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
<CardDescription>Quick actions to manage the identity</CardDescription>
</CardHeader>
<CardContent>
<IdentityActions identity={identity}/>
<IdentityActions
identity={identity}
permissions={{
pmEditUser,
pmDeleteUser,
pmEditUserState,
pmDeleteUserSession,
pmCreateUserCode,
pmCreateUserLink,
}}
/>
</CardContent>
</Card>
<Card>

View file

@ -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"
>
<Button className="mr-2" size="icon">
<Button
disabled={!permissions.pmCreateUserCode}
className="mr-2"
size="icon">
<Key className="h-4"/>
</Button>
</ConfirmationDialogWrapper>
@ -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"
>
<Button className="mr-2" size="icon">
<Button
disabled={!permissions.pmCreateUserLink}
className="mr-2"
size="icon">
<Link className="h-4"/>
</Button>
</ConfirmationDialogWrapper>
@ -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"
>
<Button className="mr-2" size="icon">
<Button
disabled={!permissions.pmEditUserState}
className="mr-2"
size="icon">
<UserX className="h-4"/>
</Button>
</ConfirmationDialogWrapper>
@ -176,7 +195,10 @@ export function IdentityActions({ identity }: IdentityActionProps,
dialogDescription="Are you sure you want to activate this identity?"
dialogButtonSubmit="Activate"
>
<Button className="mr-2" size="icon">
<Button
disabled={!permissions.pmEditUserState}
className="mr-2"
size="icon">
<UserCheck className="h-4"/>
</Button>
</ConfirmationDialogWrapper>
@ -194,7 +216,10 @@ export function IdentityActions({ identity }: IdentityActionProps,
dialogButtonSubmit="Invalidate sessions"
dialogButtonSubmitProps={{ variant: 'destructive' }}
>
<Button className="mr-2" size="icon">
<Button
disabled={!permissions.pmDeleteUserSession}
className="mr-2"
size="icon">
<UserMinus className="h-4"/>
</Button>
</ConfirmationDialogWrapper>
@ -214,7 +239,10 @@ export function IdentityActions({ identity }: IdentityActionProps,
dialogButtonSubmit="Delete identity"
dialogButtonSubmitProps={{ variant: 'destructive' }}
>
<Button className="mr-2" size="icon">
<Button
disabled={!permissions.pmDeleteUser}
className="mr-2"
size="icon">
<Trash className="h-4"/>
</Button>
</ConfirmationDialogWrapper>