From 4f1c11c5ef36d956e6d4fa304b419dc3b1a21881 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 3 Aug 2021 22:40:13 +0200 Subject: [PATCH 1/8] providers/saml: add WantAssertionsSigned Signed-off-by: Jens Langhammer # Conflicts: # authentik/providers/saml/processors/metadata_parser.py --- .../providers/saml/processors/metadata_parser.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/authentik/providers/saml/processors/metadata_parser.py b/authentik/providers/saml/processors/metadata_parser.py index 8708a6c06..0009cd61c 100644 --- a/authentik/providers/saml/processors/metadata_parser.py +++ b/authentik/providers/saml/processors/metadata_parser.py @@ -134,10 +134,18 @@ class ServiceProviderMetadataParser: # For now we'll only look at the first descriptor. # Even if multiple descriptors exist, we can only configure one descriptor = sp_sso_descriptors[0] - auth_n_request_signed = ( - descriptor.attrib["AuthnRequestsSigned"].lower() == "true" - ) - assertion_signed = descriptor.attrib["WantAssertionsSigned"].lower() == "true" + + auth_n_request_signed = False + if "AuthnRequestsSigned" in descriptor.attrib: + auth_n_request_signed = ( + descriptor.attrib["AuthnRequestsSigned"].lower() == "true" + ) + + assertion_signed = False + if "WantAssertionsSigned" in descriptor.attrib: + assertion_signed = ( + descriptor.attrib["WantAssertionsSigned"].lower() == "true" + ) acs_services = descriptor.findall( f"{{{NS_SAML_METADATA}}}AssertionConsumerService" From aa4f7fb2b655a7e249c3202da157b291c189fac9 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 3 Aug 2021 22:40:56 +0200 Subject: [PATCH 2/8] providers/saml: fix error when PropertyMapping return value isn't string Signed-off-by: Jens Langhammer --- authentik/providers/saml/processors/assertion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authentik/providers/saml/processors/assertion.py b/authentik/providers/saml/processors/assertion.py index 765947ce7..f9e1e4d49 100644 --- a/authentik/providers/saml/processors/assertion.py +++ b/authentik/providers/saml/processors/assertion.py @@ -163,7 +163,7 @@ class AssertionProcessor: provider=self.provider, ) if value is not None: - name_id.text = value + name_id.text = str(value) return name_id except PropertyMappingExpressionException as exc: Event.new( From 66bb68a747daa9f4f613675f84aab6338a584e59 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Wed, 4 Aug 2021 21:37:13 +0200 Subject: [PATCH 3/8] lifecycle: decrease default worker count on compose Signed-off-by: Jens Langhammer --- lifecycle/gunicorn.conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lifecycle/gunicorn.conf.py b/lifecycle/gunicorn.conf.py index e03372481..211f78680 100644 --- a/lifecycle/gunicorn.conf.py +++ b/lifecycle/gunicorn.conf.py @@ -51,7 +51,8 @@ logconfig_dict = { if SERVICE_HOST_ENV_NAME in os.environ: workers = 2 else: - workers = int(os.environ.get("WORKERS", cpu_count() * 2 + 1)) + default_workers = max(cpu_count() * 0.25, 1) + 1 # Minimum of 2 workers + workers = int(os.environ.get("WORKERS", default_workers)) threads = 4 warnings.simplefilter("once") From 1cd59be8dcb89edcb737356810a428e1854a89ba Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 5 Aug 2021 14:43:16 +0200 Subject: [PATCH 4/8] web/admin: fix email being required Signed-off-by: Jens Langhammer # Conflicts: # web/src/pages/user-settings/UserDetailsPage.ts # web/src/pages/users/UserForm.ts --- web/src/pages/user-settings/UserDetailsPage.ts | 3 +-- web/src/pages/users/UserForm.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/web/src/pages/user-settings/UserDetailsPage.ts b/web/src/pages/user-settings/UserDetailsPage.ts index 6a2049cd7..a8ab30188 100644 --- a/web/src/pages/user-settings/UserDetailsPage.ts +++ b/web/src/pages/user-settings/UserDetailsPage.ts @@ -69,9 +69,8 @@ export class UserDetailsPage extends LitElement { - +
diff --git a/web/src/pages/users/UserForm.ts b/web/src/pages/users/UserForm.ts index 9cec630ed..065302e08 100644 --- a/web/src/pages/users/UserForm.ts +++ b/web/src/pages/users/UserForm.ts @@ -58,9 +58,8 @@ export class UserForm extends ModelForm { - + From 1b91543add0c3392a8dfeb1568016a5f1b2fee90 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 5 Aug 2021 17:38:48 +0200 Subject: [PATCH 5/8] core: add UserSelfSerializer and separate method for users to update themselves with limited fields rework user settings page to better use form closes #1227 Signed-off-by: Jens Langhammer # Conflicts: # authentik/core/api/users.py # web/src/elements/forms/ModelForm.ts # web/src/pages/user-settings/UserDetailsPage.ts # web/src/pages/user-settings/UserSettingsPage.ts --- .gitignore | 2 +- authentik/core/api/users.py | 59 ++++++++- lifecycle/gunicorn.conf.py | 2 +- schema.yml | 112 +++++++++++++++++- web/src/elements/forms/ModelForm.ts | 12 +- web/src/locales/en.po | 22 ++-- web/src/locales/pseudo-LOCALE.po | 22 ++-- .../pages/user-settings/UserDetailsPage.ts | 100 ---------------- web/src/pages/user-settings/UserSelfForm.ts | 100 ++++++++++++++++ .../pages/user-settings/UserSettingsPage.ts | 15 ++- 10 files changed, 307 insertions(+), 139 deletions(-) delete mode 100644 web/src/pages/user-settings/UserDetailsPage.ts create mode 100644 web/src/pages/user-settings/UserSelfForm.ts diff --git a/.gitignore b/.gitignore index 33d287ce7..a1c635a7a 100644 --- a/.gitignore +++ b/.gitignore @@ -200,4 +200,4 @@ media/ *mmdb .idea/ -api/ +/api/ diff --git a/authentik/core/api/users.py b/authentik/core/api/users.py index 6593fb937..f7a02e27b 100644 --- a/authentik/core/api/users.py +++ b/authentik/core/api/users.py @@ -10,6 +10,7 @@ from drf_spectacular.utils import extend_schema, extend_schema_field from guardian.utils import get_anonymous_user from rest_framework.decorators import action from rest_framework.fields import CharField, JSONField, SerializerMethodField +from rest_framework.permissions import IsAuthenticated from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import ( @@ -62,12 +63,40 @@ class UserSerializer(ModelSerializer): ] +class UserSelfSerializer(ModelSerializer): + """User Serializer for information a user can retrieve about themselves and + update about themselves""" + + is_superuser = BooleanField(read_only=True) + avatar = CharField(read_only=True) + groups = ListSerializer(child=GroupSerializer(), read_only=True, source="ak_groups") + uid = CharField(read_only=True) + + class Meta: + + model = User + fields = [ + "pk", + "username", + "name", + "is_active", + "is_superuser", + "groups", + "email", + "avatar", + "uid", + ] + extra_kwargs = { + "is_active": {"read_only": True}, + } + + class SessionUserSerializer(PassiveSerializer): """Response for the /user/me endpoint, returns the currently active user (as `user` property) and, if this user is being impersonated, the original user in the `original` property.""" - user = UserSerializer() - original = UserSerializer(required=False) + user = UserSelfSerializer() + original = UserSelfSerializer(required=False) class UserMetricsSerializer(PassiveSerializer): @@ -158,12 +187,36 @@ class UserViewSet(UsedByMixin, ModelViewSet): data={"user": UserSerializer(request.user).data} ) if SESSION_IMPERSONATE_USER in request._request.session: - serializer.initial_data["original"] = UserSerializer( + serializer.initial_data["original"] = UserSelfSerializer( request._request.session[SESSION_IMPERSONATE_ORIGINAL_USER] ).data serializer.is_valid() return Response(serializer.data) + @extend_schema( + request=UserSelfSerializer, responses={200: SessionUserSerializer(many=False)} + ) + @action( + methods=["PUT"], + detail=False, + pagination_class=None, + filter_backends=[], + permission_classes=[IsAuthenticated], + ) + def update_self(self, request: Request) -> Response: + """Allow users to change information on their own profile""" + data = UserSelfSerializer( + instance=User.objects.get(pk=request.user.pk), data=request.data + ) + if not data.is_valid(): + return Response(data.errors) + new_user = data.save() + # If we're impersonating, we need to update that user object + # since it caches the full object + if SESSION_IMPERSONATE_USER in request.session: + request.session[SESSION_IMPERSONATE_USER] = new_user + return self.me(request) + @permission_required("authentik_core.view_user", ["authentik_events.view_event"]) @extend_schema(responses={200: UserMetricsSerializer(many=False)}) @action(detail=True, pagination_class=None, filter_backends=[]) diff --git a/lifecycle/gunicorn.conf.py b/lifecycle/gunicorn.conf.py index 211f78680..6acca4436 100644 --- a/lifecycle/gunicorn.conf.py +++ b/lifecycle/gunicorn.conf.py @@ -51,7 +51,7 @@ logconfig_dict = { if SERVICE_HOST_ENV_NAME in os.environ: workers = 2 else: - default_workers = max(cpu_count() * 0.25, 1) + 1 # Minimum of 2 workers + default_workers = max(cpu_count() * 0.25, 1) + 1 # Minimum of 2 workers workers = int(os.environ.get("WORKERS", default_workers)) threads = 4 diff --git a/schema.yml b/schema.yml index 29a140afc..4b819fb76 100644 --- a/schema.yml +++ b/schema.yml @@ -3185,6 +3185,38 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/core/users/update_self/: + put: + operationId: core_users_update_self_update + description: Allow users to change information on their own profile + tags: + - core + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserSelfRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/UserSelfRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/UserSelfRequest' + required: true + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SessionUser' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/crypto/certificatekeypairs/: get: operationId: crypto_certificatekeypairs_list @@ -27577,9 +27609,9 @@ components: and, if this user is being impersonated, the original user in the `original` property. properties: user: - $ref: '#/components/schemas/User' + $ref: '#/components/schemas/UserSelf' original: - $ref: '#/components/schemas/User' + $ref: '#/components/schemas/UserSelf' required: - user SetIconRequest: @@ -28478,6 +28510,82 @@ components: required: - name - username + UserSelf: + type: object + description: |- + User Serializer for information a user can retrieve about themselves and + update about themselves + properties: + pk: + type: integer + readOnly: true + title: ID + username: + type: string + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + pattern: ^[\w.@+-]+$ + maxLength: 150 + name: + type: string + description: User's display name. + is_active: + type: boolean + readOnly: true + title: Active + description: Designates whether this user should be treated as active. Unselect + this instead of deleting accounts. + is_superuser: + type: boolean + readOnly: true + groups: + type: array + items: + $ref: '#/components/schemas/Group' + readOnly: true + email: + type: string + format: email + title: Email address + maxLength: 254 + avatar: + type: string + readOnly: true + uid: + type: string + readOnly: true + required: + - avatar + - groups + - is_active + - is_superuser + - name + - pk + - uid + - username + UserSelfRequest: + type: object + description: |- + User Serializer for information a user can retrieve about themselves and + update about themselves + properties: + username: + type: string + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + pattern: ^[\w.@+-]+$ + maxLength: 150 + name: + type: string + description: User's display name. + email: + type: string + format: email + title: Email address + maxLength: 254 + required: + - name + - username UserSetting: type: object description: Serializer for User settings for stages and sources diff --git a/web/src/elements/forms/ModelForm.ts b/web/src/elements/forms/ModelForm.ts index 59d06dd38..20f9a8657 100644 --- a/web/src/elements/forms/ModelForm.ts +++ b/web/src/elements/forms/ModelForm.ts @@ -3,18 +3,20 @@ import { EVENT_REFRESH } from "../../constants"; import { Form } from "./Form"; export abstract class ModelForm extends Form { + viewportCheck = true; abstract loadInstance(pk: PKT): Promise; @property({attribute: false}) set instancePk(value: PKT) { this._instancePk = value; - if (this.isInViewport) { - this.loadInstance(value).then(instance => { - this.instance = instance; - this.requestUpdate(); - }); + if (this.viewportCheck && !this.isInViewport) { + return; } + this.loadInstance(value).then((instance) => { + this.instance = instance; + this.requestUpdate(); + }); } private _instancePk?: PKT; diff --git a/web/src/locales/en.po b/web/src/locales/en.po index 5f5de2312..46ce0b148 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -1077,7 +1077,7 @@ msgstr "Delete Refresh Code" msgid "Delete Session" msgstr "Delete Session" -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts msgid "Delete account" msgstr "Delete account" @@ -1297,7 +1297,7 @@ msgstr "Either no applications are defined, or you don't have access to any." #: src/flows/stages/identification/IdentificationStage.ts #: src/pages/events/TransportForm.ts #: src/pages/stages/identification/IdentificationStageForm.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts #: src/pages/users/UserViewPage.ts msgid "Email" @@ -1434,7 +1434,6 @@ msgstr "Everything is ok." msgid "Exception" msgstr "Exception" -#: src/pages/flows/FlowListPage.ts #: src/pages/flows/FlowViewPage.ts msgid "Execute" msgstr "Execute" @@ -1487,7 +1486,6 @@ msgstr "Expiry date" msgid "Explicit Consent" msgstr "Explicit Consent" -#: src/pages/flows/FlowListPage.ts #: src/pages/flows/FlowViewPage.ts msgid "Export" msgstr "Export" @@ -2113,7 +2111,7 @@ msgstr "Load servers" #: src/flows/stages/prompt/PromptStage.ts #: src/pages/applications/ApplicationViewPage.ts #: src/pages/applications/ApplicationViewPage.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/utils.ts msgid "Loading" msgstr "Loading" @@ -2402,7 +2400,7 @@ msgstr "My Applications" #: src/pages/stages/user_login/UserLoginStageForm.ts #: src/pages/stages/user_logout/UserLogoutStageForm.ts #: src/pages/stages/user_write/UserWriteStageForm.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts #: src/pages/users/UserListPage.ts #: src/pages/users/UserViewPage.ts @@ -3118,7 +3116,7 @@ msgstr "Request token URL" msgid "Required" msgstr "Required" -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." msgstr "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." @@ -3765,7 +3763,7 @@ msgstr "Successfully updated binding." msgid "Successfully updated certificate-key pair." msgstr "Successfully updated certificate-key pair." -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts msgid "Successfully updated details." msgstr "Successfully updated details." @@ -4297,7 +4295,7 @@ msgstr "Up-to-date!" #: src/pages/stages/StageListPage.ts #: src/pages/stages/prompt/PromptListPage.ts #: src/pages/tenants/TenantListPage.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts #: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts #: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts @@ -4400,7 +4398,7 @@ msgstr "Update User" msgid "Update available" msgstr "Update available" -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSettingsPage.ts msgid "Update details" msgstr "Update details" @@ -4533,7 +4531,7 @@ msgstr "User {0}" msgid "User's avatar" msgstr "User's avatar" -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts msgid "User's display name." msgstr "User's display name." @@ -4553,7 +4551,7 @@ msgstr "Userinfo URL" #: src/flows/stages/identification/IdentificationStage.ts #: src/pages/policies/reputation/UserReputationListPage.ts #: src/pages/stages/identification/IdentificationStageForm.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts #: src/pages/users/UserViewPage.ts msgid "Username" diff --git a/web/src/locales/pseudo-LOCALE.po b/web/src/locales/pseudo-LOCALE.po index ed51dac91..650899455 100644 --- a/web/src/locales/pseudo-LOCALE.po +++ b/web/src/locales/pseudo-LOCALE.po @@ -1071,7 +1071,7 @@ msgstr "" msgid "Delete Session" msgstr "" -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts msgid "Delete account" msgstr "" @@ -1289,7 +1289,7 @@ msgstr "" #: src/flows/stages/identification/IdentificationStage.ts #: src/pages/events/TransportForm.ts #: src/pages/stages/identification/IdentificationStageForm.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts #: src/pages/users/UserViewPage.ts msgid "Email" @@ -1426,7 +1426,6 @@ msgstr "" msgid "Exception" msgstr "" -#: src/pages/flows/FlowListPage.ts #: src/pages/flows/FlowViewPage.ts msgid "Execute" msgstr "" @@ -1479,7 +1478,6 @@ msgstr "" msgid "Explicit Consent" msgstr "" -#: src/pages/flows/FlowListPage.ts #: src/pages/flows/FlowViewPage.ts msgid "Export" msgstr "" @@ -2105,7 +2103,7 @@ msgstr "" #: src/flows/stages/prompt/PromptStage.ts #: src/pages/applications/ApplicationViewPage.ts #: src/pages/applications/ApplicationViewPage.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/utils.ts msgid "Loading" msgstr "" @@ -2394,7 +2392,7 @@ msgstr "" #: src/pages/stages/user_login/UserLoginStageForm.ts #: src/pages/stages/user_logout/UserLogoutStageForm.ts #: src/pages/stages/user_write/UserWriteStageForm.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts #: src/pages/users/UserListPage.ts #: src/pages/users/UserViewPage.ts @@ -3110,7 +3108,7 @@ msgstr "" msgid "Required" msgstr "" -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." msgstr "" @@ -3757,7 +3755,7 @@ msgstr "" msgid "Successfully updated certificate-key pair." msgstr "" -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts msgid "Successfully updated details." msgstr "" @@ -4282,7 +4280,7 @@ msgstr "" #: src/pages/stages/StageListPage.ts #: src/pages/stages/prompt/PromptListPage.ts #: src/pages/tenants/TenantListPage.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts #: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts #: src/pages/user-settings/settings/UserSettingsAuthenticatorWebAuthn.ts @@ -4385,7 +4383,7 @@ msgstr "" msgid "Update available" msgstr "" -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSettingsPage.ts msgid "Update details" msgstr "" @@ -4518,7 +4516,7 @@ msgstr "" msgid "User's avatar" msgstr "" -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts msgid "User's display name." msgstr "" @@ -4538,7 +4536,7 @@ msgstr "" #: src/flows/stages/identification/IdentificationStage.ts #: src/pages/policies/reputation/UserReputationListPage.ts #: src/pages/stages/identification/IdentificationStageForm.ts -#: src/pages/user-settings/UserDetailsPage.ts +#: src/pages/user-settings/UserSelfForm.ts #: src/pages/users/UserForm.ts #: src/pages/users/UserViewPage.ts msgid "Username" diff --git a/web/src/pages/user-settings/UserDetailsPage.ts b/web/src/pages/user-settings/UserDetailsPage.ts deleted file mode 100644 index a8ab30188..000000000 --- a/web/src/pages/user-settings/UserDetailsPage.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { t } from "@lingui/macro"; -import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; -import PFCard from "@patternfly/patternfly/components/Card/card.css"; -import AKGlobal from "../../authentik.css"; -import PFButton from "@patternfly/patternfly/components/Button/button.css"; -import PFBase from "@patternfly/patternfly/patternfly-base.css"; -import PFForm from "@patternfly/patternfly/components/Form/form.css"; -import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; -import { CoreApi, User } from "authentik-api"; -import { me } from "../../api/Users"; -import { ifDefined } from "lit-html/directives/if-defined"; -import { DEFAULT_CONFIG, tenant } from "../../api/Config"; -import "../../elements/forms/FormElement"; -import "../../elements/EmptyState"; -import "../../elements/forms/Form"; -import "../../elements/forms/HorizontalFormElement"; -import { until } from "lit-html/directives/until"; - -@customElement("ak-user-details") -export class UserDetailsPage extends LitElement { - - static get styles(): CSSResult[] { - return [PFBase, PFCard, PFForm, PFFormControl, PFButton, AKGlobal]; - } - - @property({attribute: false}) - user?: User; - - firstUpdated(): void { - me().then((user) => { - this.user = user.user; - }); - } - - render(): TemplateResult { - if (!this.user) { - return html` - `; - } - return html`
-
- ${t`Update details`} -
-
- { - return new CoreApi(DEFAULT_CONFIG).coreUsersUpdate({ - id: this.user?.pk || 0, - userRequest: data as User - }); - }}> -
- - -

