import { PolicyBindingCheckTarget, PolicyBindingCheckTargetToLabel, } from "@goauthentik/admin/policies/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { first, groupBy } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-toggle-group"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/SearchSelect"; import { msg } from "@lit/localize"; import { CSSResult, nothing } from "lit"; import { TemplateResult, html } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; import { CoreApi, CoreGroupsListRequest, CoreUsersListRequest, Group, PoliciesAllListRequest, PoliciesApi, Policy, PolicyBinding, User, } from "@goauthentik/api"; export type PolicyBindingNotice = { type: PolicyBindingCheckTarget; notice: string }; @customElement("ak-policy-binding-form") export class PolicyBindingForm extends ModelForm { async loadInstance(pk: string): Promise { const binding = await new PoliciesApi(DEFAULT_CONFIG).policiesBindingsRetrieve({ policyBindingUuid: pk, }); if (binding?.policyObj) { this.policyGroupUser = PolicyBindingCheckTarget.policy; } if (binding?.groupObj) { this.policyGroupUser = PolicyBindingCheckTarget.group; } if (binding?.userObj) { this.policyGroupUser = PolicyBindingCheckTarget.user; } this.defaultOrder = await this.getOrder(); return binding; } @property() targetPk?: string; @state() policyGroupUser: PolicyBindingCheckTarget = PolicyBindingCheckTarget.policy; @property({ type: Array }) allowedTypes: PolicyBindingCheckTarget[] = [ PolicyBindingCheckTarget.policy, PolicyBindingCheckTarget.group, PolicyBindingCheckTarget.user, ]; @property({ type: Array }) typeNotices: PolicyBindingNotice[] = []; @state() defaultOrder = 0; getSuccessMessage(): string { if (this.instance?.pk) { return msg("Successfully updated binding."); } else { return msg("Successfully created binding."); } } static get styles(): CSSResult[] { return [...super.styles, PFContent]; } async load(): Promise { // Overwrite the default for policyGroupUser with the first allowed type, // as this function is called when the correct parameters are set this.policyGroupUser = this.allowedTypes[0]; } send(data: PolicyBinding): Promise { if (this.targetPk) { data.target = this.targetPk; } switch (this.policyGroupUser) { case PolicyBindingCheckTarget.policy: data.user = null; data.group = null; break; case PolicyBindingCheckTarget.group: data.policy = null; data.user = null; break; case PolicyBindingCheckTarget.user: data.policy = null; data.group = null; break; } if (this.instance?.pk) { return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsUpdate({ policyBindingUuid: this.instance.pk, policyBindingRequest: data, }); } else { return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsCreate({ policyBindingRequest: data, }); } } async getOrder(): Promise { if (this.instance?.pk) { return this.instance.order; } const bindings = await new PoliciesApi(DEFAULT_CONFIG).policiesBindingsList({ target: this.targetPk || "", }); const orders = bindings.results.map((binding) => binding.order); if (orders.length < 1) { return 0; } return Math.max(...orders) + 1; } renderModeSelector(): TemplateResult { return html` ) => { this.policyGroupUser = ev.detail.value; }} > ${Object.keys(PolicyBindingCheckTarget).map((ct) => { if (this.allowedTypes.includes(ct as PolicyBindingCheckTarget)) { return html``; } return nothing; })} `; } renderForm(): TemplateResult { return html`
${this.renderModeSelector()}

${msg("Negates the outcome of the binding. Messages are unaffected.")}

${msg("Result used when policy execution fails.")}

`; } } declare global { interface HTMLElementTagNameMap { "ak-policy-binding-form": PolicyBindingForm; } }