
* 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: Update to OpenAPI 7.11.
This commit updates our Makefile to generate the Typescript api using OpenAPI 7.11, and updates
names (mostly of enum targets) in our product to correspond to the changes in how OpenAPI generates
enum source names.
1. Replaced `ProviderModelEnum.` (note terminal period) with `ProviderModelEnum.AuthentikProvider`.
For example:
```
- ProviderModelEnum.SamlSamlprovider
+ ProviderModelEnum.AuthentikProvidersSamlSamlprovider
```
2. Replaced `RbacPermissionsAssignedByUsersListModelEnum.` (note terminal period) with
`RbacPermissionsAssignedByUsersListModelEnum.Authentik`. For example:
```
- RbacPermissionsAssignedByUsersListModelEnum.ProvidersLdapLdapprovider.toString(),
+ RbacPermissionsAssignedByUsersListModelEnum.AuthentikProvidersLdapLdapprovider.toString(),
```
3. Replaced `SyncObjectModelEnum.` (note terminal period) with
`SyncObjectModelEnum.AuthentikCoreModels`. For example:
```
- model=${SyncObjectModelEnum.Group}
+ model=${SyncObjectModelEnum.AuthentikCoreModelsGroup}
```
4. Replaced `SignatureAlgorithmEnum._` (note terminal symbols) with
`SignatureAlgorithmEnum.HttpWwwW3Org`. For example:
```
- ["ECDSA-SHA256", SignatureAlgorithmEnum._200104XmldsigMoreecdsaSha256],
+ ["ECDSA-SHA256", SignatureAlgorithmEnum.HttpWwwW3Org200104XmldsigMoreecdsaSha256],
```
5. Replaced `DigestAlgorithmEnum._` (note terminal symbols) with `DigestAlgorithmEnum.HttpWwwW3Org`.
For example:
```
- ["SHA256", DigestAlgorithmEnum._200104Xmlencsha256, true],
+ ["SHA256", DigestAlgorithmEnum.HttpWwwW3Org200104Xmlencsha256, true],
```
6. Replaced `NameIdPolicyEnum._` (note terminal symbols) with
`NameIdPolicyEnum.UrnOasisNamesTcSaml`. This one is trickier than the others: If you look
closely, you'll see that how OpenAPI generates the names has changed, with `nameid` now being
`Nameid`, and `FormatemailAddress` now being `FormatEmailAddress`.
```
- value=${NameIdPolicyEnum._11nameidFormatemailAddress}
+ value=${NameIdPolicyEnum.UrnOasisNamesTcSaml11NameidFormatEmailAddress}
```
# How
After determining how the enum prefixes had changed, I just ran six of these, testing after each
step to ensure that `npm run lint:types` had fewer errors than the previous run, until the product
built without type errors.
``` sh
$ perl -pi.bak -e 's/DigestAlgorithmEnum\._/DigestAlgorithmEnum.HttpWwwW3Org/' $(rg -l 'DigestAlgorithmEnum\.' src/)
```
# Testing
You can validate that these items have changed by finding the prefixes in the source code and
assuring yourself that every option, checkbox, or radio associated with them is populated correctly.
# User documentation changes required.
None.
# Developer documentation changes required.
None.
355 lines
18 KiB
TypeScript
355 lines
18 KiB
TypeScript
import "@goauthentik/admin/applications/ApplicationAuthorizeChart";
|
|
import "@goauthentik/admin/applications/ApplicationCheckAccessForm";
|
|
import "@goauthentik/admin/applications/ApplicationForm";
|
|
import "@goauthentik/admin/applications/entitlements/ApplicationEntitlementPage";
|
|
import "@goauthentik/admin/policies/BoundPoliciesList";
|
|
import "@goauthentik/admin/rbac/ObjectPermissionsPage";
|
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
|
import { PFSize } from "@goauthentik/common/enums.js";
|
|
import "@goauthentik/components/events/ObjectChangelog";
|
|
import "@goauthentik/elements/AppIcon";
|
|
import { AKElement } from "@goauthentik/elements/Base";
|
|
import "@goauthentik/elements/EmptyState";
|
|
import "@goauthentik/elements/PageHeader";
|
|
import "@goauthentik/elements/Tabs";
|
|
import "@goauthentik/elements/buttons/SpinnerButton";
|
|
|
|
import { msg } from "@lit/localize";
|
|
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
|
|
import { customElement, property, state } from "lit/decorators.js";
|
|
import { ifDefined } from "lit/directives/if-defined.js";
|
|
|
|
import PFBanner from "@patternfly/patternfly/components/Banner/banner.css";
|
|
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
|
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
|
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
|
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
|
|
import PFList from "@patternfly/patternfly/components/List/list.css";
|
|
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
|
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
|
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
|
|
|
import {
|
|
Application,
|
|
CoreApi,
|
|
OutpostsApi,
|
|
RbacPermissionsAssignedByUsersListModelEnum,
|
|
} from "@goauthentik/api";
|
|
|
|
@customElement("ak-application-view")
|
|
export class ApplicationViewPage extends AKElement {
|
|
@property({ type: String })
|
|
applicationSlug?: string;
|
|
|
|
@state()
|
|
application?: Application;
|
|
|
|
@state()
|
|
missingOutpost = false;
|
|
|
|
static get styles(): CSSResult[] {
|
|
return [
|
|
PFBase,
|
|
PFList,
|
|
PFBanner,
|
|
PFPage,
|
|
PFContent,
|
|
PFButton,
|
|
PFDescriptionList,
|
|
PFGrid,
|
|
PFCard,
|
|
];
|
|
}
|
|
|
|
fetchIsMissingOutpost(providersByPk: Array<number>) {
|
|
new OutpostsApi(DEFAULT_CONFIG)
|
|
.outpostsInstancesList({
|
|
providersByPk,
|
|
pageSize: 1,
|
|
})
|
|
.then((outposts) => {
|
|
if (outposts.pagination.count < 1) {
|
|
this.missingOutpost = true;
|
|
}
|
|
});
|
|
}
|
|
|
|
fetchApplication(slug: string) {
|
|
new CoreApi(DEFAULT_CONFIG).coreApplicationsRetrieve({ slug }).then((app) => {
|
|
this.application = app;
|
|
if (
|
|
app.providerObj &&
|
|
[
|
|
RbacPermissionsAssignedByUsersListModelEnum.AuthentikProvidersProxyProxyprovider.toString(),
|
|
RbacPermissionsAssignedByUsersListModelEnum.AuthentikProvidersLdapLdapprovider.toString(),
|
|
].includes(app.providerObj.metaModelName)
|
|
) {
|
|
this.fetchIsMissingOutpost([app.provider || 0]);
|
|
}
|
|
});
|
|
}
|
|
|
|
willUpdate(changedProperties: PropertyValues<this>) {
|
|
if (changedProperties.has("applicationSlug") && this.applicationSlug) {
|
|
this.fetchApplication(this.applicationSlug);
|
|
}
|
|
}
|
|
|
|
render(): TemplateResult {
|
|
return html`<ak-page-header
|
|
header=${this.application?.name || msg("Loading")}
|
|
description=${ifDefined(this.application?.metaPublisher)}
|
|
.iconImage=${true}
|
|
>
|
|
<ak-app-icon
|
|
size=${PFSize.Medium}
|
|
name=${ifDefined(this.application?.name || undefined)}
|
|
icon=${ifDefined(this.application?.metaIcon || undefined)}
|
|
slot="icon"
|
|
></ak-app-icon>
|
|
</ak-page-header>
|
|
${this.renderApp()}`;
|
|
}
|
|
|
|
renderApp(): TemplateResult {
|
|
if (!this.application) {
|
|
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
|
|
</ak-empty-state>`;
|
|
}
|
|
return html`<ak-tabs>
|
|
${this.missingOutpost
|
|
? html`<div slot="header" class="pf-c-banner pf-m-warning">
|
|
${msg("Warning: Application is not used by any Outpost.")}
|
|
</div>`
|
|
: html``}
|
|
<section
|
|
slot="page-overview"
|
|
data-tab-title="${msg("Overview")}"
|
|
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
|
>
|
|
<div class="pf-l-grid pf-m-gutter">
|
|
<div
|
|
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-2-col-on-xl pf-m-2-col-on-2xl"
|
|
>
|
|
<div class="pf-c-card__title">${msg("Related")}</div>
|
|
<div class="pf-c-card__body">
|
|
<dl class="pf-c-description-list">
|
|
${this.application.providerObj
|
|
? html`<div class="pf-c-description-list__group">
|
|
<dt class="pf-c-description-list__term">
|
|
<span class="pf-c-description-list__text"
|
|
>${msg("Provider")}</span
|
|
>
|
|
</dt>
|
|
<dd class="pf-c-description-list__description">
|
|
<div class="pf-c-description-list__text">
|
|
<a
|
|
href="#/core/providers/${this.application
|
|
.providerObj?.pk}"
|
|
>
|
|
${this.application.providerObj?.name}
|
|
(${this.application.providerObj?.verboseName})
|
|
</a>
|
|
</div>
|
|
</dd>
|
|
</div>`
|
|
: html``}
|
|
${(this.application.backchannelProvidersObj || []).length > 0
|
|
? html`<div class="pf-c-description-list__group">
|
|
<dt class="pf-c-description-list__term">
|
|
<span class="pf-c-description-list__text"
|
|
>${msg("Backchannel Providers")}</span
|
|
>
|
|
</dt>
|
|
<dd class="pf-c-description-list__description">
|
|
<div class="pf-c-description-list__text">
|
|
<ul class="pf-c-list">
|
|
${this.application.backchannelProvidersObj.map(
|
|
(provider) => {
|
|
return html`
|
|
<li>
|
|
<a
|
|
href="#/core/providers/${provider.pk}"
|
|
>
|
|
${provider.name}
|
|
(${provider.verboseName})
|
|
</a>
|
|
</li>
|
|
`;
|
|
},
|
|
)}
|
|
</ul>
|
|
</div>
|
|
</dd>
|
|
</div>`
|
|
: html``}
|
|
<div class="pf-c-description-list__group">
|
|
<dt class="pf-c-description-list__term">
|
|
<span class="pf-c-description-list__text"
|
|
>${msg("Policy engine mode")}</span
|
|
>
|
|
</dt>
|
|
<dd class="pf-c-description-list__description">
|
|
<div class="pf-c-description-list__text">
|
|
${this.application.policyEngineMode?.toUpperCase()}
|
|
</div>
|
|
</dd>
|
|
</div>
|
|
<div class="pf-c-description-list__group">
|
|
<dt class="pf-c-description-list__term">
|
|
<span class="pf-c-description-list__text"
|
|
>${msg("Edit")}</span
|
|
>
|
|
</dt>
|
|
<dd class="pf-c-description-list__description">
|
|
<div class="pf-c-description-list__text">
|
|
<ak-forms-modal>
|
|
<span slot="submit"> ${msg("Update")} </span>
|
|
<span slot="header">
|
|
${msg("Update Application")}
|
|
</span>
|
|
<ak-application-form
|
|
slot="form"
|
|
.instancePk=${this.application.slug}
|
|
>
|
|
</ak-application-form>
|
|
<button
|
|
slot="trigger"
|
|
class="pf-c-button pf-m-secondary"
|
|
>
|
|
${msg("Edit")}
|
|
</button>
|
|
</ak-forms-modal>
|
|
</div>
|
|
</dd>
|
|
</div>
|
|
<div class="pf-c-description-list__group">
|
|
<dt class="pf-c-description-list__term">
|
|
<span class="pf-c-description-list__text"
|
|
>${msg("Check access")}</span
|
|
>
|
|
</dt>
|
|
<dd class="pf-c-description-list__description">
|
|
<div class="pf-c-description-list__text">
|
|
<ak-forms-modal .closeAfterSuccessfulSubmit=${false}>
|
|
<span slot="submit"> ${msg("Check")} </span>
|
|
<span slot="header">
|
|
${msg("Check Application access")}
|
|
</span>
|
|
<ak-application-check-access-form
|
|
slot="form"
|
|
.application=${this.application}
|
|
>
|
|
</ak-application-check-access-form>
|
|
<button
|
|
slot="trigger"
|
|
class="pf-c-button pf-m-secondary"
|
|
>
|
|
${msg("Test")}
|
|
</button>
|
|
</ak-forms-modal>
|
|
</div>
|
|
</dd>
|
|
</div>
|
|
${this.application.launchUrl
|
|
? html`<div class="pf-c-description-list__group">
|
|
<dt class="pf-c-description-list__term">
|
|
<span class="pf-c-description-list__text"
|
|
>${msg("Launch")}</span
|
|
>
|
|
</dt>
|
|
<dd class="pf-c-description-list__description">
|
|
<div class="pf-c-description-list__text">
|
|
<a
|
|
target="_blank"
|
|
href=${this.application.launchUrl}
|
|
slot="trigger"
|
|
class="pf-c-button pf-m-secondary"
|
|
>
|
|
${msg("Launch")}
|
|
</a>
|
|
</div>
|
|
</dd>
|
|
</div>`
|
|
: html``}
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-10-col-on-xl pf-m-10-col-on-2xl"
|
|
>
|
|
<div class="pf-c-card__title">
|
|
${msg("Logins over the last week (per 8 hours)")}
|
|
</div>
|
|
<div class="pf-c-card__body">
|
|
${this.application &&
|
|
html` <ak-charts-application-authorize
|
|
applicationSlug=${this.application.slug}
|
|
>
|
|
</ak-charts-application-authorize>`}
|
|
</div>
|
|
</div>
|
|
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
|
|
<div class="pf-c-card__title">${msg("Changelog")}</div>
|
|
<div class="pf-c-card__body">
|
|
<ak-object-changelog
|
|
targetModelPk=${this.application.pk || ""}
|
|
targetModelApp="authentik_core"
|
|
targetModelName="application"
|
|
>
|
|
</ak-object-changelog>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section
|
|
slot="page-app-entitlements"
|
|
data-tab-title="${msg("Application entitlements")}"
|
|
>
|
|
<div slot="header" class="pf-c-banner pf-m-info">
|
|
${msg("Application entitlements are in preview.")}
|
|
<a href="mailto:hello+feature/app-ent@goauthentik.io"
|
|
>${msg("Send us feedback!")}</a
|
|
>
|
|
</div>
|
|
<div class="pf-c-page__main-section pf-m-no-padding-mobile">
|
|
<div class="pf-c-card">
|
|
<div class="pf-c-card__title">
|
|
${msg(
|
|
"These entitlements can be used to configure user access in this application.",
|
|
)}
|
|
</div>
|
|
<ak-application-entitlements-list .app=${this.application.pk}>
|
|
</ak-application-entitlements-list>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section
|
|
slot="page-policy-bindings"
|
|
data-tab-title="${msg("Policy / Group / User Bindings")}"
|
|
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
|
>
|
|
<div class="pf-c-card">
|
|
<div class="pf-c-card__title">
|
|
${msg("These policies control which users can access this application.")}
|
|
</div>
|
|
<ak-bound-policies-list .target=${this.application.pk}>
|
|
</ak-bound-policies-list>
|
|
</div>
|
|
</section>
|
|
<ak-rbac-object-permission-page
|
|
slot="page-permissions"
|
|
data-tab-title="${msg("Permissions")}"
|
|
model=${RbacPermissionsAssignedByUsersListModelEnum.AuthentikCoreApplication}
|
|
objectPk=${this.application.pk}
|
|
></ak-rbac-object-permission-page>
|
|
</ak-tabs>`;
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"ak-application-view": ApplicationViewPage;
|
|
}
|
|
}
|