${t`Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.`}

-
- - -

${t`User's display name.`}

-
- - - - -
-
-
- - ${until(tenant().then(tenant => { - if (tenant.flowUnenrollment) { - return html` - ${t`Delete account`} - `; - } - return html``; - }))} -
-
-
-
-
-
-
`; - } - -} diff --git a/web/src/pages/user-settings/UserSelfForm.ts b/web/src/pages/user-settings/UserSelfForm.ts new file mode 100644 index 000000000..2fa33a9c9 --- /dev/null +++ b/web/src/pages/user-settings/UserSelfForm.ts @@ -0,0 +1,100 @@ +import { t } from "@lingui/macro"; +import { customElement, html, TemplateResult } from "lit-element"; +import { CoreApi, UserSelf } from "authentik-api"; +import { ifDefined } from "lit-html/directives/if-defined"; +import { DEFAULT_CONFIG, tenant } from "../../api/Config"; +import "../../elements/forms/FormElement"; +import "../../elements/EmptyState"; +import "../../elements/forms/Form"; +import "../../elements/forms/HorizontalFormElement"; +import { until } from "lit-html/directives/until"; +import { ModelForm } from "../../elements/forms/ModelForm"; + +@customElement("ak-user-self-form") +export class UserSelfForm extends ModelForm { + viewportCheck = false; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + loadInstance(pk: number): Promise { + return new CoreApi(DEFAULT_CONFIG).coreUsersMeRetrieve().then((su) => { + return su.user; + }); + } + + getSuccessMessage(): string { + return t`Successfully updated details.`; + } + + send = (data: UserSelf): Promise => { + return new CoreApi(DEFAULT_CONFIG) + .coreUsersUpdateSelfUpdate({ + userSelfRequest: data, + }) + .then((su) => { + return su.user; + }); + }; + + renderForm(): TemplateResult { + if (!this.instance) { + return html` `; + } + return html`
+ + +

