From 66fa4e30856d7c5b13588b97e968c68e32c94b30 Mon Sep 17 00:00:00 2001 From: Ken Sternberg Date: Fri, 12 Jan 2024 10:21:02 -0800 Subject: [PATCH] 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. --- ...rd-authentication-method-choice.choices.ts | 23 ++++ ...ion-wizard-authentication-method-choice.ts | 6 +- ...pplication-wizard-authentication-by-rac.ts | 128 ++++++++++++++++++ web/src/admin/applications/wizard/types.ts | 2 + web/src/admin/common/ak-license-notice.ts | 35 +++++ web/src/admin/providers/ProviderWizard.ts | 16 +-- 6 files changed, 199 insertions(+), 11 deletions(-) create mode 100644 web/src/admin/applications/wizard/methods/rac/ak-application-wizard-authentication-by-rac.ts create mode 100644 web/src/admin/common/ak-license-notice.ts diff --git a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.choices.ts b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.choices.ts index 2c0442915..d0e2c4d0c 100644 --- a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.choices.ts +++ b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.choices.ts @@ -1,3 +1,5 @@ +import "@goauthentik/admin/common/ak-license-notice"; + import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -8,6 +10,7 @@ import type { ModelRequest, OAuth2ProviderRequest, ProxyProviderRequest, + RACProviderRequest, RadiusProviderRequest, SAMLProviderRequest, SCIMProviderRequest, @@ -19,6 +22,9 @@ type ProviderRenderer = () => TemplateResult; 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. */ @@ -30,12 +36,14 @@ type ProviderType = [ ProviderRenderer, // Function that returns the provider's wizard panel as a TemplateResult 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 + ProviderNote?, ]; export type LocalTypeCreate = TypeCreate & { formName: string; modelName: ProviderModelEnumType; converter: ModelConverter; + note?: ProviderNote; }; // prettier-ignore @@ -103,6 +111,19 @@ const _providerModelsTable: ProviderType[] = [ mode: ProxyMode.ForwardDomain, }), ], + [ + "racprovider", + msg("Remote Access Provider"), + msg("Remotely access computers/servers via RDP/SSH/VNC"), + () => + html``, + ProviderModelEnum.RacRacprovider, + (provider: OneOfProvider) => ({ + providerModel: ProviderModelEnum.RacRacprovider, + ...(provider as RACProviderRequest), + }), + () => html`` + ], [ "samlprovider", msg("SAML (Security Assertion Markup Language)"), @@ -148,6 +169,7 @@ function mapProviders([ _, modelName, converter, + note, ]: ProviderType): LocalTypeCreate { return { formName, @@ -156,6 +178,7 @@ function mapProviders([ component: "", modelName, converter, + note, }; } diff --git a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts index e13e11eca..08cb7693d 100644 --- a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts +++ b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts @@ -7,7 +7,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement"; import { msg } from "@lit/localize"; 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 BasePanel from "../BasePanel"; @@ -48,7 +48,9 @@ export class ApplicationWizardAuthenticationMethodChoice extends BasePanel { @change=${this.handleChoice} /> - ${type.description} + ${type.description}${type.note ? type.note() : nothing} `; } diff --git a/web/src/admin/applications/wizard/methods/rac/ak-application-wizard-authentication-by-rac.ts b/web/src/admin/applications/wizard/methods/rac/ak-application-wizard-authentication-by-rac.ts new file mode 100644 index 000000000..e9c26cf31 --- /dev/null +++ b/web/src/admin/applications/wizard/methods/rac/ak-application-wizard-authentication-by-rac.ts @@ -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`${msg("Configure Remote Access Provider Provider")} +
+ + + + +

+ ${msg("Flow used when authorizing this provider.")} +

+
+ + + + + ${msg("Protocol settings")} +
+ + +

+ ${msg("Hold control/command to select multiple items.")} +

+
+ + + +

${msg("Connection settings.")}

+
+
+
+
`; + } +} + +export default ApplicationWizardAuthenticationByRAC; diff --git a/web/src/admin/applications/wizard/types.ts b/web/src/admin/applications/wizard/types.ts index a6e86cac1..d36340c87 100644 --- a/web/src/admin/applications/wizard/types.ts +++ b/web/src/admin/applications/wizard/types.ts @@ -6,6 +6,7 @@ import { type OAuth2ProviderRequest, type ProvidersSamlImportMetadataCreateRequest, type ProxyProviderRequest, + type RACProviderRequest, type RadiusProviderRequest, type SAMLProviderRequest, type SCIMProviderRequest, @@ -16,6 +17,7 @@ export type OneOfProvider = | Partial | Partial | Partial + | Partial | Partial | Partial | Partial diff --git a/web/src/admin/common/ak-license-notice.ts b/web/src/admin/common/ak-license-notice.ts new file mode 100644 index 000000000..b180179d2 --- /dev/null +++ b/web/src/admin/common/ak-license-notice.ts @@ -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` + + ${msg("Provider requires enterprise.")} + ${msg("Learn more")} + + `; + } +} diff --git a/web/src/admin/providers/ProviderWizard.ts b/web/src/admin/providers/ProviderWizard.ts index 7f19b4d02..094c784a5 100644 --- a/web/src/admin/providers/ProviderWizard.ts +++ b/web/src/admin/providers/ProviderWizard.ts @@ -1,3 +1,4 @@ +import "@goauthentik/admin/common/ak-license-notice"; import "@goauthentik/admin/providers/ldap/LDAPProviderForm"; import "@goauthentik/admin/providers/oauth2/OAuth2ProviderForm"; import "@goauthentik/admin/providers/proxy/ProxyProviderForm"; @@ -86,15 +87,12 @@ export class InitialProviderWizardPage extends WizardPage { ?disabled=${type.requiresEnterprise ? !this.enterprise?.hasLicense : false} /> - ${type.description} - ${type.requiresEnterprise && !this.enterprise?.hasLicense - ? html` - - ${msg("Provider require enterprise.")} - ${msg("Learn more")} - - ` - : nothing} + ${type.description} + ${type.requiresEnterprise + ? html`` + : nothing} + `; })} `;