From 7db3be604c7dc39a942ccce1808ebd7ca638fedd Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 10 Aug 2021 21:27:41 +0200 Subject: [PATCH] web/admin: allow modification of users groups from user view Signed-off-by: Jens Langhammer --- web/src/locales/en.po | 14 +++- web/src/locales/pseudo-LOCALE.po | 14 +++- web/src/pages/groups/GroupForm.ts | 5 +- web/src/pages/users/GroupSelectModal.ts | 85 +++++++++++++++++++++++++ web/src/pages/users/UserForm.ts | 65 ++++++++++++++++++- 5 files changed, 174 insertions(+), 9 deletions(-) create mode 100644 web/src/pages/users/GroupSelectModal.ts diff --git a/web/src/locales/en.po b/web/src/locales/en.po index 8e0de1eb2..bd9e88df5 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -134,6 +134,7 @@ msgid "Active" msgstr "Active" #: src/pages/groups/MemberSelectModal.ts +#: src/pages/users/GroupSelectModal.ts msgid "Add" msgstr "Add" @@ -515,6 +516,7 @@ msgstr "Can be in the format of 'unix://' when connecting to a local docker daem #: src/elements/forms/DeleteForm.ts #: src/elements/forms/ModalForm.ts #: src/pages/groups/MemberSelectModal.ts +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserActiveForm.ts msgid "Cancel" msgstr "Cancel" @@ -1814,6 +1816,7 @@ msgstr "Group {0}" #: src/interfaces/AdminInterface.ts #: src/pages/admin-overview/AdminOverviewPage.ts #: src/pages/groups/GroupListPage.ts +#: src/pages/users/UserForm.ts msgid "Groups" msgstr "Groups" @@ -1858,7 +1861,6 @@ msgid "Hide service-accounts" msgstr "Hide service-accounts" #: src/pages/events/RuleForm.ts -#: src/pages/groups/GroupForm.ts #: src/pages/outposts/OutpostForm.ts #: src/pages/providers/oauth2/OAuth2ProviderForm.ts #: src/pages/providers/saml/SAMLProviderForm.ts @@ -2246,6 +2248,7 @@ msgstr "Loading" #: src/pages/tenants/TenantForm.ts #: src/pages/tenants/TenantForm.ts #: src/pages/tenants/TenantForm.ts +#: src/pages/users/UserForm.ts #: src/pages/users/UserResetEmailForm.ts msgid "Loading..." msgstr "Loading..." @@ -2335,6 +2338,7 @@ msgstr "Maximum age (in days)" #: src/pages/groups/GroupForm.ts #: src/pages/groups/GroupListPage.ts +#: src/pages/users/GroupSelectModal.ts msgid "Members" msgstr "Members" @@ -2474,6 +2478,7 @@ msgstr "My Applications" #: src/pages/stages/user_logout/UserLogoutStageForm.ts #: src/pages/stages/user_write/UserWriteStageForm.ts #: src/pages/user-settings/UserSelfForm.ts +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserForm.ts #: src/pages/users/UserListPage.ts #: src/pages/users/UserViewPage.ts @@ -2520,6 +2525,7 @@ msgstr "New version available!" #: src/pages/tenants/TenantListPage.ts #: src/pages/tokens/TokenListPage.ts #: src/pages/user-settings/tokens/UserTokenList.ts +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserListPage.ts msgid "No" msgstr "No" @@ -3367,6 +3373,10 @@ msgstr "Select an enrollment flow" msgid "Select an identification method." msgstr "Select an identification method." +#: src/pages/users/GroupSelectModal.ts +msgid "Select groups to add user to" +msgstr "Select groups to add user to" + #: src/flows/stages/identification/IdentificationStage.ts msgid "Select one of the sources below to login." msgstr "Select one of the sources below to login." @@ -3986,6 +3996,7 @@ msgstr "Successfully updated user." msgid "Successfully updated {0} {1}" msgstr "Successfully updated {0} {1}" +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserListPage.ts #: src/pages/users/UserViewPage.ts msgid "Superuser" @@ -4870,6 +4881,7 @@ msgstr "X509 Subject" #: src/pages/tenants/TenantListPage.ts #: src/pages/tokens/TokenListPage.ts #: src/pages/user-settings/tokens/UserTokenList.ts +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserListPage.ts msgid "Yes" msgstr "Yes" diff --git a/web/src/locales/pseudo-LOCALE.po b/web/src/locales/pseudo-LOCALE.po index 1d9134d36..be7f53902 100644 --- a/web/src/locales/pseudo-LOCALE.po +++ b/web/src/locales/pseudo-LOCALE.po @@ -134,6 +134,7 @@ msgid "Active" msgstr "" #: src/pages/groups/MemberSelectModal.ts +#: src/pages/users/GroupSelectModal.ts msgid "Add" msgstr "" @@ -511,6 +512,7 @@ msgstr "" #: src/elements/forms/DeleteForm.ts #: src/elements/forms/ModalForm.ts #: src/pages/groups/MemberSelectModal.ts +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserActiveForm.ts msgid "Cancel" msgstr "" @@ -1806,6 +1808,7 @@ msgstr "" #: src/interfaces/AdminInterface.ts #: src/pages/admin-overview/AdminOverviewPage.ts #: src/pages/groups/GroupListPage.ts +#: src/pages/users/UserForm.ts msgid "Groups" msgstr "" @@ -1850,7 +1853,6 @@ msgid "Hide service-accounts" msgstr "" #: src/pages/events/RuleForm.ts -#: src/pages/groups/GroupForm.ts #: src/pages/outposts/OutpostForm.ts #: src/pages/providers/oauth2/OAuth2ProviderForm.ts #: src/pages/providers/saml/SAMLProviderForm.ts @@ -2238,6 +2240,7 @@ msgstr "" #: src/pages/tenants/TenantForm.ts #: src/pages/tenants/TenantForm.ts #: src/pages/tenants/TenantForm.ts +#: src/pages/users/UserForm.ts #: src/pages/users/UserResetEmailForm.ts msgid "Loading..." msgstr "" @@ -2327,6 +2330,7 @@ msgstr "" #: src/pages/groups/GroupForm.ts #: src/pages/groups/GroupListPage.ts +#: src/pages/users/GroupSelectModal.ts msgid "Members" msgstr "" @@ -2466,6 +2470,7 @@ msgstr "" #: src/pages/stages/user_logout/UserLogoutStageForm.ts #: src/pages/stages/user_write/UserWriteStageForm.ts #: src/pages/user-settings/UserSelfForm.ts +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserForm.ts #: src/pages/users/UserListPage.ts #: src/pages/users/UserViewPage.ts @@ -2512,6 +2517,7 @@ msgstr "" #: src/pages/tenants/TenantListPage.ts #: src/pages/tokens/TokenListPage.ts #: src/pages/user-settings/tokens/UserTokenList.ts +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserListPage.ts msgid "No" msgstr "" @@ -3359,6 +3365,10 @@ msgstr "" msgid "Select an identification method." msgstr "" +#: src/pages/users/GroupSelectModal.ts +msgid "Select groups to add user to" +msgstr "" + #: src/flows/stages/identification/IdentificationStage.ts msgid "Select one of the sources below to login." msgstr "" @@ -3978,6 +3988,7 @@ msgstr "" msgid "Successfully updated {0} {1}" msgstr "" +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserListPage.ts #: src/pages/users/UserViewPage.ts msgid "Superuser" @@ -4853,6 +4864,7 @@ msgstr "" #: src/pages/tenants/TenantListPage.ts #: src/pages/tokens/TokenListPage.ts #: src/pages/user-settings/tokens/UserTokenList.ts +#: src/pages/users/GroupSelectModal.ts #: src/pages/users/UserListPage.ts msgid "Yes" msgstr "" diff --git a/web/src/pages/groups/GroupForm.ts b/web/src/pages/groups/GroupForm.ts index f34df4057..5b90a8c28 100644 --- a/web/src/pages/groups/GroupForm.ts +++ b/web/src/pages/groups/GroupForm.ts @@ -33,7 +33,7 @@ export class GroupForm extends ModelForm { send = (data: Group): Promise => { if (this.instance?.pk) { return new CoreApi(DEFAULT_CONFIG).coreGroupsUpdate({ - groupUuid: this.instance.pk || "", + groupUuid: this.instance.pk, groupRequest: data, }); } else { @@ -143,9 +143,6 @@ export class GroupForm extends ModelForm { -

