web: add RAC Provider to the list of providers understood by the wizard
This commit also creates a new, simple alert that knows how to look up the enterprise requirements and chooses to fill itself in with a notice saying "A license is required for this provider," or nothing. That harmonizes the display across both wizards, and reduces the demands on the wizards themselves to "know" about enterprise features.
This commit is contained in:
parent
be66ee52cd
commit
66fa4e3085
|
@ -1,3 +1,5 @@
|
||||||
|
import "@goauthentik/admin/common/ak-license-notice";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { TemplateResult, html } from "lit";
|
import { TemplateResult, html } from "lit";
|
||||||
|
|
||||||
|
@ -8,6 +10,7 @@ import type {
|
||||||
ModelRequest,
|
ModelRequest,
|
||||||
OAuth2ProviderRequest,
|
OAuth2ProviderRequest,
|
||||||
ProxyProviderRequest,
|
ProxyProviderRequest,
|
||||||
|
RACProviderRequest,
|
||||||
RadiusProviderRequest,
|
RadiusProviderRequest,
|
||||||
SAMLProviderRequest,
|
SAMLProviderRequest,
|
||||||
SCIMProviderRequest,
|
SCIMProviderRequest,
|
||||||
|
@ -19,6 +22,9 @@ type ProviderRenderer = () => TemplateResult;
|
||||||
|
|
||||||
type ModelConverter = (provider: OneOfProvider) => ModelRequest;
|
type ModelConverter = (provider: OneOfProvider) => ModelRequest;
|
||||||
|
|
||||||
|
type ProviderNoteProvider = () => TemplateResult | undefined;
|
||||||
|
type ProviderNote = ProviderNoteProvider | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There's an internal key and an API key because "Proxy" has three different subtypes.
|
* There's an internal key and an API key because "Proxy" has three different subtypes.
|
||||||
*/
|
*/
|
||||||
|
@ -30,12 +36,14 @@ type ProviderType = [
|
||||||
ProviderRenderer, // Function that returns the provider's wizard panel as a TemplateResult
|
ProviderRenderer, // Function that returns the provider's wizard panel as a TemplateResult
|
||||||
ProviderModelEnumType, // key used by the API to distinguish between providers
|
ProviderModelEnumType, // key used by the API to distinguish between providers
|
||||||
ModelConverter, // Handler that takes a generic provider and returns one specifically typed to its panel
|
ModelConverter, // Handler that takes a generic provider and returns one specifically typed to its panel
|
||||||
|
ProviderNote?,
|
||||||
];
|
];
|
||||||
|
|
||||||
export type LocalTypeCreate = TypeCreate & {
|
export type LocalTypeCreate = TypeCreate & {
|
||||||
formName: string;
|
formName: string;
|
||||||
modelName: ProviderModelEnumType;
|
modelName: ProviderModelEnumType;
|
||||||
converter: ModelConverter;
|
converter: ModelConverter;
|
||||||
|
note?: ProviderNote;
|
||||||
};
|
};
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
|
@ -103,6 +111,19 @@ const _providerModelsTable: ProviderType[] = [
|
||||||
mode: ProxyMode.ForwardDomain,
|
mode: ProxyMode.ForwardDomain,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"racprovider",
|
||||||
|
msg("Remote Access Provider"),
|
||||||
|
msg("Remotely access computers/servers via RDP/SSH/VNC"),
|
||||||
|
() =>
|
||||||
|
html`<ak-application-wizard-authentication-for-rac></ak-application-wizard-authentication-for-rac>`,
|
||||||
|
ProviderModelEnum.RacRacprovider,
|
||||||
|
(provider: OneOfProvider) => ({
|
||||||
|
providerModel: ProviderModelEnum.RacRacprovider,
|
||||||
|
...(provider as RACProviderRequest),
|
||||||
|
}),
|
||||||
|
() => html`<ak-license-notice></ak-license-notice>`
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"samlprovider",
|
"samlprovider",
|
||||||
msg("SAML (Security Assertion Markup Language)"),
|
msg("SAML (Security Assertion Markup Language)"),
|
||||||
|
@ -148,6 +169,7 @@ function mapProviders([
|
||||||
_,
|
_,
|
||||||
modelName,
|
modelName,
|
||||||
converter,
|
converter,
|
||||||
|
note,
|
||||||
]: ProviderType): LocalTypeCreate {
|
]: ProviderType): LocalTypeCreate {
|
||||||
return {
|
return {
|
||||||
formName,
|
formName,
|
||||||
|
@ -156,6 +178,7 @@ function mapProviders([
|
||||||
component: "",
|
component: "",
|
||||||
modelName,
|
modelName,
|
||||||
converter,
|
converter,
|
||||||
|
note,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||||
import { html } from "lit";
|
import { html, nothing } from "lit";
|
||||||
import { map } from "lit/directives/map.js";
|
import { map } from "lit/directives/map.js";
|
||||||
|
|
||||||
import BasePanel from "../BasePanel";
|
import BasePanel from "../BasePanel";
|
||||||
|
@ -48,7 +48,9 @@ export class ApplicationWizardAuthenticationMethodChoice extends BasePanel {
|
||||||
@change=${this.handleChoice}
|
@change=${this.handleChoice}
|
||||||
/>
|
/>
|
||||||
<label class="pf-c-radio__label" for="provider-${type.formName}">${type.name}</label>
|
<label class="pf-c-radio__label" for="provider-${type.formName}">${type.name}</label>
|
||||||
<span class="pf-c-radio__description">${type.description}</span>
|
<span class="pf-c-radio__description"
|
||||||
|
>${type.description}${type.note ? type.note() : nothing}</span
|
||||||
|
>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
import "@goauthentik/admin/applications/wizard/ak-wizard-title";
|
||||||
|
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
||||||
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
|
import "@goauthentik/components/ak-text-input";
|
||||||
|
import "@goauthentik/elements/CodeMirror";
|
||||||
|
import "@goauthentik/elements/forms/FormGroup";
|
||||||
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
|
import YAML from "yaml";
|
||||||
|
|
||||||
|
import { msg } from "@lit/localize";
|
||||||
|
import { html } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators.js";
|
||||||
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
FlowsInstancesListDesignationEnum,
|
||||||
|
PaginatedEndpointList,
|
||||||
|
PaginatedRACPropertyMappingList,
|
||||||
|
PropertymappingsApi,
|
||||||
|
RACProvider,
|
||||||
|
RacApi,
|
||||||
|
} from "@goauthentik/api";
|
||||||
|
|
||||||
|
import BaseProviderPanel from "../BaseProviderPanel";
|
||||||
|
|
||||||
|
@customElement("ak-application-wizard-authentication-by-rac")
|
||||||
|
export class ApplicationWizardAuthenticationByRAC extends BaseProviderPanel {
|
||||||
|
@state()
|
||||||
|
endpoints?: PaginatedEndpointList;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
propertyMappings?: PaginatedRACPropertyMappingList;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
new RacApi(DEFAULT_CONFIG).racEndpointsList({}).then((endpoints) => {
|
||||||
|
this.endpoints = endpoints;
|
||||||
|
});
|
||||||
|
new PropertymappingsApi(DEFAULT_CONFIG)
|
||||||
|
.propertymappingsRacList({
|
||||||
|
ordering: "name",
|
||||||
|
})
|
||||||
|
.then((propertyMappings) => {
|
||||||
|
this.propertyMappings = propertyMappings;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const provider = this.wizard.provider as RACProvider | undefined;
|
||||||
|
const selected = new Set(Array.from(provider?.propertyMappings ?? []));
|
||||||
|
const errors = this.wizard.errors.provider;
|
||||||
|
|
||||||
|
return html`<ak-wizard-title
|
||||||
|
>${msg("Configure Remote Access Provider Provider")}</ak-wizard-title
|
||||||
|
>
|
||||||
|
<form class="pf-c-form pf-m-horizontal" @input=${this.handleChange}>
|
||||||
|
<ak-text-input
|
||||||
|
name="name"
|
||||||
|
label=${msg("Name")}
|
||||||
|
value=${ifDefined(provider?.name)}
|
||||||
|
.errorMessages=${errors?.name ?? []}
|
||||||
|
required
|
||||||
|
></ak-text-input>
|
||||||
|
|
||||||
|
<ak-form-element-horizontal
|
||||||
|
name="authorizationFlow"
|
||||||
|
label=${msg("Authorization flow")}
|
||||||
|
?required=${true}
|
||||||
|
>
|
||||||
|
<ak-flow-search
|
||||||
|
flowType=${FlowsInstancesListDesignationEnum.Authorization}
|
||||||
|
.currentFlow=${provider?.authorizationFlow}
|
||||||
|
required
|
||||||
|
></ak-flow-search>
|
||||||
|
<p class="pf-c-form__helper-text">
|
||||||
|
${msg("Flow used when authorizing this provider.")}
|
||||||
|
</p>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
|
|
||||||
|
<ak-text-input
|
||||||
|
name="connectionExpiry"
|
||||||
|
label=${msg("Connection expiry")}
|
||||||
|
required
|
||||||
|
value="${provider?.connectionExpiry ?? "hours=8"}"
|
||||||
|
help=${msg(
|
||||||
|
"Determines how long a session lasts before being disconnected and requiring re-authorization.",
|
||||||
|
)}
|
||||||
|
required
|
||||||
|
></ak-text-input>
|
||||||
|
|
||||||
|
<ak-form-group .expanded=${true}>
|
||||||
|
<span slot="header"> ${msg("Protocol settings")} </span>
|
||||||
|
<div slot="body" class="pf-c-form">
|
||||||
|
<ak-form-element-horizontal
|
||||||
|
label=${msg("Property mappings")}
|
||||||
|
?required=${true}
|
||||||
|
name="propertyMappings"
|
||||||
|
>
|
||||||
|
<select class="pf-c-form-control" multiple>
|
||||||
|
${this.propertyMappings?.results.map(
|
||||||
|
(mapping) =>
|
||||||
|
html`<option
|
||||||
|
value=${ifDefined(mapping.pk)}
|
||||||
|
?selected=${selected.has(mapping.pk)}
|
||||||
|
>
|
||||||
|
${mapping.name}
|
||||||
|
</option>`,
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
<p class="pf-c-form__helper-text">
|
||||||
|
${msg("Hold control/command to select multiple items.")}
|
||||||
|
</p>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
|
<ak-form-element-horizontal label=${msg("Settings")} name="settings">
|
||||||
|
<ak-codemirror
|
||||||
|
mode="yaml"
|
||||||
|
value="${YAML.stringify(provider?.settings ?? {})}"
|
||||||
|
>
|
||||||
|
</ak-codemirror>
|
||||||
|
<p class="pf-c-form__helper-text">${msg("Connection settings.")}</p>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
|
</div>
|
||||||
|
</ak-form-group>
|
||||||
|
</form>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ApplicationWizardAuthenticationByRAC;
|
|
@ -6,6 +6,7 @@ import {
|
||||||
type OAuth2ProviderRequest,
|
type OAuth2ProviderRequest,
|
||||||
type ProvidersSamlImportMetadataCreateRequest,
|
type ProvidersSamlImportMetadataCreateRequest,
|
||||||
type ProxyProviderRequest,
|
type ProxyProviderRequest,
|
||||||
|
type RACProviderRequest,
|
||||||
type RadiusProviderRequest,
|
type RadiusProviderRequest,
|
||||||
type SAMLProviderRequest,
|
type SAMLProviderRequest,
|
||||||
type SCIMProviderRequest,
|
type SCIMProviderRequest,
|
||||||
|
@ -16,6 +17,7 @@ export type OneOfProvider =
|
||||||
| Partial<SCIMProviderRequest>
|
| Partial<SCIMProviderRequest>
|
||||||
| Partial<SAMLProviderRequest>
|
| Partial<SAMLProviderRequest>
|
||||||
| Partial<ProvidersSamlImportMetadataCreateRequest>
|
| Partial<ProvidersSamlImportMetadataCreateRequest>
|
||||||
|
| Partial<RACProviderRequest>
|
||||||
| Partial<RadiusProviderRequest>
|
| Partial<RadiusProviderRequest>
|
||||||
| Partial<ProxyProviderRequest>
|
| Partial<ProxyProviderRequest>
|
||||||
| Partial<OAuth2ProviderRequest>
|
| Partial<OAuth2ProviderRequest>
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
|
import "@goauthentik/elements/Alert";
|
||||||
|
import { AKElement } from "@goauthentik/elements/Base";
|
||||||
|
|
||||||
|
import { msg } from "@lit/localize";
|
||||||
|
import { html, nothing } from "lit";
|
||||||
|
import { customElement, state } from "lit/decorators.js";
|
||||||
|
|
||||||
|
import { EnterpriseApi } from "@goauthentik/api";
|
||||||
|
|
||||||
|
@customElement("ak-license-notice")
|
||||||
|
export class AkLicenceNotice extends AKElement {
|
||||||
|
@state()
|
||||||
|
hasLicense = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
console.log("Notice constructed");
|
||||||
|
super();
|
||||||
|
new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseSummaryRetrieve().then((enterprise) => {
|
||||||
|
this.hasLicense = enterprise.hasLicense;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.log(this.hasLicense);
|
||||||
|
return this.hasLicense
|
||||||
|
? nothing
|
||||||
|
: html`
|
||||||
|
<ak-alert class="pf-c-radio__description" inline>
|
||||||
|
${msg("Provider requires enterprise.")}
|
||||||
|
<a href="#/enterprise/licenses">${msg("Learn more")}</a>
|
||||||
|
</ak-alert>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "@goauthentik/admin/common/ak-license-notice";
|
||||||
import "@goauthentik/admin/providers/ldap/LDAPProviderForm";
|
import "@goauthentik/admin/providers/ldap/LDAPProviderForm";
|
||||||
import "@goauthentik/admin/providers/oauth2/OAuth2ProviderForm";
|
import "@goauthentik/admin/providers/oauth2/OAuth2ProviderForm";
|
||||||
import "@goauthentik/admin/providers/proxy/ProxyProviderForm";
|
import "@goauthentik/admin/providers/proxy/ProxyProviderForm";
|
||||||
|
@ -86,15 +87,12 @@ export class InitialProviderWizardPage extends WizardPage {
|
||||||
?disabled=${type.requiresEnterprise ? !this.enterprise?.hasLicense : false}
|
?disabled=${type.requiresEnterprise ? !this.enterprise?.hasLicense : false}
|
||||||
/>
|
/>
|
||||||
<label class="pf-c-radio__label" for=${type.component}>${type.name}</label>
|
<label class="pf-c-radio__label" for=${type.component}>${type.name}</label>
|
||||||
<span class="pf-c-radio__description">${type.description}</span>
|
<span class="pf-c-radio__description"
|
||||||
${type.requiresEnterprise && !this.enterprise?.hasLicense
|
>${type.description}
|
||||||
? html`
|
${type.requiresEnterprise
|
||||||
<ak-alert class="pf-c-radio__description" ?inline=${true}>
|
? html`<ak-license-notice></ak-license-notice>`
|
||||||
${msg("Provider require enterprise.")}
|
|
||||||
<a href="#/enterprise/licenses">${msg("Learn more")}</a>
|
|
||||||
</ak-alert>
|
|
||||||
`
|
|
||||||
: nothing}
|
: nothing}
|
||||||
|
</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
})}
|
})}
|
||||||
</form>`;
|
</form>`;
|
||||||
|
|
Reference in New Issue