From 68617180a2112a462c061b2f9ad3eeab87bcd9ff Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Thu, 18 Apr 2024 11:16:28 +0200 Subject: [PATCH] Show indicator for transient user in user sessions list in admin ui (28879) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For transient users a transient label is now shown in the realm sessions and client sessions list in the admin ui. Fixes #28879 Co-authored-by: Thomas Darimont Co-authored-by: Hynek Mlnařík Signed-off-by: Thomas Darimont --- .../idm/UserSessionRepresentation.java | 9 +++++++++ .../admin-ui/src/sessions/SessionsTable.tsx | 19 ++++++++++++++++++- .../src/defs/userSessionRepresentation.ts | 1 + .../admin/ui/rest/SessionsResource.java | 2 ++ .../ui/rest/model/SessionRepresentation.java | 9 +++++++++ .../models/utils/ModelToRepresentation.java | 1 + 6 files changed, 40 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java index 2e9294fa52..8bada55779 100755 --- a/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java @@ -33,6 +33,7 @@ public class UserSessionRepresentation { private long lastAccess; private boolean rememberMe; private Map clients = new HashMap<>(); + private boolean transientUser; public String getId() { return id; @@ -97,4 +98,12 @@ public class UserSessionRepresentation { public void setClients(Map clients) { this.clients = clients; } + + public boolean isTransientUser() { + return transientUser; + } + + public void setTransientUser(boolean transientUser) { + this.transientUser = transientUser; + } } diff --git a/js/apps/admin-ui/src/sessions/SessionsTable.tsx b/js/apps/admin-ui/src/sessions/SessionsTable.tsx index b5328ba4b0..602b717ff7 100644 --- a/js/apps/admin-ui/src/sessions/SessionsTable.tsx +++ b/js/apps/admin-ui/src/sessions/SessionsTable.tsx @@ -1,12 +1,14 @@ import type UserSessionRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userSessionRepresentation"; import { Button, + Label, List, ListItem, ListVariant, ToolbarItem, + Tooltip, } from "@patternfly/react-core"; -import { CubesIcon } from "@patternfly/react-icons"; +import { CubesIcon, InfoCircleIcon } from "@patternfly/react-icons"; import { MouseEvent, ReactNode, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Link, useMatch, useNavigate } from "react-router-dom"; @@ -50,9 +52,24 @@ export type SessionsTableProps = { const UsernameCell = (row: UserSessionRepresentation) => { const { realm } = useRealm(); + const { t } = useTranslation(); return ( {row.username} + {row.transientUser && ( + <> + {" "} + + + + + )} ); }; diff --git a/js/libs/keycloak-admin-client/src/defs/userSessionRepresentation.ts b/js/libs/keycloak-admin-client/src/defs/userSessionRepresentation.ts index 7611fa29ae..d5670e3498 100644 --- a/js/libs/keycloak-admin-client/src/defs/userSessionRepresentation.ts +++ b/js/libs/keycloak-admin-client/src/defs/userSessionRepresentation.ts @@ -6,4 +6,5 @@ export default interface UserSessionRepresentation { start?: number; userId?: string; username?: string; + transientUser?: boolean; } diff --git a/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/SessionsResource.java b/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/SessionsResource.java index 0ea990731e..cf728806f2 100644 --- a/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/SessionsResource.java +++ b/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/SessionsResource.java @@ -14,6 +14,7 @@ import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserSessionModel; +import org.keycloak.models.light.LightweightUserAdapter; import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import jakarta.ws.rs.Consumes; @@ -118,6 +119,7 @@ public class SessionsResource { ClientModel client = clientSession.getClient(); rep.getClients().put(client.getId(), client.getClientId()); } + rep.setTransientUser(LightweightUserAdapter.isLightweightUser(session.getUser().getId())); return rep; } } diff --git a/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/model/SessionRepresentation.java b/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/model/SessionRepresentation.java index c16f05800a..5833f6ae19 100644 --- a/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/model/SessionRepresentation.java +++ b/rest/admin-ui-ext/src/main/java/org/keycloak/admin/ui/rest/model/SessionRepresentation.java @@ -13,6 +13,7 @@ public class SessionRepresentation { private String ipAddress; private long start; private long lastAccess; + private boolean transientUser; private SessionType type; private Map clients = new HashMap<>(); @@ -81,6 +82,14 @@ public class SessionRepresentation { this.clients = clients; } + public boolean isTransientUser() { + return transientUser; + } + + public void setTransientUser(boolean transientUser) { + this.transientUser = transientUser; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 240cf46f74..861fd90dd2 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -679,6 +679,7 @@ public class ModelToRepresentation { ClientModel client = clientSession.getClient(); rep.getClients().put(client.getId(), client.getClientId()); } + rep.setTransientUser(LightweightUserAdapter.isLightweightUser(session.getUser().getId())); return rep; }