diff --git a/authentik/stages/user_write/api.py b/authentik/stages/user_write/api.py index 5acaa6ae1..9abac9ef2 100644 --- a/authentik/stages/user_write/api.py +++ b/authentik/stages/user_write/api.py @@ -12,7 +12,7 @@ class UserWriteStageSerializer(StageSerializer): class Meta: model = UserWriteStage - fields = StageSerializer.Meta.fields + fields = StageSerializer.Meta.fields + ["create_users_as_inactive"] class UserWriteStageViewSet(UsedByMixin, ModelViewSet): diff --git a/authentik/stages/user_write/migrations/0003_userwritestage_create_users_as_inactive.py b/authentik/stages/user_write/migrations/0003_userwritestage_create_users_as_inactive.py new file mode 100644 index 000000000..5ca410291 --- /dev/null +++ b/authentik/stages/user_write/migrations/0003_userwritestage_create_users_as_inactive.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.4 on 2021-06-28 20:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_stages_user_write", "0002_auto_20200918_1653"), + ] + + operations = [ + migrations.AddField( + model_name="userwritestage", + name="create_users_as_inactive", + field=models.BooleanField( + default=False, + help_text="When set, newly created users are inactive and cannot login.", + ), + ), + ] diff --git a/authentik/stages/user_write/models.py b/authentik/stages/user_write/models.py index eb37a89f6..be5b8d1d0 100644 --- a/authentik/stages/user_write/models.py +++ b/authentik/stages/user_write/models.py @@ -1,6 +1,7 @@ """write stage models""" from typing import Type +from django.db import models from django.utils.translation import gettext_lazy as _ from django.views import View from rest_framework.serializers import BaseSerializer @@ -12,6 +13,11 @@ class UserWriteStage(Stage): """Writes currently pending data into the pending user, or if no user exists, creates a new user with the data.""" + create_users_as_inactive = models.BooleanField( + default=False, + help_text=_("When set, newly created users are inactive and cannot login."), + ) + @property def serializer(self) -> BaseSerializer: from authentik.stages.user_write.api import UserWriteStageSerializer diff --git a/authentik/stages/user_write/stage.py b/authentik/stages/user_write/stage.py index 61f3eb275..554cd36d6 100644 --- a/authentik/stages/user_write/stage.py +++ b/authentik/stages/user_write/stage.py @@ -35,7 +35,9 @@ class UserWriteStageView(StageView): data = self.executor.plan.context[PLAN_CONTEXT_PROMPT] user_created = False if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: - self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = User() + self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = User( + is_active=not self.executor.current_stage.create_users_as_inactive + ) self.executor.plan.context[ PLAN_CONTEXT_AUTHENTICATION_BACKEND ] = class_to_path(ModelBackend) diff --git a/schema.yml b/schema.yml index 40a26b97d..026a7f49a 100644 --- a/schema.yml +++ b/schema.yml @@ -25778,6 +25778,9 @@ components: type: array items: $ref: '#/components/schemas/FlowRequest' + create_users_as_inactive: + type: boolean + description: When set, newly created users are inactive and cannot login. PatchedWebAuthnDeviceRequest: type: object description: Serializer for WebAuthn authenticator devices @@ -28272,6 +28275,9 @@ components: type: array items: $ref: '#/components/schemas/Flow' + create_users_as_inactive: + type: boolean + description: When set, newly created users are inactive and cannot login. required: - component - name @@ -28288,6 +28294,9 @@ components: type: array items: $ref: '#/components/schemas/FlowRequest' + create_users_as_inactive: + type: boolean + description: When set, newly created users are inactive and cannot login. required: - name ValidationError: diff --git a/web/src/locales/en.po b/web/src/locales/en.po index 406594bce..a4ff46ed9 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -945,6 +945,10 @@ msgstr "Create User" msgid "Create provider" msgstr "Create provider" +#: src/pages/stages/user_write/UserWriteStageForm.ts +msgid "Create users as inactive" +msgstr "Create users as inactive" + #: src/pages/applications/ApplicationForm.ts #: src/pages/flows/BoundStagesList.ts #: src/pages/outposts/ServiceConnectionListPage.ts @@ -2151,6 +2155,10 @@ msgstr "Logs" msgid "Long-running operations which authentik executes in the background." msgstr "Long-running operations which authentik executes in the background." +#: src/pages/stages/user_write/UserWriteStageForm.ts +msgid "Mark newly created users as inactive." +msgstr "Mark newly created users as inactive." + #: src/pages/policies/event_matcher/EventMatcherPolicyForm.ts msgid "Match created events with this action type. When left empty, all action types will be matched." msgstr "Match created events with this action type. When left empty, all action types will be matched." @@ -3384,6 +3392,7 @@ msgstr "Stage used to validate any authenticator. This stage should be used duri #: src/pages/stages/password/PasswordStageForm.ts #: src/pages/stages/prompt/PromptStageForm.ts #: src/pages/stages/user_login/UserLoginStageForm.ts +#: src/pages/stages/user_write/UserWriteStageForm.ts msgid "Stage-specific settings" msgstr "Stage-specific settings" diff --git a/web/src/locales/pseudo-LOCALE.po b/web/src/locales/pseudo-LOCALE.po index 15917a8a8..b5dab2646 100644 --- a/web/src/locales/pseudo-LOCALE.po +++ b/web/src/locales/pseudo-LOCALE.po @@ -939,6 +939,10 @@ msgstr "" msgid "Create provider" msgstr "" +#: +msgid "Create users as inactive" +msgstr "" + #: #: #: @@ -2143,6 +2147,10 @@ msgstr "" msgid "Long-running operations which authentik executes in the background." msgstr "" +#: +msgid "Mark newly created users as inactive." +msgstr "" + #: msgid "Match created events with this action type. When left empty, all action types will be matched." msgstr "" @@ -3376,6 +3384,7 @@ msgstr "" #: #: #: +#: msgid "Stage-specific settings" msgstr "" diff --git a/web/src/pages/stages/user_write/UserWriteStageForm.ts b/web/src/pages/stages/user_write/UserWriteStageForm.ts index aebd2143c..58e7fa604 100644 --- a/web/src/pages/stages/user_write/UserWriteStageForm.ts +++ b/web/src/pages/stages/user_write/UserWriteStageForm.ts @@ -5,7 +5,9 @@ import { html, TemplateResult } from "lit-html"; import { DEFAULT_CONFIG } from "../../../api/Config"; import { ifDefined } from "lit-html/directives/if-defined"; import "../../../elements/forms/HorizontalFormElement"; +import "../../../elements/forms/FormGroup"; import { ModelForm } from "../../../elements/forms/ModelForm"; +import { first } from "../../../utils"; @customElement("ak-stage-user-write-form") export class UserWriteStageForm extends ModelForm { @@ -49,6 +51,22 @@ export class UserWriteStageForm extends ModelForm { name="name"> + + + ${t`Stage-specific settings`} + +
+ +
+ + +
+

${t`Mark newly created users as inactive.`}

+
+
+
`; } diff --git a/website/docs/releases/v2021.6.md b/website/docs/releases/v2021.6.md index 2053142ec..8ce50f86c 100644 --- a/website/docs/releases/v2021.6.md +++ b/website/docs/releases/v2021.6.md @@ -132,6 +132,8 @@ slug: "2021.6" - providers/oauth2: fix exp of JWT when not using seconds - sources/ldap: improve error handling when checking for password complexity on non-ad setups - stages/authenticator_duo: fix component not being set in API +- stages/prompt: ensure hidden and static fields keep the value they had set +- stages/user_write: add flag to create new users as inactive - tenants: include all default flows in current_tenant - web/admin: fix deletion of authenticator not reloading the state correctly - web/admin: fix only recovery flows being selectable for unenrollment flow in tenant form diff --git a/website/static/flows/enrollment-email-verification.akflow b/website/static/flows/enrollment-email-verification.akflow index ebf7af9d1..da7bd5b75 100644 --- a/website/static/flows/enrollment-email-verification.akflow +++ b/website/static/flows/enrollment-email-verification.akflow @@ -145,7 +145,9 @@ "name": "default-enrollment-user-write" }, "model": "authentik_stages_user_write.userwritestage", - "attrs": {} + "attrs": { + "create_users_as_inactive": true + } }, { "identifiers": {