diff --git a/dashboard/src/app/(inside)/user/[id]/page.tsx b/dashboard/src/app/(inside)/user/[id]/page.tsx
index 98a578a..e590abc 100644
--- a/dashboard/src/app/(inside)/user/[id]/page.tsx
+++ b/dashboard/src/app/(inside)/user/[id]/page.tsx
@@ -1,5 +1,4 @@
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 { 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 { permission, relation } from '@/lib/permission';
import { redirect } from 'next/navigation';
+import InsufficientPermission from '@/components/insufficient-permission';
+import { getIdentity, getIdentitySchema, listIdentitySessions } from '@/lib/action/identity';
interface MergedAddress {
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 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 pmAccessUserSession = await checkPermission(permission.user.session, relation.access, 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 detailIdentity = pmAccessUser && await getIdentity(detailIdentityId);
- const identityApi = await getIdentityApi();
- 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) {
+ if (!detailIdentity) {
return ;
}
- if (!identity.verifiable_addresses || !identity.verifiable_addresses[0]) {
+ if (!detailIdentity.verifiable_addresses || !detailIdentity.verifiable_addresses[0]) {
return ;
}
- const identitySchema = await identityApi
- .getIdentitySchema({ id: identity.schema_id })
- .then((response) => response.data as KratosSchema);
+
+ const detailIdentitySessions = pmAccessUserSession && await listIdentitySessions(detailIdentityId);
+
+ const detailIdentitySchema = await getIdentitySchema(detailIdentity.schema_id)
+ .then((response) => response as KratosSchema);
const addresses = mergeAddresses(
- identity.recovery_addresses ?? [],
- identity.verifiable_addresses ?? [],
+ detailIdentity.recovery_addresses ?? [],
+ detailIdentity.verifiable_addresses ?? [],
);
return (
{addresses[0].value}
-
{identity.id}
+
{detailIdentity.id}
-
-
- Traits
- All identity properties specified in the identity schema
-
-
-
-
-
+ {
+ pmAccessUserTraits ?
+
+
+ Traits
+ All identity properties specified in the identity
+ schema
+
+
+
+
+
+ :
+
+ }
Actions
@@ -157,7 +158,7 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id
All authentication mechanisms registered with this identity
-
+
@@ -229,46 +230,48 @@ export default async function UserDetailsPage({ params }: { params: Promise<{ id
See and manage all sessions of this identity
-
-
-
- OS
- Browser
- Active since
-
-
-
- {
- sessions ?
- sessions.map((session) => {
+ {
+ detailIdentitySessions ?
+
+
+
+ OS
+ Browser
+ Active since
+
+
+
+ {
+ detailIdentitySessions.map((session) => {
- const device = session.devices![0];
- const parser = new UAParser(device.user_agent);
- const result = parser.getResult();
+ 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()}
-
-
- );
- })
- :
-
- }
-
-
+ return (
+
+
+ {result.os.name}
+ {result.os.version}
+
+
+ {result.browser.name}
+ {result.browser.version}
+
+
+ {new Date(session.authenticated_at!).toLocaleString()}
+
+
+ );
+ })
+ }
+
+
+ :
+ This user has no active sessions
+ }
diff --git a/dashboard/src/lib/action/identity.ts b/dashboard/src/lib/action/identity.ts
index b39e721..11ef3d9 100644
--- a/dashboard/src/lib/action/identity.ts
+++ b/dashboard/src/lib/action/identity.ts
@@ -15,6 +15,34 @@ import { eq, ilike, or, sql } from 'drizzle-orm';
import { checkPermission, requireSession } from '@/lib/action/authentication';
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 {
page: number,
pageSize: number,
@@ -131,6 +159,24 @@ export async function deleteIdentityCredential({ id, type }: DeleteIdentityCrede
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) {
const session = await requireSession();
diff --git a/dashboard/src/lib/permission.ts b/dashboard/src/lib/permission.ts
index 49958b0..69a8523 100644
--- a/dashboard/src/lib/permission.ts
+++ b/dashboard/src/lib/permission.ts
@@ -10,6 +10,7 @@ export const permission = {
link: 'admin.user.link',
session: 'admin.user.session',
state: 'admin.user.state',
+ trait: 'admin.user.trait',
},
};