Skip to content

Commit

Permalink
make policy bindings form and list more customizable
Browse files Browse the repository at this point in the history
Signed-off-by: Jens Langhammer <[email protected]>
  • Loading branch information
BeryJu committed Nov 25, 2024
1 parent 480b7d4 commit 24eb2ae
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import { customElement, property } from "lit/decorators.js";

import PFContent from "@patternfly/patternfly/components/Content/content.css";

import {
ApplicationEntitlement,
CoreApi,
} from "@goauthentik/api";
import { ApplicationEntitlement, CoreApi } from "@goauthentik/api";

@customElement("ak-application-entitlement-form")
export class ApplicationEntitlementForm extends ModelForm<ApplicationEntitlement, string> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import "@goauthentik/admin/applications/entitlements/ApplicationEntitlementForm";
import "@goauthentik/admin/groups/GroupForm";
import "@goauthentik/admin/policies/BoundPoliciesList";
import { PolicyBindingCheckTarget } from "@goauthentik/admin/policies/utils";
import "@goauthentik/admin/users/UserForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { PFSize } from "@goauthentik/common/enums";
Expand Down Expand Up @@ -67,20 +68,20 @@ export class ApplicationEntitlementsPage extends Table<ApplicationEntitlement> {
return [
html`${item.name}`,
html`<ak-forms-modal size=${PFSize.Medium}>
<span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${msg("Update Entitlement")} </span>
<ak-application-entitlement-form
slot="form"
.instancePk=${item.pbmUuid}
targetPk=${ifDefined(this.app)}
>
</ak-application-entitlement-form>
<button slot="trigger" class="pf-c-button pf-m-plain">
<pf-tooltip position="top" content=${msg("Edit")}>
<i class="fas fa-edit"></i>
</pf-tooltip>
</button>
</ak-forms-modal>`,
<span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${msg("Update Entitlement")} </span>
<ak-application-entitlement-form
slot="form"
.instancePk=${item.pbmUuid}
targetPk=${ifDefined(this.app)}
>
</ak-application-entitlement-form>
<button slot="trigger" class="pf-c-button pf-m-plain">
<pf-tooltip position="top" content=${msg("Edit")}>
<i class="fas fa-edit"></i>
</pf-tooltip>
</button>
</ak-forms-modal>`,
];
}

Expand All @@ -94,7 +95,14 @@ export class ApplicationEntitlementsPage extends Table<ApplicationEntitlement> {
"These bindings control which users have access to this entitlement.",
)}
</p>
<ak-bound-policies-list .target=${item.pbmUuid}> </ak-bound-policies-list>
<ak-bound-policies-list
.target=${item.pbmUuid}
.allowedTypes=${[
PolicyBindingCheckTarget.group,
PolicyBindingCheckTarget.user,
]}
>
</ak-bound-policies-list>
</div>
</div>
</td>`;
Expand Down
49 changes: 35 additions & 14 deletions web/src/admin/policies/BoundPoliciesList.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import "@goauthentik/admin/groups/GroupForm";
import "@goauthentik/admin/policies/PolicyBindingForm";
import { PolicyBindingNotice } from "@goauthentik/admin/policies/PolicyBindingForm";
import "@goauthentik/admin/policies/PolicyWizard";
import {
PolicyBindingCheckTarget,
PolicyBindingCheckTargetToLabel,
} from "@goauthentik/admin/policies/utils";
import "@goauthentik/admin/users/UserForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { PFSize } from "@goauthentik/common/enums.js";
Expand All @@ -13,7 +18,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { Table, TableColumn } from "@goauthentik/elements/table/Table";

import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { TemplateResult, html, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";

Expand All @@ -24,14 +29,25 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
@property()
target?: string;

@property({ type: Boolean })
policyOnly = false;
@property({ type: Array })
allowedTypes: PolicyBindingCheckTarget[] = [
PolicyBindingCheckTarget.group,
PolicyBindingCheckTarget.user,
PolicyBindingCheckTarget.policy,
];

@property({ type: Array })
typeNotices: PolicyBindingNotice[] = [];

checkbox = true;
clearOnRefresh = true;

order = "order";

get allowedTypesLabel(): string {
return this.allowedTypes.map((ct) => PolicyBindingCheckTargetToLabel(ct)).join(" / ");
}

async apiEndpoint(): Promise<PaginatedResponse<PolicyBinding>> {
return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsList({
...(await this.defaultEndpointConfig()),
Expand All @@ -42,7 +58,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
columns(): TableColumn[] {
return [
new TableColumn(msg("Order"), "order"),
new TableColumn(msg("Policy / User / Group")),
new TableColumn(this.allowedTypesLabel),
new TableColumn(msg("Enabled"), "enabled"),
new TableColumn(msg("Timeout"), "timeout"),
new TableColumn(msg("Actions")),
Expand Down Expand Up @@ -121,7 +137,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
return [
{ key: msg("Order"), value: item.order.toString() },
{
key: msg("Policy / User / Group"),
key: this.allowedTypesLabel,
value: this.getPolicyUserGroupRowLabel(item),
},
];
Expand Down Expand Up @@ -156,8 +172,9 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
<ak-policy-binding-form
slot="form"
.instancePk=${item.pk}
.allowedTypes=${this.allowedTypes}
.typeNotices=${this.typeNotices}
targetPk=${ifDefined(this.target)}
?policyOnly=${this.policyOnly}
>
</ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-secondary">
Expand All @@ -183,7 +200,8 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
<ak-policy-binding-form
slot="form"
targetPk=${ifDefined(this.target)}
?policyOnly=${this.policyOnly}
.allowedTypes=${this.allowedTypes}
.typeNotices=${this.typeNotices}
>
</ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
Expand All @@ -196,22 +214,25 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
}

renderToolbar(): TemplateResult {
return html`<ak-policy-wizard
createText=${msg("Create and bind Policy")}
?showBindingPage=${true}
bindingTarget=${ifDefined(this.target)}
></ak-policy-wizard>
return html`${this.allowedTypes.includes(PolicyBindingCheckTarget.policy)
? html`<ak-policy-wizard
createText=${msg("Create and bind Policy")}
?showBindingPage=${true}
bindingTarget=${ifDefined(this.target)}
></ak-policy-wizard>`
: nothing}
<ak-forms-modal size=${PFSize.Medium}>
<span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${msg("Create Binding")} </span>
<ak-policy-binding-form
slot="form"
targetPk=${ifDefined(this.target)}
?policyOnly=${this.policyOnly}
.allowedTypes=${this.allowedTypes}
.typeNotices=${this.typeNotices}
>
</ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${msg("Bind existing policy/group/user")}
${msg(str`Bind existing ${this.allowedTypesLabel}`)}
</button>
</ak-forms-modal> `;
}
Expand Down
91 changes: 55 additions & 36 deletions web/src/admin/policies/PolicyBindingForm.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
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";
Expand All @@ -7,7 +11,7 @@ import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect";

import { msg } from "@lit/localize";
import { CSSResult } from "lit";
import { CSSResult, nothing } from "lit";
import { TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";

Expand All @@ -25,11 +29,7 @@ import {
User,
} from "@goauthentik/api";

enum target {
policy = "policy",
group = "group",
user = "user",
}
export type PolicyBindingNotice = { type: PolicyBindingCheckTarget; notice: string };

@customElement("ak-policy-binding-form")
export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
Expand All @@ -38,13 +38,13 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
policyBindingUuid: pk,
});
if (binding?.policyObj) {
this.policyGroupUser = target.policy;
this.policyGroupUser = PolicyBindingCheckTarget.policy;
}
if (binding?.groupObj) {
this.policyGroupUser = target.group;
this.policyGroupUser = PolicyBindingCheckTarget.group;
}
if (binding?.userObj) {
this.policyGroupUser = target.user;
this.policyGroupUser = PolicyBindingCheckTarget.user;
}
this.defaultOrder = await this.getOrder();
return binding;
Expand All @@ -54,10 +54,17 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
targetPk?: string;

@state()
policyGroupUser: target = target.policy;
policyGroupUser: PolicyBindingCheckTarget = PolicyBindingCheckTarget.policy;

@property({ type: Array })
allowedTypes: PolicyBindingCheckTarget[] = [
PolicyBindingCheckTarget.group,
PolicyBindingCheckTarget.user,
PolicyBindingCheckTarget.policy,
];

@property({ type: Boolean })
policyOnly = false;
@property({ type: Array })
typeNotices: PolicyBindingNotice[] = [];

@state()
defaultOrder = 0;
Expand All @@ -74,20 +81,26 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
return [...super.styles, PFContent];
}

async load(): Promise<void> {
// 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<unknown> {
if (this.targetPk) {
data.target = this.targetPk;
}
switch (this.policyGroupUser) {
case target.policy:
case PolicyBindingCheckTarget.policy:
data.user = null;
data.group = null;
break;
case target.group:
case PolicyBindingCheckTarget.group:
data.policy = null;
data.user = null;
break;
case target.user:
case PolicyBindingCheckTarget.user:
data.policy = null;
data.group = null;
break;
Expand Down Expand Up @@ -122,13 +135,18 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
renderModeSelector(): TemplateResult {
return html` <ak-toggle-group
value=${this.policyGroupUser}
@ak-toggle=${(ev: CustomEvent<{ value: target }>) => {
@ak-toggle=${(ev: CustomEvent<{ value: PolicyBindingCheckTarget }>) => {
this.policyGroupUser = ev.detail.value;
}}
>
<option value=${target.policy}>${msg("Policy")}</option>
<option value=${target.group}>${msg("Group")}</option>
<option value=${target.user}>${msg("User")}</option>
${Object.keys(PolicyBindingCheckTarget).map((ct) => {
if (this.allowedTypes.includes(ct as PolicyBindingCheckTarget)) {
return html`<option value=${ct}>
${PolicyBindingCheckTargetToLabel(ct as PolicyBindingCheckTarget)}
</option>`;
}
return nothing;
})}
</ak-toggle-group>`;
}

Expand All @@ -139,7 +157,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<ak-form-element-horizontal
label=${msg("Policy")}
name="policy"
?hidden=${this.policyGroupUser !== target.policy}
?hidden=${this.policyGroupUser !== PolicyBindingCheckTarget.policy}
>
<ak-search-select
.groupBy=${(items: Policy[]) => {
Expand Down Expand Up @@ -169,11 +187,16 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
?blankable=${true}
>
</ak-search-select>
${this.typeNotices
.filter(({ type }) => type === PolicyBindingCheckTarget.policy)
.map((msg) => {
return html`<p class="pf-c-form__helper-text">${msg.notice}</p>`;
})}
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Group")}
name="group"
?hidden=${this.policyGroupUser !== target.group}
?hidden=${this.policyGroupUser !== PolicyBindingCheckTarget.group}
>
<ak-search-select
.fetchObjects=${async (query?: string): Promise<Group[]> => {
Expand Down Expand Up @@ -201,18 +224,16 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
?blankable=${true}
>
</ak-search-select>
${this.policyOnly
? html`<p class="pf-c-form__helper-text">
${msg(
"Group mappings can only be checked if a user is already logged in when trying to access this source.",
)}
</p>`
: html``}
${this.typeNotices
.filter(({ type }) => type === PolicyBindingCheckTarget.group)
.map((msg) => {
return html`<p class="pf-c-form__helper-text">${msg.notice}</p>`;
})}
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("User")}
name="user"
?hidden=${this.policyGroupUser !== target.user}
?hidden=${this.policyGroupUser !== PolicyBindingCheckTarget.user}
>
<ak-search-select
.fetchObjects=${async (query?: string): Promise<User[]> => {
Expand Down Expand Up @@ -240,13 +261,11 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
?blankable=${true}
>
</ak-search-select>
${this.policyOnly
? html`<p class="pf-c-form__helper-text">
${msg(
"User mappings can only be checked if a user is already logged in when trying to access this source.",
)}
</p>`
: html``}
${this.typeNotices
.filter(({ type }) => type === PolicyBindingCheckTarget.user)
.map((msg) => {
return html`<p class="pf-c-form__helper-text">${msg.notice}</p>`;
})}
</ak-form-element-horizontal>
</div>
</div>
Expand Down
Loading

0 comments on commit 24eb2ae

Please sign in to comment.