
* web: Add InvalidationFlow to Radius Provider dialogues
## What
- Bugfix: adds the InvalidationFlow to the Radius Provider dialogues
- Repairs: `{"invalidation_flow":["This field is required."]}` message, which was *not* propagated
to the Notification.
- Nitpick: Pretties `?foo=${true}` expressions: `s/\?([^=]+)=\$\{true\}/\1/`
## Note
Yes, I know I'm going to have to do more magic when we harmonize the forms, and no, I didn't add the
Property Mappings to the wizard, and yes, I know I'm going to have pain with the *new* version of
the wizard. But this is a serious bug; you can't make Radius servers with *either* of the current
dialogues at the moment.
* This (temporary) change is needed to prevent the unit tests from failing.
\# What
\# Why
\# How
\# Designs
\# Test Steps
\# Other Notes
* Revert "This (temporary) change is needed to prevent the unit tests from failing."
This reverts commit dddde09be5
.
* web: remove Lit syntax from always true attributes
## What
Replaces instances of `?loading=${true}` and `?loading="${true}"` with `loading`
## Why
The Lit syntax is completely unnecessary when the attribute's state is constant, and it's a few
(just a few) extra CPU cycles for Lit to process that.
More to the point, it annoys me.
## How
```
$ perl -pi.bak -e 's/\?loading=\$\{true\}/loading/' $(rg -l '\?loading=\$\{true\}')
$ find . -name '*.bak' -exec rm {} \;
$ perl -pi.bak -e 's/\?loading="\$\{true\}"/loading/' $(rg -l '\?loading="\$\{true\}"')
$ find . -name '*.bak' -exec rm {} \;
```
* Prettier had opinions
* web: move optional textual information out of attributes and into slots
## What
Replaces instances of:
```
<ak-empty-state header=${msg(...)}></ak-empty-state>
```
with
```
<ak-empty-state><span slot="header">${msg(...)}</span></ak-empty-state>
```
## Why
1. It's correct.
2. It lets us elide the decorations for any slots we aren't using.
3. It's preparation for moving to Patternfly 5
4. It annoyed me.
## How
Since we already have Patternfly Elements installed, we have access to the PFE-Core, which has the
unbelievable useful `SlotsController`. Using it, I created a conditional render template that will
only put in the header, body, and primary slots if there is something in the lightDOM requesting
those slots. The conditional template will still put the spinner in if the header is not provided
but the loading state is true.
I then had to edit all the places where this is used. For about 30 of them, this script sufficed:
```
perl -pi.bak -e 's/header="?(\$\{msg\([^)]+\)\})"?>/><span slot="header">\1<\/span>/' \
$(rg -l `<ak-empty-state[^>]header')
```
The other six had to be done by hand. I have tested a handful of the automatic ones, and all of the
ones that were edited manually. I'm pleasantly surprised that the textual rules [are inherited by
the slots as expected](https://htmlwithsuperpowers.netlify.app/styling/inheritable.htm).
110 lines
3.6 KiB
TypeScript
110 lines
3.6 KiB
TypeScript
import { EventGeo, EventUser } 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";
|
|
import { formatElapsedTime } from "@goauthentik/common/temporal";
|
|
import "@goauthentik/components/ak-event-info";
|
|
import "@goauthentik/elements/Tabs";
|
|
import "@goauthentik/elements/buttons/Dropdown";
|
|
import "@goauthentik/elements/buttons/ModalButton";
|
|
import "@goauthentik/elements/buttons/SpinnerButton";
|
|
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
|
import { Table, TableColumn } from "@goauthentik/elements/table/Table";
|
|
import { SlottedTemplateResult } from "@goauthentik/elements/types";
|
|
|
|
import { msg } from "@lit/localize";
|
|
import { PropertyValues, TemplateResult, html } from "lit";
|
|
import { customElement, property } from "lit/decorators.js";
|
|
|
|
import { Event, EventsApi } from "@goauthentik/api";
|
|
|
|
@customElement("ak-object-changelog")
|
|
export class ObjectChangelog extends Table<Event> {
|
|
expandable = true;
|
|
|
|
@property()
|
|
order = "-created";
|
|
|
|
@property()
|
|
targetModelPk!: string | number;
|
|
|
|
@property()
|
|
targetModelApp?: string;
|
|
|
|
@property()
|
|
targetModelName = "";
|
|
|
|
async apiEndpoint(): Promise<PaginatedResponse<Event>> {
|
|
let modelName = this.targetModelName;
|
|
let appName = this.targetModelApp;
|
|
if (this.targetModelName.indexOf(".") !== -1) {
|
|
const parts = this.targetModelName.split(".", 1);
|
|
appName = parts[0];
|
|
modelName = parts[1];
|
|
}
|
|
if (this.targetModelName === "") {
|
|
return Promise.reject();
|
|
}
|
|
return new EventsApi(DEFAULT_CONFIG).eventsEventsList({
|
|
...(await this.defaultEndpointConfig()),
|
|
action: "model_",
|
|
contextModelApp: appName,
|
|
contextModelName: modelName,
|
|
contextModelPk: this.targetModelPk.toString(),
|
|
});
|
|
}
|
|
|
|
columns(): TableColumn[] {
|
|
return [
|
|
new TableColumn(msg("Action"), "action"),
|
|
new TableColumn(msg("User"), "enabled"),
|
|
new TableColumn(msg("Creation Date"), "created"),
|
|
new TableColumn(msg("Client IP"), "client_ip"),
|
|
];
|
|
}
|
|
|
|
willUpdate(changedProperties: PropertyValues<this>) {
|
|
if (changedProperties.has("targetModelName") && this.targetModelName) {
|
|
this.fetch();
|
|
}
|
|
}
|
|
|
|
row(item: EventWithContext): SlottedTemplateResult[] {
|
|
return [
|
|
html`${actionToLabel(item.action)}`,
|
|
EventUser(item),
|
|
html`<div>${formatElapsedTime(item.created)}</div>
|
|
<small>${item.created.toLocaleString()}</small>`,
|
|
html`<div>${item.clientIp || msg("-")}</div>
|
|
|
|
<small>${EventGeo(item)}</small>`,
|
|
];
|
|
}
|
|
|
|
renderExpanded(item: Event): TemplateResult {
|
|
return html` <td role="cell" colspan="4">
|
|
<div class="pf-c-table__expandable-row-content">
|
|
<ak-event-info .event=${item as EventWithContext}></ak-event-info>
|
|
</div>
|
|
</td>
|
|
<td></td>
|
|
<td></td>
|
|
<td></td>`;
|
|
}
|
|
|
|
renderEmpty(): TemplateResult {
|
|
return super.renderEmpty(
|
|
html`<ak-empty-state
|
|
><span slot="header">${msg("No Events found.")}</span>
|
|
<div slot="body">${msg("No matching events could be found.")}</div>
|
|
</ak-empty-state>`,
|
|
);
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"ak-object-changelog": ObjectChangelog;
|
|
}
|
|
}
|