import "@goauthentik/admin/enterprise/EnterpriseLicenseForm"; import "@goauthentik/admin/enterprise/EnterpriseStatusCard"; import "@goauthentik/admin/rbac/ObjectPermissionModal"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { formatElapsedTime } from "@goauthentik/common/temporal"; import { PFColor } from "@goauthentik/elements/Label"; import "@goauthentik/elements/Spinner"; import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/cards/AggregateCard"; import "@goauthentik/elements/forms/DeleteBulkForm"; import "@goauthentik/elements/forms/ModalForm"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table"; import { TablePage } from "@goauthentik/elements/table/TablePage"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg, str } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; import { customElement, property, state } from "lit/decorators.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 PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; import { EnterpriseApi, License, LicenseForecast, LicenseSummary, LicenseSummaryStatusEnum, RbacPermissionsAssignedByUsersListModelEnum, } from "@goauthentik/api"; @customElement("ak-enterprise-license-list") export class EnterpriseLicenseListPage extends TablePage { checkbox = true; clearOnRefresh = true; searchEnabled(): boolean { return true; } pageTitle(): string { return msg("Licenses"); } pageDescription(): string { return msg("Manage enterprise licenses"); } pageIcon(): string { return "pf-icon pf-icon-key"; } @property() order = "name"; @state() forecast?: LicenseForecast; @state() summary?: LicenseSummary; @state() installID?: string; static get styles(): CSSResult[] { return super.styles.concat( PFGrid, PFBanner, PFFormControl, PFButton, PFCard, css` .pf-m-no-padding-bottom { padding-bottom: 0; } .install-id { word-break: break-all; } `, ); } async apiEndpoint(): Promise> { this.forecast = await new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseForecastRetrieve(); this.summary = await new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseSummaryRetrieve({ cached: false, }); this.installID = ( await new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseInstallIdRetrieve() ).installId; return new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseList( await this.defaultEndpointConfig(), ); } columns(): TableColumn[] { return [ new TableColumn(msg("Name"), "name"), new TableColumn(msg("Users")), new TableColumn(msg("Expiry date")), new TableColumn(msg("Actions")), ]; } // TODO: Make this more generic, maybe automatically get the plural name // of the object to use in the renderEmpty renderEmpty(inner?: TemplateResult): TemplateResult { return super.renderEmpty(html` ${inner ? inner : html`${msg("No licenses found.")}
${this.searchEnabled() ? this.renderEmptyClearSearch() : html``}
${this.renderObjectCreate()}
`} `); } renderToolbarSelected(): TemplateResult { const disabled = this.selectedElements.length < 1; return html` { return [ { key: msg("Name"), value: item.name }, { key: msg("Expiry"), value: item.expiry?.toLocaleString() }, ]; }} .usedBy=${(item: License) => { return new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseUsedByList({ licenseUuid: item.licenseUuid, }); }} .delete=${(item: License) => { return new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseDestroy({ licenseUuid: item.licenseUuid, }); }} > `; } renderSectionBefore(): TemplateResult { return html`
${this.renderGetLicenseCard()} ~ ${(this.forecast?.internalUsers || 0) + (this.forecast?.forecastedInternalUsers || 0)} ~ ${(this.forecast?.externalUsers || 0) + (this.forecast?.forecastedExternalUsers || 0)} ${this.summary && this.summary?.status !== LicenseSummaryStatusEnum.Unlicensed ? html`
${formatElapsedTime(this.summary.latestValid)}
${this.summary.latestValid.toLocaleString()}` : "-"}
`; } row(item: License): TemplateResult[] { let color = PFColor.Green; if (item.expiry) { const now = new Date(); const inAMonth = new Date(); inAMonth.setDate(inAMonth.getDate() + 30); if (item.expiry <= inAMonth) { color = PFColor.Orange; } if (item.expiry <= now) { color = PFColor.Red; } } return [ html`
${item.name}
`, html`
${msg(str`Internal: ${item.internalUsers}`)}
${msg(str`External: ${item.externalUsers}`)}
`, html` ${item.expiry?.toLocaleString()} `, html` ${msg("Update")} ${msg("Update License")} `, ]; } renderGetLicenseCard() { const renderSpinner = () => html`
`; const installURL = (installID: string) => [ "https://customers.goauthentik.io/from_authentik/purchase/?install_id=", encodeURIComponent(installID), "&authentik_url=", encodeURI(window.location.origin), ].join(""); const renderCard = (installID: string) => html`
${msg("Your Install ID")}
${installID}
`; return html`
${this.installID ? renderCard(this.installID) : renderSpinner()}
`; } renderObjectCreate(): TemplateResult { return html` ${msg("Install")} ${msg("Install License")} `; } } declare global { interface HTMLElementTagNameMap { "ak-enterprise-license-list": EnterpriseLicenseListPage; } }