+ ${t`Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.`} +

+
+ + +

${t`User's display name.`}

+
+ + + + +
+
+
+ + ${until( + tenant().then((tenant) => { + if (tenant.flowUnenrollment) { + return html` + ${t`Delete account`} + `; + } + return html``; + }), + )} +
+
+
+
`; + } +} diff --git a/web/src/pages/user-settings/UserSettingsPage.ts b/web/src/pages/user-settings/UserSettingsPage.ts index dcc7db913..f38dfacfa 100644 --- a/web/src/pages/user-settings/UserSettingsPage.ts +++ b/web/src/pages/user-settings/UserSettingsPage.ts @@ -20,7 +20,7 @@ import { ifDefined } from "lit-html/directives/if-defined"; import "../../elements/Tabs"; import "../../elements/PageHeader"; import "./tokens/UserTokenList"; -import "./UserDetailsPage"; +import "./UserSelfForm"; import "./settings/UserSettingsAuthenticatorDuo"; import "./settings/UserSettingsAuthenticatorStatic"; import "./settings/UserSettingsAuthenticatorTOTP"; @@ -95,8 +95,17 @@ export class UserSettingsPage extends LitElement { description=${t`Configure settings relevant to your user profile.`}> -
- +
+
+
${t`Update details`}
+
+ +
+
From 8e797fa76b8e385a324c6930bfeaac9938abc10b Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 5 Aug 2021 18:16:06 +0200 Subject: [PATCH 6/8] outpost/ldap: fix errors with new UserSelf serializer Signed-off-by: Jens Langhammer --- internal/outpost/ldap/instance_bind.go | 4 ++-- internal/outpost/ldap/instance_search.go | 14 +++++++++++--- internal/outpost/ldap/ldap.go | 3 ++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/internal/outpost/ldap/instance_bind.go b/internal/outpost/ldap/instance_bind.go index 62d133b33..42f0fb93e 100644 --- a/internal/outpost/ldap/instance_bind.go +++ b/internal/outpost/ldap/instance_bind.go @@ -75,7 +75,7 @@ func (pi *ProviderInstance) Bind(username string, req BindRequest) (ldap.LDAPRes pi.boundUsersMutex.Lock() cs := pi.SearchAccessCheck(userInfo.User) pi.boundUsers[req.BindDN] = UserFlags{ - UserInfo: userInfo.User, + UserPk: userInfo.User.Pk, CanSearch: cs != nil, } if pi.boundUsers[req.BindDN].CanSearch { @@ -88,7 +88,7 @@ func (pi *ProviderInstance) Bind(username string, req BindRequest) (ldap.LDAPRes } // SearchAccessCheck Check if the current user is allowed to search -func (pi *ProviderInstance) SearchAccessCheck(user api.User) *string { +func (pi *ProviderInstance) SearchAccessCheck(user api.UserSelf) *string { for _, group := range user.Groups { for _, allowedGroup := range pi.searchAllowedGroups { pi.log.WithField("userGroup", group.Pk).WithField("allowedGroup", allowedGroup).Trace("Checking search access") diff --git a/internal/outpost/ldap/instance_search.go b/internal/outpost/ldap/instance_search.go index b0d52b61e..657ecce67 100644 --- a/internal/outpost/ldap/instance_search.go +++ b/internal/outpost/ldap/instance_search.go @@ -11,9 +11,17 @@ import ( "goauthentik.io/api" ) -func (pi *ProviderInstance) SearchMe(user api.User) (ldap.ServerSearchResult, error) { +func (pi *ProviderInstance) SearchMe(req SearchRequest, f UserFlags) (ldap.ServerSearchResult, error) { + if f.UserInfo == nil { + u, _, err := pi.s.ac.Client.CoreApi.CoreUsersRetrieve(req.ctx, f.UserInfo.Pk).Execute() + if err != nil { + req.log.WithError(err).Warning("Failed to get user info") + return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("Failed to get userinfo") + } + f.UserInfo = &u + } entries := make([]*ldap.Entry, 1) - entries[0] = pi.UserEntry(user) + entries[0] = pi.UserEntry(*f.UserInfo) return ldap.ServerSearchResult{Entries: entries, Referrals: []string{}, Controls: []ldap.Control{}, ResultCode: ldap.LDAPResultSuccess}, nil } @@ -42,7 +50,7 @@ func (pi *ProviderInstance) Search(req SearchRequest) (ldap.ServerSearchResult, } if !flags.CanSearch { pi.log.Debug("User can't search, showing info about user") - return pi.SearchMe(flags.UserInfo) + return pi.SearchMe(req, flags) } accsp.Finish() diff --git a/internal/outpost/ldap/ldap.go b/internal/outpost/ldap/ldap.go index 74bbc71f3..6d7a72c7b 100644 --- a/internal/outpost/ldap/ldap.go +++ b/internal/outpost/ldap/ldap.go @@ -39,7 +39,8 @@ type ProviderInstance struct { } type UserFlags struct { - UserInfo api.User + UserInfo *api.User + UserPk int32 CanSearch bool } From b4cfc56e5e8d3b9c6f207c630a3bebf042e66d23 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 5 Aug 2021 18:45:21 +0200 Subject: [PATCH 7/8] web/admin: fix source form's userMatchingMode being swapped Signed-off-by: Jens Langhammer # Conflicts: # web/src/pages/sources/oauth/OAuthSourceForm.ts # web/src/pages/sources/plex/PlexSourceForm.ts --- web/src/pages/sources/oauth/OAuthSourceForm.ts | 8 ++++---- web/src/pages/sources/plex/PlexSourceForm.ts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/web/src/pages/sources/oauth/OAuthSourceForm.ts b/web/src/pages/sources/oauth/OAuthSourceForm.ts index e76a8a842..cc6cbcc12 100644 --- a/web/src/pages/sources/oauth/OAuthSourceForm.ts +++ b/web/src/pages/sources/oauth/OAuthSourceForm.ts @@ -124,16 +124,16 @@ export class OAuthSourceForm extends ModelForm { - - - - diff --git a/web/src/pages/sources/plex/PlexSourceForm.ts b/web/src/pages/sources/plex/PlexSourceForm.ts index 726a6fb2e..cdd208666 100644 --- a/web/src/pages/sources/plex/PlexSourceForm.ts +++ b/web/src/pages/sources/plex/PlexSourceForm.ts @@ -146,16 +146,16 @@ export class PlexSourceForm extends ModelForm { - - - - From 18211a203331ccadcb4430dd8c2a776ac26e9764 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 5 Aug 2021 19:23:03 +0200 Subject: [PATCH 8/8] release: 2021.7.3 --- .bumpversion.cfg | 2 +- .github/workflows/release.yml | 20 +++++++++---------- authentik/__init__.py | 2 +- docker-compose.yml | 4 ++-- internal/constants/constants.go | 2 +- schema.yml | 2 +- web/src/constants.ts | 2 +- website/docs/installation/docker-compose.md | 4 ++-- .../outposts/manual-deploy-docker-compose.md | 4 ++-- .../docs/outposts/manual-deploy-kubernetes.md | 14 ++++++------- 10 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index d9f67e487..f8e0f0d8e 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2021.7.2 +current_version = 2021.7.3 tag = True commit = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)\-?(?P.*) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ff962ed1..d0f810c85 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,14 +33,14 @@ jobs: with: push: ${{ github.event_name == 'release' }} tags: | - beryju/authentik:2021.7.2, + beryju/authentik:2021.7.3, beryju/authentik:latest, - ghcr.io/goauthentik/server:2021.7.2, + ghcr.io/goauthentik/server:2021.7.3, ghcr.io/goauthentik/server:latest platforms: linux/amd64,linux/arm64 context: . - name: Building Docker Image (stable) - if: ${{ github.event_name == 'release' && !contains('2021.7.2', 'rc') }} + if: ${{ github.event_name == 'release' && !contains('2021.7.3', 'rc') }} run: | docker pull beryju/authentik:latest docker tag beryju/authentik:latest beryju/authentik:stable @@ -75,14 +75,14 @@ jobs: with: push: ${{ github.event_name == 'release' }} tags: | - beryju/authentik-proxy:2021.7.2, + beryju/authentik-proxy:2021.7.3, beryju/authentik-proxy:latest, - ghcr.io/goauthentik/proxy:2021.7.2, + ghcr.io/goauthentik/proxy:2021.7.3, ghcr.io/goauthentik/proxy:latest file: proxy.Dockerfile platforms: linux/amd64,linux/arm64 - name: Building Docker Image (stable) - if: ${{ github.event_name == 'release' && !contains('2021.7.2', 'rc') }} + if: ${{ github.event_name == 'release' && !contains('2021.7.3', 'rc') }} run: | docker pull beryju/authentik-proxy:latest docker tag beryju/authentik-proxy:latest beryju/authentik-proxy:stable @@ -117,14 +117,14 @@ jobs: with: push: ${{ github.event_name == 'release' }} tags: | - beryju/authentik-ldap:2021.7.2, + beryju/authentik-ldap:2021.7.3, beryju/authentik-ldap:latest, - ghcr.io/goauthentik/ldap:2021.7.2, + ghcr.io/goauthentik/ldap:2021.7.3, ghcr.io/goauthentik/ldap:latest file: ldap.Dockerfile platforms: linux/amd64,linux/arm64 - name: Building Docker Image (stable) - if: ${{ github.event_name == 'release' && !contains('2021.7.2', 'rc') }} + if: ${{ github.event_name == 'release' && !contains('2021.7.3', 'rc') }} run: | docker pull beryju/authentik-ldap:latest docker tag beryju/authentik-ldap:latest beryju/authentik-ldap:stable @@ -176,7 +176,7 @@ jobs: SENTRY_PROJECT: authentik SENTRY_URL: https://sentry.beryju.org with: - version: authentik@2021.7.2 + version: authentik@2021.7.3 environment: beryjuorg-prod sourcemaps: './web/dist' url_prefix: '~/static/dist' diff --git a/authentik/__init__.py b/authentik/__init__.py index 49849a06c..808981aab 100644 --- a/authentik/__init__.py +++ b/authentik/__init__.py @@ -1,3 +1,3 @@ """authentik""" -__version__ = "2021.7.2" +__version__ = "2021.7.3" ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" diff --git a/docker-compose.yml b/docker-compose.yml index 60d8d5f29..bd72ca4ef 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,7 +21,7 @@ services: networks: - internal server: - image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.7.2} + image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.7.3} restart: unless-stopped command: server environment: @@ -44,7 +44,7 @@ services: - "0.0.0.0:9000:9000" - "0.0.0.0:9443:9443" worker: - image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.7.2} + image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.7.3} restart: unless-stopped command: worker networks: diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 680d353cd..83f92fb81 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -17,4 +17,4 @@ func OutpostUserAgent() string { return fmt.Sprintf("authentik-outpost@%s (%s)", VERSION, BUILD()) } -const VERSION = "2021.7.2" +const VERSION = "2021.7.3" diff --git a/schema.yml b/schema.yml index 4b819fb76..197cdbdee 100644 --- a/schema.yml +++ b/schema.yml @@ -1,7 +1,7 @@ openapi: 3.0.3 info: title: authentik - version: 2021.7.2 + version: 2021.7.3 description: Making authentication simple. contact: email: hello@beryju.org diff --git a/web/src/constants.ts b/web/src/constants.ts index 314eb50af..5117d9bbd 100644 --- a/web/src/constants.ts +++ b/web/src/constants.ts @@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success"; export const ERROR_CLASS = "pf-m-danger"; export const PROGRESS_CLASS = "pf-m-in-progress"; export const CURRENT_CLASS = "pf-m-current"; -export const VERSION = "2021.7.2"; +export const VERSION = "2021.7.3"; export const PAGE_SIZE = 20; export const TITLE_DEFAULT = "authentik"; export const ROUTE_SEPARATOR = ";"; diff --git a/website/docs/installation/docker-compose.md b/website/docs/installation/docker-compose.md index 0f3ac2acc..3d46ba38b 100644 --- a/website/docs/installation/docker-compose.md +++ b/website/docs/installation/docker-compose.md @@ -12,11 +12,11 @@ This installation method is for test-setups and small-scale productive setups. ## Preparation -Download the latest `docker-compose.yml` from [here](https://raw.githubusercontent.com/goauthentik/authentik/version/2021.7.2/docker-compose.yml). Place it in a directory of your choice. +Download the latest `docker-compose.yml` from [here](https://raw.githubusercontent.com/goauthentik/authentik/version/2021.7.3/docker-compose.yml). Place it in a directory of your choice. To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env` -To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.7.2 >> .env` +To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.7.3 >> .env` If this is a fresh authentik install run the following commands to generate a password: diff --git a/website/docs/outposts/manual-deploy-docker-compose.md b/website/docs/outposts/manual-deploy-docker-compose.md index 6ee2adf3a..667e6c253 100644 --- a/website/docs/outposts/manual-deploy-docker-compose.md +++ b/website/docs/outposts/manual-deploy-docker-compose.md @@ -11,7 +11,7 @@ version: "3.5" services: authentik_proxy: - image: ghcr.io/goauthentik/proxy:2021.7.2 + image: ghcr.io/goauthentik/proxy:2021.7.3 ports: - 4180:4180 - 4443:4443 @@ -21,7 +21,7 @@ services: AUTHENTIK_TOKEN: token-generated-by-authentik # Or, for the LDAP Outpost authentik_proxy: - image: ghcr.io/goauthentik/ldap:2021.7.2 + image: ghcr.io/goauthentik/ldap:2021.7.3 ports: - 389:3389 environment: diff --git a/website/docs/outposts/manual-deploy-kubernetes.md b/website/docs/outposts/manual-deploy-kubernetes.md index b63191bfa..ec34c8873 100644 --- a/website/docs/outposts/manual-deploy-kubernetes.md +++ b/website/docs/outposts/manual-deploy-kubernetes.md @@ -14,7 +14,7 @@ metadata: app.kubernetes.io/instance: __OUTPOST_NAME__ app.kubernetes.io/managed-by: goauthentik.io app.kubernetes.io/name: authentik-proxy - app.kubernetes.io/version: 2021.7.2 + app.kubernetes.io/version: 2021.7.3 name: authentik-outpost-api stringData: authentik_host: "__AUTHENTIK_URL__" @@ -29,7 +29,7 @@ metadata: app.kubernetes.io/instance: __OUTPOST_NAME__ app.kubernetes.io/managed-by: goauthentik.io app.kubernetes.io/name: authentik-proxy - app.kubernetes.io/version: 2021.7.2 + app.kubernetes.io/version: 2021.7.3 name: authentik-outpost spec: ports: @@ -54,7 +54,7 @@ metadata: app.kubernetes.io/instance: __OUTPOST_NAME__ app.kubernetes.io/managed-by: goauthentik.io app.kubernetes.io/name: authentik-proxy - app.kubernetes.io/version: 2021.7.2 + app.kubernetes.io/version: 2021.7.3 name: authentik-outpost spec: selector: @@ -62,14 +62,14 @@ spec: app.kubernetes.io/instance: __OUTPOST_NAME__ app.kubernetes.io/managed-by: goauthentik.io app.kubernetes.io/name: authentik-proxy - app.kubernetes.io/version: 2021.7.2 + app.kubernetes.io/version: 2021.7.3 template: metadata: labels: app.kubernetes.io/instance: __OUTPOST_NAME__ app.kubernetes.io/managed-by: goauthentik.io app.kubernetes.io/name: authentik-proxy - app.kubernetes.io/version: 2021.7.2 + app.kubernetes.io/version: 2021.7.3 spec: containers: - env: @@ -88,7 +88,7 @@ spec: secretKeyRef: key: authentik_host_insecure name: authentik-outpost-api - image: ghcr.io/goauthentik/proxy:2021.7.2 + image: ghcr.io/goauthentik/proxy:2021.7.3 name: proxy ports: - containerPort: 4180 @@ -110,7 +110,7 @@ metadata: app.kubernetes.io/instance: __OUTPOST_NAME__ app.kubernetes.io/managed-by: goauthentik.io app.kubernetes.io/name: authentik-proxy - app.kubernetes.io/version: 2021.7.2 + app.kubernetes.io/version: 2021.7.3 name: authentik-outpost spec: rules: