diff --git a/authentik/stages/email/api.py b/authentik/stages/email/api.py index 636d0bafb..ec9d461a4 100644 --- a/authentik/stages/email/api.py +++ b/authentik/stages/email/api.py @@ -43,6 +43,7 @@ class EmailStageSerializer(StageSerializer): "token_expiry", "subject", "template", + "activate_user_on_success", ] extra_kwargs = {"password": {"write_only": True}} @@ -65,6 +66,7 @@ class EmailStageViewSet(UsedByMixin, ModelViewSet): "token_expiry", "subject", "template", + "activate_user_on_success", ] ordering = ["name"] diff --git a/authentik/stages/email/migrations/0004_emailstage_activate_user_on_success.py b/authentik/stages/email/migrations/0004_emailstage_activate_user_on_success.py new file mode 100644 index 000000000..77c8be05f --- /dev/null +++ b/authentik/stages/email/migrations/0004_emailstage_activate_user_on_success.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.7 on 2021-10-04 16:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_stages_email", "0003_auto_20210404_1054"), + ] + + operations = [ + migrations.AddField( + model_name="emailstage", + name="activate_user_on_success", + field=models.BooleanField( + default=False, help_text="Activate users upon completion of stage." + ), + ), + ] diff --git a/authentik/stages/email/models.py b/authentik/stages/email/models.py index b9b7fe12d..7584d7190 100644 --- a/authentik/stages/email/models.py +++ b/authentik/stages/email/models.py @@ -71,6 +71,10 @@ class EmailStage(Stage): timeout = models.IntegerField(default=10) from_address = models.EmailField(default="system@authentik.local") + activate_user_on_success = models.BooleanField( + default=False, help_text=_("Activate users upon completion of stage.") + ) + token_expiry = models.IntegerField( default=30, help_text=_("Time in minutes the token sent is valid.") ) diff --git a/authentik/stages/email/stage.py b/authentik/stages/email/stage.py index 77f29e0a0..8dee06f64 100644 --- a/authentik/stages/email/stage.py +++ b/authentik/stages/email/stage.py @@ -106,6 +106,9 @@ class EmailStageView(ChallengeStageView): self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = token.user token.delete() messages.success(request, _("Successfully verified Email.")) + if self.executor.current_stage.activate_user_on_success: + self.executor.plan.context[PLAN_CONTEXT_PENDING_USER].is_active = True + self.executor.plan.context[PLAN_CONTEXT_PENDING_USER].save() return self.executor.stage_ok() if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: LOGGER.debug("No pending user") diff --git a/authentik/stages/email/tests/test_stage.py b/authentik/stages/email/tests/test_stage.py index c67ce8881..f0a1e6c9a 100644 --- a/authentik/stages/email/tests/test_stage.py +++ b/authentik/stages/email/tests/test_stage.py @@ -31,6 +31,7 @@ class TestEmailStage(APITestCase): ) self.stage = EmailStage.objects.create( name="email", + activate_user_on_success=True, ) self.binding = FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2) @@ -84,6 +85,8 @@ class TestEmailStage(APITestCase): """Test with token""" # Make sure token exists self.test_pending_user() + self.user.is_active = False + self.user.save() plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()]) session = self.client.session session[SESSION_KEY_PLAN] = plan @@ -125,3 +128,4 @@ class TestEmailStage(APITestCase): session = self.client.session plan: FlowPlan = session[SESSION_KEY_PLAN] self.assertEqual(plan.context[PLAN_CONTEXT_PENDING_USER], self.user) + self.assertTrue(plan.context[PLAN_CONTEXT_PENDING_USER].is_active) diff --git a/schema.yml b/schema.yml index 27e7084a2..d094ce173 100644 --- a/schema.yml +++ b/schema.yml @@ -15638,6 +15638,10 @@ paths: operationId: stages_email_list description: EmailStage Viewset parameters: + - in: query + name: activate_user_on_success + schema: + type: boolean - in: query name: from_address schema: @@ -19811,6 +19815,9 @@ components: type: string template: type: string + activate_user_on_success: + type: boolean + description: Activate users upon completion of stage. required: - component - name @@ -19863,6 +19870,9 @@ components: type: string template: type: string + activate_user_on_success: + type: boolean + description: Activate users upon completion of stage. required: - name ErrorDetail: @@ -25370,6 +25380,9 @@ components: type: string template: type: string + activate_user_on_success: + type: boolean + description: Activate users upon completion of stage. PatchedEventMatcherPolicyRequest: type: object description: Event Matcher Policy Serializer diff --git a/web/src/locales/en.po b/web/src/locales/en.po index e2e0a518f..483387081 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -159,6 +159,10 @@ msgstr "Actions over the last 24 hours" msgid "Activate" msgstr "Activate" +#: src/pages/stages/email/EmailStageForm.ts +msgid "Activate pending user on success" +msgstr "Activate pending user on success" + #: src/pages/groups/MemberSelectModal.ts #: src/pages/users/UserListPage.ts #: src/pages/users/UserListPage.ts @@ -294,6 +298,10 @@ msgstr "Application" msgid "Application Icon" msgstr "Application Icon" +#: src/elements/charts/UserChart.ts +msgid "Application authorizations" +msgstr "Application authorizations" + #: src/pages/events/utils.ts msgid "Application authorized" msgstr "Application authorized" @@ -439,6 +447,10 @@ msgstr "Authorization URL" msgid "Authorization flow" msgstr "Authorization flow" +#: src/elements/charts/ApplicationAuthorizeChart.ts +msgid "Authorizations" +msgstr "Authorizations" + #: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts msgid "Authorize URL" msgstr "Authorize URL" @@ -1724,6 +1736,11 @@ msgstr "External Host" msgid "External host" msgstr "External host" +#: src/elements/charts/AdminLoginsChart.ts +#: src/elements/charts/UserChart.ts +msgid "Failed Logins" +msgstr "Failed Logins" + #: src/pages/stages/password/PasswordStageForm.ts msgid "Failed attempts before cancel" msgstr "Failed attempts before cancel" @@ -1778,9 +1795,13 @@ msgstr "Field of the user object this value is written to." msgid "Field which contains a unique Identifier." msgstr "Field which contains a unique Identifier." +#: +#~ msgid "Field which contains members of a group." +#~ msgstr "Field which contains members of a group." + #: src/pages/sources/ldap/LDAPSourceForm.ts -msgid "Field which contains members of a group." -msgstr "Field which contains members of a group." +msgid "Field which contains members of a group. Note that if using the \"memberUid\" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'" +msgstr "Field which contains members of a group. Note that if using the \"memberUid\" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'" #: src/pages/stages/prompt/PromptStageForm.ts msgid "Fields" @@ -3607,6 +3628,10 @@ msgstr "Scopes" msgid "Score" msgstr "Score" +#: src/pages/providers/ldap/LDAPProviderForm.ts +msgid "Search group" +msgstr "Search group" + #: src/elements/table/TableSearch.ts #: src/user/LibraryPage.ts msgid "Search..." @@ -4027,6 +4052,11 @@ msgstr "Subject-alt name" msgid "Successful" msgstr "Successful" +#: src/elements/charts/AdminLoginsChart.ts +#: src/elements/charts/UserChart.ts +msgid "Successful Logins" +msgstr "Successful Logins" + #: src/pages/flows/FlowListPage.ts msgid "Successfully cleared flow cache" msgstr "Successfully cleared flow cache" @@ -4354,9 +4384,9 @@ msgstr "Sync" msgid "Sync groups" msgstr "Sync groups" -#: src/pages/providers/ldap/LDAPProviderForm.ts -msgid "Sync parent group" -msgstr "Sync parent group" +#: +#~ msgid "Sync parent group" +#~ msgstr "Sync parent group" #: src/pages/sources/ldap/LDAPSourceViewPage.ts msgid "Sync status" @@ -5212,6 +5242,10 @@ msgstr "Webhook Mapping" msgid "Webhook URL" msgstr "Webhook URL" +#: src/pages/stages/email/EmailStageForm.ts +msgid "When a user returns from the email successfully, their account will be activated." +msgstr "When a user returns from the email successfully, their account will be activated." + #: src/pages/stages/identification/IdentificationStageForm.ts msgid "When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown." msgstr "When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown." diff --git a/web/src/locales/pseudo-LOCALE.po b/web/src/locales/pseudo-LOCALE.po index 0a3ad1a61..de14a6654 100644 --- a/web/src/locales/pseudo-LOCALE.po +++ b/web/src/locales/pseudo-LOCALE.po @@ -159,6 +159,10 @@ msgstr "" msgid "Activate" msgstr "" +#: src/pages/stages/email/EmailStageForm.ts +msgid "Activate pending user on success" +msgstr "" + #: src/pages/groups/MemberSelectModal.ts #: src/pages/users/UserListPage.ts #: src/pages/users/UserListPage.ts @@ -294,6 +298,10 @@ msgstr "" msgid "Application Icon" msgstr "" +#: src/elements/charts/UserChart.ts +msgid "Application authorizations" +msgstr "" + #: src/pages/events/utils.ts msgid "Application authorized" msgstr "" @@ -435,6 +443,10 @@ msgstr "" msgid "Authorization flow" msgstr "" +#: src/elements/charts/ApplicationAuthorizeChart.ts +msgid "Authorizations" +msgstr "" + #: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts msgid "Authorize URL" msgstr "" @@ -1716,6 +1728,11 @@ msgstr "" msgid "External host" msgstr "" +#: src/elements/charts/AdminLoginsChart.ts +#: src/elements/charts/UserChart.ts +msgid "Failed Logins" +msgstr "" + #: src/pages/stages/password/PasswordStageForm.ts msgid "Failed attempts before cancel" msgstr "" @@ -1770,8 +1787,12 @@ msgstr "" msgid "Field which contains a unique Identifier." msgstr "" +#: +#~ msgid "Field which contains members of a group." +#~ msgstr "" + #: src/pages/sources/ldap/LDAPSourceForm.ts -msgid "Field which contains members of a group." +msgid "Field which contains members of a group. Note that if using the \"memberUid\" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'" msgstr "" #: src/pages/stages/prompt/PromptStageForm.ts @@ -3599,6 +3620,10 @@ msgstr "" msgid "Score" msgstr "" +#: src/pages/providers/ldap/LDAPProviderForm.ts +msgid "Search group" +msgstr "" + #: src/elements/table/TableSearch.ts #: src/user/LibraryPage.ts msgid "Search..." @@ -4019,6 +4044,11 @@ msgstr "" msgid "Successful" msgstr "" +#: src/elements/charts/AdminLoginsChart.ts +#: src/elements/charts/UserChart.ts +msgid "Successful Logins" +msgstr "" + #: src/pages/flows/FlowListPage.ts msgid "Successfully cleared flow cache" msgstr "" @@ -4346,9 +4376,9 @@ msgstr "" msgid "Sync groups" msgstr "" -#: src/pages/providers/ldap/LDAPProviderForm.ts -msgid "Sync parent group" -msgstr "" +#: +#~ msgid "Sync parent group" +#~ msgstr "" #: src/pages/sources/ldap/LDAPSourceViewPage.ts msgid "Sync status" @@ -5197,6 +5227,10 @@ msgstr "" msgid "Webhook URL" msgstr "" +#: src/pages/stages/email/EmailStageForm.ts +msgid "When a user returns from the email successfully, their account will be activated." +msgstr "" + #: src/pages/stages/identification/IdentificationStageForm.ts msgid "When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown." msgstr "" diff --git a/web/src/pages/stages/email/EmailStageForm.ts b/web/src/pages/stages/email/EmailStageForm.ts index 740d03937..1159b5552 100644 --- a/web/src/pages/stages/email/EmailStageForm.ts +++ b/web/src/pages/stages/email/EmailStageForm.ts @@ -147,6 +147,21 @@ export class EmailStageForm extends ModelForm { ${t`Stage-specific settings`}
+ +
+ + +
+

+ ${t`When a user returns from the email successfully, their account will be activated.`} +

+