mirror of
https://codeberg.org/MarkusThielker/next-ory.git
synced 2025-04-19 09:01:18 +00:00
NORY-59: add permission checks to identity action UI
This commit is contained in:
parent
c935bbd8a2
commit
8d10b744e9
2 changed files with 71 additions and 14 deletions
|
@ -11,6 +11,9 @@ import { Badge } from '@/components/ui/badge';
|
||||||
import { Check, X } from 'lucide-react';
|
import { Check, X } from 'lucide-react';
|
||||||
import { IdentityActions } from '@/components/identity/identity-actions';
|
import { IdentityActions } from '@/components/identity/identity-actions';
|
||||||
import { IdentityCredentials } from '@/components/identity/identity-credentials';
|
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 {
|
interface MergedAddress {
|
||||||
recovery_id?: string;
|
recovery_id?: string;
|
||||||
|
@ -76,19 +79,35 @@ function mergeAddresses(
|
||||||
|
|
||||||
export default async function UserDetailsPage({ params }: { params: Promise<{ id: string }> }) {
|
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 identityApi = await getIdentityApi();
|
||||||
const identity = await identityApi.getIdentity({ id: identityId })
|
const identity = await identityApi.getIdentity({ id: detailIdentityId })
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
console.log('identity', response.data);
|
|
||||||
return response.data;
|
return response.data;
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
console.log('Identity not found');
|
console.log('Identity not found');
|
||||||
});
|
});
|
||||||
|
|
||||||
const sessions = await identityApi.listIdentitySessions({ id: identityId })
|
const sessions = await identityApi.listIdentitySessions({ id: detailIdentityId })
|
||||||
.then((response) => response.data)
|
.then((response) => response.data)
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
console.log('No sessions found');
|
console.log('No sessions found');
|
||||||
|
@ -97,7 +116,7 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
return <ErrorDisplay
|
return <ErrorDisplay
|
||||||
title="Identity not found"
|
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]) {
|
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>
|
<CardDescription>Quick actions to manage the identity</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<IdentityActions identity={identity}/>
|
<IdentityActions
|
||||||
|
identity={identity}
|
||||||
|
permissions={{
|
||||||
|
pmEditUser,
|
||||||
|
pmDeleteUser,
|
||||||
|
pmEditUserState,
|
||||||
|
pmDeleteUserSession,
|
||||||
|
pmCreateUserCode,
|
||||||
|
pmCreateUserLink,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Card>
|
<Card>
|
||||||
|
|
|
@ -28,12 +28,22 @@ import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
|
|
||||||
interface IdentityActionProps {
|
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 router = useRouter();
|
||||||
|
|
||||||
const [dialogVisible, setDialogVisible] = useState(false);
|
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?"
|
dialogDescription="Are you sure you want to create a recovery code for this identity?"
|
||||||
dialogButtonSubmit="Create code"
|
dialogButtonSubmit="Create code"
|
||||||
>
|
>
|
||||||
<Button className="mr-2" size="icon">
|
<Button
|
||||||
|
disabled={!permissions.pmCreateUserCode}
|
||||||
|
className="mr-2"
|
||||||
|
size="icon">
|
||||||
<Key className="h-4"/>
|
<Key className="h-4"/>
|
||||||
</Button>
|
</Button>
|
||||||
</ConfirmationDialogWrapper>
|
</ConfirmationDialogWrapper>
|
||||||
|
@ -142,7 +155,10 @@ export function IdentityActions({ identity }: IdentityActionProps,
|
||||||
dialogDescription="Are you sure you want to create a recovery link for this identity?"
|
dialogDescription="Are you sure you want to create a recovery link for this identity?"
|
||||||
dialogButtonSubmit="Create link"
|
dialogButtonSubmit="Create link"
|
||||||
>
|
>
|
||||||
<Button className="mr-2" size="icon">
|
<Button
|
||||||
|
disabled={!permissions.pmCreateUserLink}
|
||||||
|
className="mr-2"
|
||||||
|
size="icon">
|
||||||
<Link className="h-4"/>
|
<Link className="h-4"/>
|
||||||
</Button>
|
</Button>
|
||||||
</ConfirmationDialogWrapper>
|
</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!"
|
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"
|
dialogButtonSubmit="Deactivate"
|
||||||
>
|
>
|
||||||
<Button className="mr-2" size="icon">
|
<Button
|
||||||
|
disabled={!permissions.pmEditUserState}
|
||||||
|
className="mr-2"
|
||||||
|
size="icon">
|
||||||
<UserX className="h-4"/>
|
<UserX className="h-4"/>
|
||||||
</Button>
|
</Button>
|
||||||
</ConfirmationDialogWrapper>
|
</ConfirmationDialogWrapper>
|
||||||
|
@ -176,7 +195,10 @@ export function IdentityActions({ identity }: IdentityActionProps,
|
||||||
dialogDescription="Are you sure you want to activate this identity?"
|
dialogDescription="Are you sure you want to activate this identity?"
|
||||||
dialogButtonSubmit="Activate"
|
dialogButtonSubmit="Activate"
|
||||||
>
|
>
|
||||||
<Button className="mr-2" size="icon">
|
<Button
|
||||||
|
disabled={!permissions.pmEditUserState}
|
||||||
|
className="mr-2"
|
||||||
|
size="icon">
|
||||||
<UserCheck className="h-4"/>
|
<UserCheck className="h-4"/>
|
||||||
</Button>
|
</Button>
|
||||||
</ConfirmationDialogWrapper>
|
</ConfirmationDialogWrapper>
|
||||||
|
@ -194,7 +216,10 @@ export function IdentityActions({ identity }: IdentityActionProps,
|
||||||
dialogButtonSubmit="Invalidate sessions"
|
dialogButtonSubmit="Invalidate sessions"
|
||||||
dialogButtonSubmitProps={{ variant: 'destructive' }}
|
dialogButtonSubmitProps={{ variant: 'destructive' }}
|
||||||
>
|
>
|
||||||
<Button className="mr-2" size="icon">
|
<Button
|
||||||
|
disabled={!permissions.pmDeleteUserSession}
|
||||||
|
className="mr-2"
|
||||||
|
size="icon">
|
||||||
<UserMinus className="h-4"/>
|
<UserMinus className="h-4"/>
|
||||||
</Button>
|
</Button>
|
||||||
</ConfirmationDialogWrapper>
|
</ConfirmationDialogWrapper>
|
||||||
|
@ -214,7 +239,10 @@ export function IdentityActions({ identity }: IdentityActionProps,
|
||||||
dialogButtonSubmit="Delete identity"
|
dialogButtonSubmit="Delete identity"
|
||||||
dialogButtonSubmitProps={{ variant: 'destructive' }}
|
dialogButtonSubmitProps={{ variant: 'destructive' }}
|
||||||
>
|
>
|
||||||
<Button className="mr-2" size="icon">
|
<Button
|
||||||
|
disabled={!permissions.pmDeleteUser}
|
||||||
|
className="mr-2"
|
||||||
|
size="icon">
|
||||||
<Trash className="h-4"/>
|
<Trash className="h-4"/>
|
||||||
</Button>
|
</Button>
|
||||||
</ConfirmationDialogWrapper>
|
</ConfirmationDialogWrapper>
|
||||||
|
|
Loading…
Add table
Reference in a new issue