- ${t`Hold control/command to select multiple items.`} -

{ + checkbox = true; + checkboxChip = true; + + searchEnabled(): boolean { + return true; + } + + @property() + confirm!: (selectedItems: Group[]) => Promise; + + order = "name"; + + apiEndpoint(page: number): Promise> { + return new CoreApi(DEFAULT_CONFIG).coreGroupsList({ + ordering: this.order, + page: page, + pageSize: PAGE_SIZE / 2, + search: this.search || "", + }); + } + + columns(): TableColumn[] { + return [ + new TableColumn(t`Name`, "username"), + new TableColumn(t`Superuser`, "is_superuser"), + new TableColumn(t`Members`, ""), + ]; + } + + row(item: Group): TemplateResult[] { + return [ + html`
+
${item.name}
+
`, + html`${item.isSuperuser ? t`Yes` : t`No`}`, + html`${item.users.length}`, + ]; + } + + renderSelectedChip(item: Group): TemplateResult { + return html`${item.name}`; + } + + renderModalInner(): TemplateResult { + return html`
+
+

${t`Select groups to add user to`}

+
+
+
${this.renderTable()}
+
+ { + return this.confirm(this.selectedElements).then(() => { + this.open = false; + }); + }} + class="pf-m-primary" + > + ${t`Add`}   + { + this.open = false; + }} + class="pf-m-secondary" + > + ${t`Cancel`} + +
`; + } +} diff --git a/web/src/pages/users/UserForm.ts b/web/src/pages/users/UserForm.ts index 4ad479df9..99ca087d3 100644 --- a/web/src/pages/users/UserForm.ts +++ b/web/src/pages/users/UserForm.ts @@ -1,4 +1,4 @@ -import { CoreApi, User } from "authentik-api"; +import { CoreApi, Group, User } from "authentik-api"; import { t } from "@lingui/macro"; import { customElement } from "lit-element"; import { html, TemplateResult } from "lit-html"; @@ -6,9 +6,11 @@ import { DEFAULT_CONFIG } from "../../api/Config"; import { ifDefined } from "lit-html/directives/if-defined"; import "../../elements/forms/HorizontalFormElement"; import "../../elements/CodeMirror"; +import "./GroupSelectModal"; import YAML from "yaml"; import { first } from "../../utils"; import { ModelForm } from "../../elements/forms/ModelForm"; +import { until } from "lit-html/directives/until"; @customElement("ak-user-form") export class UserForm extends ModelForm { @@ -27,9 +29,9 @@ export class UserForm extends ModelForm { } send = (data: User): Promise => { - if (this.instance) { + if (this.instance?.pk) { return new CoreApi(DEFAULT_CONFIG).coreUsersUpdate({ - id: this.instance.pk || 0, + id: this.instance.pk, userRequest: data, }); } else { @@ -82,6 +84,63 @@ export class UserForm extends ModelForm { ${t`Designates whether this user should be treated as active. Unselect this instead of deleting accounts.`}

+ +
+ { + // Because the model only has the IDs, map the group list to IDs + const ids = items.map((g) => g.pk); + if (!this.instance) this.instance = {} as User; + this.instance.groups = Array.from(this.instance?.groups || []).concat( + ids, + ); + this.requestUpdate(); + return Promise.resolve(); + }} + > + + +
+ + ${until( + new CoreApi(DEFAULT_CONFIG) + .coreGroupsList({ + ordering: "name", + }) + .then((groups) => { + return groups.results.map((group) => { + const selected = Array.from( + this.instance?.groups || [], + ).some((sg) => { + return sg == group.pk; + }); + if (!selected) return; + return html` { + if (!this.instance) return; + const groups = Array.from( + this.instance?.groups || [], + ); + const idx = groups.indexOf(group.pk); + groups.splice(idx, 1); + this.instance.groups = groups; + this.requestUpdate(); + }} + > + ${group.name} + `; + }); + }), + html``, + )} + +
+
+