events: use pending_user as user when possible (#15238)

* unrelated: dont show nested for user

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* unrelated: fix error when no extents in. map

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* events: use pending_user when possible

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix for identification stage "fake" user

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* better username rendering

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L.
2025-06-25 18:22:51 +02:00
committed by GitHub
parent 31b72751bc
commit 680db9bae6
12 changed files with 167 additions and 43 deletions

View File

@ -1,4 +1,4 @@
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
import { EventGeo, renderEventUser } from "@goauthentik/admin/events/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventWithContext } from "@goauthentik/common/events";
import { actionToLabel } from "@goauthentik/common/labels";
@ -73,7 +73,7 @@ export class RecentEventsCard extends Table<Event> {
return [
html`<div><a href="${`#/events/log/${item.pk}`}">${actionToLabel(item.action)}</a></div>
<small>${item.app}</small>`,
EventUser(item),
renderEventUser(item),
html`<div>${formatElapsedTime(item.created)}</div>
<small>${item.created.toLocaleString()}</small>`,
html` <div>${item.clientIp || msg("-")}</div>

View File

@ -3,7 +3,7 @@ import { WithLicenseSummary } from "#elements/mixins/license";
import { updateURLParams } from "#elements/router/RouteMatch";
import "@goauthentik/admin/events/EventMap";
import "@goauthentik/admin/events/EventVolumeChart";
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
import { EventGeo, renderEventUser } from "@goauthentik/admin/events/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventWithContext } from "@goauthentik/common/events";
import { actionToLabel } from "@goauthentik/common/labels";
@ -113,7 +113,7 @@ export class EventListPage extends WithLicenseSummary(TablePage<Event>) {
return [
html`<div>${actionToLabel(item.action)}</div>
<small>${item.app}</small>`,
EventUser(item),
renderEventUser(item),
html`<div>${formatElapsedTime(item.created)}</div>
<small>${item.created.toLocaleString()}</small>`,
html`<div>${item.clientIp || msg("-")}</div>

View File

@ -8,6 +8,7 @@ import OlMap from "@openlayers-elements/core/ol-map";
import "@openlayers-elements/maps/ol-layer-openstreetmap";
import "@openlayers-elements/maps/ol-select";
import Feature from "ol/Feature";
import { isEmpty } from "ol/extent";
import { Point } from "ol/geom";
import { fromLonLat } from "ol/proj";
import Icon from "ol/style/Icon";
@ -124,6 +125,9 @@ export class EventMap extends AKElement {
this.vectorLayer?.source?.addFeature(feature);
});
// Zoom to show points better
if (isEmpty(this.vectorLayer.source.getExtent())) {
return;
}
this.map.map.getView().fit(this.vectorLayer.source.getExtent(), {
padding: [
this.zoomPaddingPx,

View File

@ -1,4 +1,4 @@
import { EventGeo, EventUser } from "#admin/events/utils";
import { EventGeo, renderEventUser } from "#admin/events/utils";
import { DEFAULT_CONFIG } from "#common/api/config";
import { EventWithContext } from "#common/events";
import { actionToLabel } from "#common/labels";
@ -92,7 +92,7 @@ export class EventViewPage extends AKElement {
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${EventUser(this.event)}
${renderEventUser(this.event)}
</div>
</dd>
</div>

View File

@ -1,9 +1,9 @@
import { EventWithContext } from "@goauthentik/common/events";
import { EventUser, EventWithContext } from "@goauthentik/common/events";
import { truncate } from "@goauthentik/common/utils";
import { SlottedTemplateResult } from "@goauthentik/elements/types";
import { msg, str } from "@lit/localize";
import { html, nothing } from "lit";
import { TemplateResult, html, nothing } from "lit";
/**
* Given event with a geographical context, format it into a string for display.
@ -18,31 +18,48 @@ export function EventGeo(event: EventWithContext): SlottedTemplateResult {
return html`${parts.join(", ")}`;
}
export function EventUser(
export function renderEventUser(
event: EventWithContext,
truncateUsername?: number,
): SlottedTemplateResult {
if (!event.user.username) return html`-`;
let body: SlottedTemplateResult = nothing;
const linkOrSpan = (inner: TemplateResult, evu: EventUser) => {
return html`${evu.pk && !evu.is_anonymous
? html`<a href="#/identity/users/${evu.pk}">${inner}</a>`
: html`<span>${inner}</span>`}`;
};
if (event.user.is_anonymous) {
body = html`<div>${msg("Anonymous user")}</div>`;
} else {
body = html`<div>
<a href="#/identity/users/${event.user.pk}"
>${truncateUsername
? truncate(event.user?.username, truncateUsername)
: event.user?.username}</a
>
</div>`;
}
const renderUsername = (evu: EventUser) => {
let username = evu.username;
if (evu.is_anonymous) {
username = msg("Anonymous user");
}
if (truncateUsername) {
return truncate(username, truncateUsername);
}
return username;
};
let body: SlottedTemplateResult = nothing;
body = html`<div>${linkOrSpan(html`${renderUsername(event.user)}`, event.user)}</div>`;
if (event.user.on_behalf_of) {
return html`${body}<small>
<a href="#/identity/users/${event.user.on_behalf_of.pk}"
>${msg(str`On behalf of ${event.user.on_behalf_of.username}`)}</a
>
${linkOrSpan(
html`${msg(str`On behalf of ${renderUsername(event.user.on_behalf_of)}`)}`,
event.user.on_behalf_of,
)}
</small>`;
}
if (event.user.authenticated_as) {
return html`${body}<small>
${linkOrSpan(
html`${msg(
str`Authenticated as ${renderUsername(event.user.authenticated_as)}`,
)}`,
event.user.authenticated_as,
)}
</small>`;
}

View File

@ -4,8 +4,9 @@ export interface EventUser {
pk: number;
email?: string;
username: string;
on_behalf_of?: EventUser;
is_anonymous?: boolean;
on_behalf_of?: EventUser;
authenticated_as?: EventUser;
}
export interface EventGeo {

View File

@ -1,4 +1,4 @@
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
import { EventGeo, renderEventUser } from "@goauthentik/admin/events/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventWithContext } from "@goauthentik/common/events";
import { actionToLabel } from "@goauthentik/common/labels";
@ -72,7 +72,7 @@ export class ObjectChangelog extends Table<Event> {
row(item: EventWithContext): SlottedTemplateResult[] {
return [
html`${actionToLabel(item.action)}`,
EventUser(item),
renderEventUser(item),
html`<div>${formatElapsedTime(item.created)}</div>
<small>${item.created.toLocaleString()}</small>`,
html`<div>${item.clientIp || msg("-")}</div>

View File

@ -1,4 +1,4 @@
import { EventUser } from "@goauthentik/admin/events/utils";
import { renderEventUser } from "@goauthentik/admin/events/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventWithContext } from "@goauthentik/common/events";
import { actionToLabel } from "@goauthentik/common/labels";
@ -46,7 +46,7 @@ export class UserEvents extends Table<Event> {
row(item: EventWithContext): SlottedTemplateResult[] {
return [
html`${actionToLabel(item.action)}`,
EventUser(item),
renderEventUser(item),
html`<div>${formatElapsedTime(item.created)}</div>
<small>${item.created.toLocaleString()}</small>`,
html`<span>${item.clientIp || msg("-")}</span>`,