import React from 'react'; import { getIdentityApi } from '@/ory/sdk/server'; import { ErrorDisplay } from '@/components/error'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { IdentityTraitForm } from '@/components/forms/IdentityTraitForm'; import { KratosSchema } from '@/lib/forms/identity-form'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { UAParser } from 'ua-parser-js'; import { RecoveryIdentityAddress, VerifiableIdentityAddress } from '@ory/client'; import { Badge } from '@/components/ui/badge'; import { Check, X } from 'lucide-react'; interface MergedAddress { recovery_id?: string; verifiable_id?: string; verified?: boolean; verified_at?: string; value: string; via: string; } function mergeAddresses( recovery: RecoveryIdentityAddress[], verifiable: VerifiableIdentityAddress[], ): MergedAddress[] { const merged = [...recovery, ...verifiable]; return merged.reduce((acc: MergedAddress[], curr: any) => { const existingValue = acc.find(item => item.value && curr.value && item.value === curr.value); if (!existingValue) { let newEntry: MergedAddress; if (curr.status) { // status property exists only in verifiable addresses // expecting verifiable address newEntry = { verifiable_id: curr.id, verified: curr.verified, verified_at: curr.verified_at, value: curr.value, via: curr.via, } as MergedAddress; } else { // expecting recovery address newEntry = { recovery_id: curr.id, value: curr.value, via: curr.via, } as MergedAddress; } acc.push(newEntry); } else { const additionalValues = { recovery_id: existingValue.recovery_id, verifiable_id: curr.id, verified: curr.verified, verified_at: curr.verified_at, }; Object.assign(existingValue, additionalValues); } return acc; }, []); } export default async function UserDetailsPage({ params }: { params: Promise<{ id: string }> }) { const identityId = (await params).id; const identityApi = await getIdentityApi(); const identity = await identityApi.getIdentity({ id: identityId }) .then((response) => { console.log('identity', response.data); return response.data; }) .catch(() => { console.log('Identity not found'); }); const sessions = await identityApi.listIdentitySessions({ id: identityId }) .then((response) => { console.log('sessions', response.data); return response.data; }) .catch(() => { console.log('No sessions found'); }); if (!identity) { return ; } if (!identity.verifiable_addresses || !identity.verifiable_addresses[0]) { return ; } const identitySchema = await identityApi .getIdentitySchema({ id: identity.schema_id }) .then((response) => response.data as KratosSchema); const addresses = mergeAddresses( identity.recovery_addresses ?? [], identity.verifiable_addresses ?? [], ); return (

{addresses[0].value}

{identity.id}

Traits All identity properties specified in the identity schema Addresses All linked addresses for verification and recovery Type Value { addresses.map((address) => { return ( {address.value} {address.via} {address.verifiable_id && Verifiable { address.verified ? : } } {address.recovery_id && Recovery } ); }) }
Credentials All authentication mechanisms registered with this identity Type Value { Object.entries(identity.credentials!).map(([key, value]) => { return ( {key} {value.identifiers![0]} ); }) }
Sessions See and manage all sessions of this identity OS Browser Active since { sessions ? sessions.map((session) => { const device = session.devices![0]; const parser = new UAParser(device.user_agent); const result = parser.getResult(); return ( {result.os.name} {result.os.version} {result.browser.name} {result.browser.version} {new Date(session.authenticated_at!).toLocaleString()} ); }) : }
); }