mirror of
https://codeberg.org/MarkusThielker/next-ory.git
synced 2025-04-16 13:49:28 +00:00
NORY-59: refactor identity queries to use server actions
This commit is contained in:
parent
b72a45f39d
commit
b3be0440d1
3 changed files with 123 additions and 73 deletions
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { getIdentityApi } from '@/ory/sdk/server';
|
|
||||||
import { ErrorDisplay } from '@/components/error';
|
import { ErrorDisplay } from '@/components/error';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { IdentityTraits } from '@/components/identity/identity-traits';
|
import { IdentityTraits } from '@/components/identity/identity-traits';
|
||||||
|
@ -14,6 +13,8 @@ import { IdentityCredentials } from '@/components/identity/identity-credentials'
|
||||||
import { checkPermission, requirePermission, requireSession } from '@/lib/action/authentication';
|
import { checkPermission, requirePermission, requireSession } from '@/lib/action/authentication';
|
||||||
import { permission, relation } from '@/lib/permission';
|
import { permission, relation } from '@/lib/permission';
|
||||||
import { redirect } from 'next/navigation';
|
import { redirect } from 'next/navigation';
|
||||||
|
import InsufficientPermission from '@/components/insufficient-permission';
|
||||||
|
import { getIdentity, getIdentitySchema, listIdentitySessions } from '@/lib/action/identity';
|
||||||
|
|
||||||
interface MergedAddress {
|
interface MergedAddress {
|
||||||
recovery_id?: string;
|
recovery_id?: string;
|
||||||
|
@ -91,65 +92,65 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id
|
||||||
|
|
||||||
const pmEditUser = await checkPermission(permission.user.it, relation.edit, identityId);
|
const pmEditUser = await checkPermission(permission.user.it, relation.edit, identityId);
|
||||||
const pmDeleteUser = await checkPermission(permission.user.it, relation.delete, identityId);
|
const pmDeleteUser = await checkPermission(permission.user.it, relation.delete, identityId);
|
||||||
|
const pmAccessUserTraits = await checkPermission(permission.user.trait, relation.access, identityId);
|
||||||
const pmEditUserState = await checkPermission(permission.user.state, relation.edit, identityId);
|
const pmEditUserState = await checkPermission(permission.user.state, relation.edit, identityId);
|
||||||
|
const pmAccessUserSession = await checkPermission(permission.user.session, relation.access, identityId);
|
||||||
const pmDeleteUserSession = await checkPermission(permission.user.session, relation.delete, identityId);
|
const pmDeleteUserSession = await checkPermission(permission.user.session, relation.delete, identityId);
|
||||||
const pmCreateUserCode = await checkPermission(permission.user.code, relation.create, identityId);
|
const pmCreateUserCode = await checkPermission(permission.user.code, relation.create, identityId);
|
||||||
const pmCreateUserLink = await checkPermission(permission.user.link, relation.create, identityId);
|
const pmCreateUserLink = await checkPermission(permission.user.link, relation.create, identityId);
|
||||||
|
|
||||||
const detailIdentityId = (await params).id;
|
const detailIdentityId = (await params).id;
|
||||||
|
const detailIdentity = pmAccessUser && await getIdentity(detailIdentityId);
|
||||||
|
|
||||||
const identityApi = await getIdentityApi();
|
if (!detailIdentity) {
|
||||||
const identity = await identityApi.getIdentity({ id: detailIdentityId })
|
|
||||||
.then((response) => {
|
|
||||||
return response.data;
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
console.log('Identity not found');
|
|
||||||
});
|
|
||||||
|
|
||||||
const sessions = await identityApi.listIdentitySessions({ id: detailIdentityId })
|
|
||||||
.then((response) => response.data)
|
|
||||||
.catch(() => {
|
|
||||||
console.log('No sessions found');
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!identity) {
|
|
||||||
return <ErrorDisplay
|
return <ErrorDisplay
|
||||||
title="Identity not found"
|
title="Identity not found"
|
||||||
message={`The requested identity with id ${detailIdentityId} does not exist`}/>;
|
message={`The requested identity with id ${detailIdentityId} does not exist`}/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!identity.verifiable_addresses || !identity.verifiable_addresses[0]) {
|
if (!detailIdentity.verifiable_addresses || !detailIdentity.verifiable_addresses[0]) {
|
||||||
return <ErrorDisplay
|
return <ErrorDisplay
|
||||||
title="No verifiable adress"
|
title="No verifiable adress"
|
||||||
message="The identity you are trying to see exists but has no identifiable address"/>;
|
message="The identity you are trying to see exists but has no identifiable address"/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const identitySchema = await identityApi
|
|
||||||
.getIdentitySchema({ id: identity.schema_id })
|
const detailIdentitySessions = pmAccessUserSession && await listIdentitySessions(detailIdentityId);
|
||||||
.then((response) => response.data as KratosSchema);
|
|
||||||
|
const detailIdentitySchema = await getIdentitySchema(detailIdentity.schema_id)
|
||||||
|
.then((response) => response as KratosSchema);
|
||||||
|
|
||||||
const addresses = mergeAddresses(
|
const addresses = mergeAddresses(
|
||||||
identity.recovery_addresses ?? [],
|
detailIdentity.recovery_addresses ?? [],
|
||||||
identity.verifiable_addresses ?? [],
|
detailIdentity.verifiable_addresses ?? [],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-3xl font-bold leading-tight tracking-tight">{addresses[0].value}</p>
|
<p className="text-3xl font-bold leading-tight tracking-tight">{addresses[0].value}</p>
|
||||||
<p className="text-lg font-light">{identity.id}</p>
|
<p className="text-lg font-light">{detailIdentity.id}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 xl:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 xl:grid-cols-2 gap-4">
|
||||||
|
{
|
||||||
|
pmAccessUserTraits ?
|
||||||
<Card className="row-span-3">
|
<Card className="row-span-3">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Traits</CardTitle>
|
<CardTitle>Traits</CardTitle>
|
||||||
<CardDescription>All identity properties specified in the identity schema</CardDescription>
|
<CardDescription>All identity properties specified in the identity
|
||||||
|
schema</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<IdentityTraits schema={identitySchema} identity={identity}/>
|
<IdentityTraits schema={detailIdentitySchema} identity={detailIdentity}/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
:
|
||||||
|
<InsufficientPermission
|
||||||
|
permission={permission.user.trait}
|
||||||
|
relation={relation.access}
|
||||||
|
identityId={identityId}
|
||||||
|
classNames="row-span-3"/>
|
||||||
|
}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Actions</CardTitle>
|
<CardTitle>Actions</CardTitle>
|
||||||
|
@ -157,7 +158,7 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<IdentityActions
|
<IdentityActions
|
||||||
identity={identity}
|
identity={detailIdentity}
|
||||||
permissions={{
|
permissions={{
|
||||||
pmEditUser,
|
pmEditUser,
|
||||||
pmDeleteUser,
|
pmDeleteUser,
|
||||||
|
@ -220,7 +221,7 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id
|
||||||
<CardDescription>All authentication mechanisms registered with this identity</CardDescription>
|
<CardDescription>All authentication mechanisms registered with this identity</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
<IdentityCredentials identity={identity}/>
|
<IdentityCredentials identity={detailIdentity}/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Card>
|
<Card>
|
||||||
|
@ -229,6 +230,8 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id
|
||||||
<CardDescription>See and manage all sessions of this identity</CardDescription>
|
<CardDescription>See and manage all sessions of this identity</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
{
|
||||||
|
detailIdentitySessions ?
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
@ -239,8 +242,7 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{
|
{
|
||||||
sessions ?
|
detailIdentitySessions.map((session) => {
|
||||||
sessions.map((session) => {
|
|
||||||
|
|
||||||
const device = session.devices![0];
|
const device = session.devices![0];
|
||||||
const parser = new UAParser(device.user_agent);
|
const parser = new UAParser(device.user_agent);
|
||||||
|
@ -264,11 +266,12 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
:
|
|
||||||
<ErrorDisplay title="No sessions" message=""/>
|
|
||||||
}
|
}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
:
|
||||||
|
<p>This user has no active sessions</p>
|
||||||
|
}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,6 +15,34 @@ import { eq, ilike, or, sql } from 'drizzle-orm';
|
||||||
import { checkPermission, requireSession } from '@/lib/action/authentication';
|
import { checkPermission, requireSession } from '@/lib/action/authentication';
|
||||||
import { permission, relation } from '@/lib/permission';
|
import { permission, relation } from '@/lib/permission';
|
||||||
|
|
||||||
|
export async function getIdentity(id: string) {
|
||||||
|
|
||||||
|
const session = await requireSession();
|
||||||
|
const allowed = await checkPermission(permission.user.it, relation.access, session.identity!.id);
|
||||||
|
if (!allowed) {
|
||||||
|
throw Error('Unauthorised');
|
||||||
|
}
|
||||||
|
|
||||||
|
const identityApi = await getIdentityApi();
|
||||||
|
const { data } = await identityApi.getIdentity({ id });
|
||||||
|
|
||||||
|
console.log('Got identity', data);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function getIdentitySchema(id: string) {
|
||||||
|
|
||||||
|
const identityApi = await getIdentityApi();
|
||||||
|
const { data } = await identityApi.getIdentitySchema({ id: id });
|
||||||
|
|
||||||
|
console.log('Got identity schema');
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
interface QueryIdentitiesProps {
|
interface QueryIdentitiesProps {
|
||||||
page: number,
|
page: number,
|
||||||
pageSize: number,
|
pageSize: number,
|
||||||
|
@ -131,6 +159,24 @@ export async function deleteIdentityCredential({ id, type }: DeleteIdentityCrede
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function listIdentitySessions(id: string) {
|
||||||
|
|
||||||
|
const session = await requireSession();
|
||||||
|
const allowed = await checkPermission(permission.user.session, relation.access, session.identity!.id);
|
||||||
|
if (!allowed) {
|
||||||
|
throw Error('Unauthorised');
|
||||||
|
}
|
||||||
|
|
||||||
|
const identityApi = await getIdentityApi();
|
||||||
|
const { data } = await identityApi.listIdentitySessions({ id });
|
||||||
|
|
||||||
|
console.log('Listed identity\'s sessions', data);
|
||||||
|
|
||||||
|
revalidatePath('/user');
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
export async function deleteIdentitySessions(id: string) {
|
export async function deleteIdentitySessions(id: string) {
|
||||||
|
|
||||||
const session = await requireSession();
|
const session = await requireSession();
|
||||||
|
|
|
@ -10,6 +10,7 @@ export const permission = {
|
||||||
link: 'admin.user.link',
|
link: 'admin.user.link',
|
||||||
session: 'admin.user.session',
|
session: 'admin.user.session',
|
||||||
state: 'admin.user.state',
|
state: 'admin.user.state',
|
||||||
|
trait: 'admin.user.trait',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue