Skip to content

Commit

Permalink
Add Events tab to relevant objects in the UI
Browse files Browse the repository at this point in the history
Fixes #29113

Signed-off-by: Oliver Cremerius <antikalk@users.noreply.github.com>
  • Loading branch information
antikalk committed Nov 15, 2024
1 parent 84f60bc commit 038c304
Show file tree
Hide file tree
Showing 15 changed files with 241 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3302,4 +3302,6 @@ managedMembership=Managed membership
filterByMembershipType=Filter by Membership Type
organizationsMembersListError=Could not fetch organization members\: {{error}}
MANAGED=Managed
UNMANAGED=Unmanaged
UNMANAGED=Unmanaged
membershipEvents=Membership events
childGroupEvents=Child group events
16 changes: 15 additions & 1 deletion js/apps/admin-ui/src/client-scopes/EditClientScope.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,23 @@ import {
} from "./routes/ClientScope";
import { toClientScopes } from "./routes/ClientScopes";
import { toMapper } from "./routes/Mapper";
import { useAccess } from "../context/access/Access";
import { AdminEvents } from "../events/AdminEvents";

export default function EditClientScope() {
const { adminClient } = useAdminClient();

const { t } = useTranslation();
const navigate = useNavigate();
const { realm } = useRealm();
const { realm, realmRepresentation } = useRealm();
const { id } = useParams<ClientScopeParams>();
const { addAlert, addError } = useAlerts();
const { enabled } = useHelp();
const [clientScope, setClientScope] =
useState<ClientScopeDefaultOptionalType>();
const [key, setKey] = useState(0);
const refresh = () => setKey(key + 1);
const { hasAccess } = useAccess();

useFetch(
async () => {
Expand Down Expand Up @@ -108,6 +111,7 @@ export default function EditClientScope() {
const settingsTab = useTab("settings");
const mappersTab = useTab("mappers");
const scopeTab = useTab("scope");
const eventsTab = useTab("events");

const onSubmit = async (formData: ClientScopeDefaultOptionalType) => {
const clientScope = convertFormValuesToObject({
Expand Down Expand Up @@ -289,6 +293,16 @@ export default function EditClientScope() {
save={assignRoles}
/>
</Tab>
{realmRepresentation?.adminEventsEnabled &&
hasAccess("view-events") && (
<Tab
data-testid="admin-events-tab"
title={<TabTitleText>{t("adminEvents")}</TabTitleText>}
{...eventsTab}
>
<AdminEvents resourcePath={`*client-scopes/${id}`} />
</Tab>
)}
</RoutableTabs>
</PageSection>
</>
Expand Down
2 changes: 1 addition & 1 deletion js/apps/admin-ui/src/client-scopes/routes/ClientScope.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Path } from "react-router-dom";
import { generateEncodedPath } from "../../utils/generateEncodedPath";
import type { AppRouteObject } from "../../routes";

export type ClientScopeTab = "settings" | "mappers" | "scope";
export type ClientScopeTab = "settings" | "mappers" | "scope" | "events";

export type ClientScopeParams = {
realm: string;
Expand Down
46 changes: 36 additions & 10 deletions js/apps/admin-ui/src/clients/ClientDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Label,
PageSection,
Tab,
Tabs,
TabTitleText,
Tooltip,
} from "@patternfly/react-core";
Expand Down Expand Up @@ -73,6 +74,7 @@ import { EvaluateScopes } from "./scopes/EvaluateScopes";
import { ServiceAccount } from "./service-account/ServiceAccount";
import { getProtocolName, isRealmClient } from "./utils";
import { UserEvents } from "../events/UserEvents";
import { AdminEvents } from "../events/AdminEvents";

type ClientDetailHeaderProps = {
onChange: (value: boolean) => void;
Expand Down Expand Up @@ -243,7 +245,9 @@ export default function ClientDetails() {
const sessionsTab = useRoutableTab(tab("sessions"));
const permissionsTab = useRoutableTab(tab("permissions"));
const advancedTab = useRoutableTab(tab("advanced"));
const userEventsTab = useRoutableTab(tab("user-events"));
const eventsTab = useRoutableTab(tab("events"));

const [activeEventsTab, setActiveEventsTab] = useState("userEvents");

const clientScopesTabRoute = (tab: ClientScopesTab) =>
toClientScopesTab({
Expand Down Expand Up @@ -675,15 +679,37 @@ export default function ClientDetails() {
>
<AdvancedTab save={save} client={client} />
</Tab>
{hasAccess("view-events") && realmRepresentation?.eventsEnabled && (
<Tab
data-testid="user-events-tab"
title={<TabTitleText>{t("events")}</TabTitleText>}
{...userEventsTab}
>
<UserEvents client={client.clientId} />
</Tab>
)}
{hasAccess("view-events") &&
(realmRepresentation?.adminEventsEnabled ||
realmRepresentation?.eventsEnabled) && (
<Tab
data-testid="events-tab"
title={<TabTitleText>{t("events")}</TabTitleText>}
{...eventsTab}
>
<Tabs
activeKey={activeEventsTab}
onSelect={(_, key) => setActiveEventsTab(key as string)}
>
{realmRepresentation?.eventsEnabled && (
<Tab
eventKey="userEvents"
title={<TabTitleText>{t("userEvents")}</TabTitleText>}
>
<UserEvents client={client.clientId} />
</Tab>
)}
{realmRepresentation?.adminEventsEnabled && (
<Tab
eventKey="adminEvents"
title={<TabTitleText>{t("adminEvents")}</TabTitleText>}
>
<AdminEvents resourcePath={`clients/${client.id}`} />
</Tab>
)}
</Tabs>
</Tab>
)}
</RoutableTabs>
</FormProvider>
</PageSection>
Expand Down
2 changes: 1 addition & 1 deletion js/apps/admin-ui/src/clients/routes/Client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type ClientTab =
| "serviceAccount"
| "permissions"
| "sessions"
| "user-events";
| "events";

export type ClientParams = {
realm: string;
Expand Down
40 changes: 23 additions & 17 deletions js/apps/admin-ui/src/events/AdminEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,6 @@ type AdminEventSearchForm = {
authIpAddress: string;
};

const defaultValues: AdminEventSearchForm = {
resourceTypes: [],
operationTypes: [],
resourcePath: "",
dateFrom: "",
dateTo: "",
authClient: "",
authUser: "",
authRealm: "",
authIpAddress: "",
};

const DisplayDialog = ({
titleKey,
onClose,
Expand Down Expand Up @@ -114,7 +102,12 @@ const DetailCell = (event: AdminEventRepresentation) => (
</DescriptionList>
);

export const AdminEvents = () => {

Check failure on line 105 in js/apps/admin-ui/src/events/AdminEvents.tsx

View workflow job for this annotation

GitHub Actions / Admin UI

Delete `⏎`
type AdminEventsProps = {
resourcePath?: string;
};

export const AdminEvents = ({ resourcePath }: AdminEventsProps) => {
const { adminClient } = useAdminClient();

const { t } = useTranslation();
Expand All @@ -131,7 +124,21 @@ export const AdminEvents = () => {
useState(false);
const [activeFilters, setActiveFilters] = useState<
Partial<AdminEventSearchForm>
>({});
>({
...(resourcePath && { resourcePath }),
});

const defaultValues: AdminEventSearchForm = {
resourceTypes: [],
operationTypes: [],
resourcePath: resourcePath ? resourcePath : "",
dateFrom: "",
dateTo: "",
authClient: "",
authUser: "",
authRealm: "",
authIpAddress: "",
};

const [authEvent, setAuthEvent] = useState<AdminEventRepresentation>();
const [representationEvent, setRepresentationEvent] =
Expand Down Expand Up @@ -436,10 +443,10 @@ export const AdminEvents = () => {
)}
/>
</FormGroup>
<TextControl
{!resourcePath && (<TextControl

Check failure on line 446 in js/apps/admin-ui/src/events/AdminEvents.tsx

View workflow job for this annotation

GitHub Actions / Admin UI

Insert `⏎······················`
name="resourcePath"

Check failure on line 447 in js/apps/admin-ui/src/events/AdminEvents.tsx

View workflow job for this annotation

GitHub Actions / Admin UI

Insert `··`
label={t("resourcePath")}

Check failure on line 448 in js/apps/admin-ui/src/events/AdminEvents.tsx

View workflow job for this annotation

GitHub Actions / Admin UI

Insert `··`
/>
/>)}

Check failure on line 449 in js/apps/admin-ui/src/events/AdminEvents.tsx

View workflow job for this annotation

GitHub Actions / Admin UI

Replace `/>` with `··/>⏎····················`
<TextControl name="authRealm" label={t("realm")} />
<TextControl name="authClient" label={t("client")} />
<TextControl name="authUser" label={t("user")} />
Expand Down Expand Up @@ -514,7 +521,6 @@ export const AdminEvents = () => {
className="pf-v5-u-mt-md pf-v5-u-mr-md"
key={key}
categoryName={filterLabels[key]}
isClosable
onClick={() => removeFilter(key)}
>
{typeof value === "string" ? (
Expand Down
53 changes: 52 additions & 1 deletion js/apps/admin-ui/src/groups/GroupsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { getId, getLastId } from "./groupIdUtils";
import { toGroups } from "./routes/Groups";

import "./GroupsSection.css";
import { AdminEvents } from "../events/AdminEvents";

export default function GroupsSection() {
const { adminClient } = useAdminClient();
Expand All @@ -48,7 +49,7 @@ export default function GroupsSection() {
const [activeTab, setActiveTab] = useState(0);

const { subGroups, setSubGroups, currentGroup } = useSubGroups();
const { realm } = useRealm();
const { realm, realmRepresentation } = useRealm();

const [rename, setRename] = useState<GroupRepresentation>();
const [deleteOpen, toggleDeleteOpen] = useToggle();
Expand Down Expand Up @@ -77,6 +78,8 @@ export default function GroupsSection() {
currentGroup()?.access?.viewMembers ||
currentGroup()?.access?.manageMembers;

const [activeEventsTab, setActiveEventsTab] = useState("adminEvents");

useFetch(
async () => {
const ids = getId(location.pathname);
Expand Down Expand Up @@ -234,6 +237,54 @@ export default function GroupsSection() {
<PermissionsTab id={id} type="groups" />
</Tab>
)}
{realmRepresentation?.adminEventsEnabled &&
hasAccess("view-events") && (
<Tab
eventKey={5}
data-testid="admin-events-tab"
title={<TabTitleText>{t("adminEvents")}</TabTitleText>}
>
<Tabs
activeKey={activeEventsTab}
onSelect={(_, key) =>
setActiveEventsTab(key as string)
}
>
<Tab
eventKey="adminEvents"
title={
<TabTitleText>{t("adminEvents")}</TabTitleText>
}
>
<AdminEvents resourcePath={`groups/${id}`} />
</Tab>
<Tab
eventKey="membershipEvents"
title={
<TabTitleText>
{t("membershipEvents")}
</TabTitleText>
}
>
<AdminEvents
resourcePath={`users/*/groups/${id}`}
/>
</Tab>
<Tab
eventKey="childGroupEvents"
title={
<TabTitleText>
{t("childGroupEvents")}
</TabTitleText>
}
>
<AdminEvents
resourcePath={`groups/${id}/children`}
/>
</Tab>
</Tabs>
</Tab>
)}
</Tabs>
)}
{subGroups.length === 0 && <GroupTable refresh={refresh} />}
Expand Down
18 changes: 17 additions & 1 deletion js/apps/admin-ui/src/identity-providers/add/DetailSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
useRoutableTab,
} from "../../components/routable-tabs/RoutableTabs";
import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useAccess } from "../../context/access/Access";
import { useRealm } from "../../context/realm-context/RealmContext";
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
import { toUpperCase } from "../../util";
Expand All @@ -64,6 +65,7 @@ import { OIDCAuthentication } from "./OIDCAuthentication";
import { OIDCGeneralSettings } from "./OIDCGeneralSettings";
import { ReqAuthnConstraints } from "./ReqAuthnConstraintsSettings";
import { SamlGeneralSettings } from "./SamlGeneralSettings";
import { AdminEvents } from "../../events/AdminEvents";

type HeaderProps = {
onChange: (value: boolean) => void;
Expand Down Expand Up @@ -278,9 +280,10 @@ export default function DetailSettings() {

const { addAlert, addError } = useAlerts();
const navigate = useNavigate();
const { realm } = useRealm();
const { realm, realmRepresentation } = useRealm();
const [key, setKey] = useState(0);
const refresh = () => setKey(key + 1);
const { hasAccess } = useAccess();

useFetch(
() => adminClient.identityProviders.findOne({ alias }),
Expand Down Expand Up @@ -322,6 +325,7 @@ export default function DetailSettings() {
const settingsTab = useTab("settings");
const mappersTab = useTab("mappers");
const permissionsTab = useTab("permissions");
const eventsTab = useTab("events");

const save = async (savedProvider?: IdentityProviderRepresentation) => {
const p = savedProvider || getValues();
Expand Down Expand Up @@ -616,6 +620,18 @@ export default function DetailSettings() {
<PermissionsTab id={alias} type="identityProviders" />
</Tab>
)}
{realmRepresentation?.adminEventsEnabled &&
hasAccess("view-events") && (
<Tab
data-testid="admin-events-tab"
title={<TabTitleText>{t("adminEvents")}</TabTitleText>}
{...eventsTab}
>
<AdminEvents
resourcePath={`identity-provider/instances/${alias}`}
/>
</Tab>
)}
</RoutableTabs>
</PageSection>
</FormProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import type { Path } from "react-router-dom";
import { generateEncodedPath } from "../../utils/generateEncodedPath";
import type { AppRouteObject } from "../../routes";

export type IdentityProviderTab = "settings" | "mappers" | "permissions";
export type IdentityProviderTab =
| "settings"
| "mappers"
| "permissions"
| "events";

export type IdentityProviderParams = {
realm: string;
Expand Down
Loading

0 comments on commit 038c304

Please sign in to comment.