stages/user_write: add option to add newly created users to a group
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
198e5ce642
commit
ef341dd405
2
Makefile
2
Makefile
|
@ -62,7 +62,7 @@ gen-outpost:
|
||||||
--additional-properties=packageName=api,enumClassPrefix=true,useOneOfDiscriminatorLookup=true,disallowAdditionalPropertiesIfNotPresent=false
|
--additional-properties=packageName=api,enumClassPrefix=true,useOneOfDiscriminatorLookup=true,disallowAdditionalPropertiesIfNotPresent=false
|
||||||
rm -f api/go.mod api/go.sum
|
rm -f api/go.mod api/go.sum
|
||||||
|
|
||||||
gen: gen-build gen-clean gen-web gen-outpost
|
gen: gen-build gen-clean gen-web
|
||||||
|
|
||||||
migrate:
|
migrate:
|
||||||
python -m lifecycle.migrate
|
python -m lifecycle.migrate
|
||||||
|
|
|
@ -12,7 +12,7 @@ class UserWriteStageSerializer(StageSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
||||||
model = UserWriteStage
|
model = UserWriteStage
|
||||||
fields = StageSerializer.Meta.fields + ["create_users_as_inactive"]
|
fields = StageSerializer.Meta.fields + ["create_users_as_inactive", "create_users_group"]
|
||||||
|
|
||||||
|
|
||||||
class UserWriteStageViewSet(UsedByMixin, ModelViewSet):
|
class UserWriteStageViewSet(UsedByMixin, ModelViewSet):
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Generated by Django 3.2.7 on 2021-09-14 19:27
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_core", "0028_alter_token_intent"),
|
||||||
|
("authentik_stages_user_write", "0003_userwritestage_create_users_as_inactive"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="userwritestage",
|
||||||
|
name="create_users_group",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
default=None,
|
||||||
|
help_text="Optionally add newly created users to this group.",
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_DEFAULT,
|
||||||
|
to="authentik_core.group",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -6,6 +6,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from rest_framework.serializers import BaseSerializer
|
from rest_framework.serializers import BaseSerializer
|
||||||
|
|
||||||
|
from authentik.core.models import Group
|
||||||
from authentik.flows.models import Stage
|
from authentik.flows.models import Stage
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +19,14 @@ class UserWriteStage(Stage):
|
||||||
help_text=_("When set, newly created users are inactive and cannot login."),
|
help_text=_("When set, newly created users are inactive and cannot login."),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
create_users_group = models.ForeignKey(
|
||||||
|
Group,
|
||||||
|
null=True,
|
||||||
|
default=None,
|
||||||
|
on_delete=models.SET_DEFAULT,
|
||||||
|
help_text=_("Optionally add newly created users to this group."),
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def serializer(self) -> BaseSerializer:
|
def serializer(self) -> BaseSerializer:
|
||||||
from authentik.stages.user_write.api import UserWriteStageSerializer
|
from authentik.stages.user_write.api import UserWriteStageSerializer
|
||||||
|
|
|
@ -92,6 +92,8 @@ class UserWriteStageView(StageView):
|
||||||
try:
|
try:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
user.save()
|
user.save()
|
||||||
|
if self.executor.current_stage.create_users_group:
|
||||||
|
user.ak_groups.add(self.executor.current_stage.create_users_group)
|
||||||
except IntegrityError as exc:
|
except IntegrityError as exc:
|
||||||
LOGGER.warning("Failed to save user", exc=exc)
|
LOGGER.warning("Failed to save user", exc=exc)
|
||||||
return self.executor.stage_invalid()
|
return self.executor.stage_invalid()
|
||||||
|
|
|
@ -7,7 +7,7 @@ from django.urls import reverse
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_str
|
||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from authentik.core.models import USER_ATTRIBUTE_SOURCES, Source, User, UserSourceConnection
|
from authentik.core.models import USER_ATTRIBUTE_SOURCES, Group, Source, User, UserSourceConnection
|
||||||
from authentik.core.sources.stage import PLAN_CONTEXT_SOURCES_CONNECTION
|
from authentik.core.sources.stage import PLAN_CONTEXT_SOURCES_CONNECTION
|
||||||
from authentik.flows.challenge import ChallengeTypes
|
from authentik.flows.challenge import ChallengeTypes
|
||||||
from authentik.flows.markers import StageMarker
|
from authentik.flows.markers import StageMarker
|
||||||
|
@ -29,7 +29,10 @@ class TestUserWriteStage(APITestCase):
|
||||||
slug="test-write",
|
slug="test-write",
|
||||||
designation=FlowDesignation.AUTHENTICATION,
|
designation=FlowDesignation.AUTHENTICATION,
|
||||||
)
|
)
|
||||||
self.stage = UserWriteStage.objects.create(name="write")
|
self.group = Group.objects.create(name="test-group")
|
||||||
|
self.stage = UserWriteStage.objects.create(
|
||||||
|
name="write", create_users_as_inactive=True, create_users_group=self.group
|
||||||
|
)
|
||||||
self.binding = FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
|
self.binding = FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
|
||||||
self.source = Source.objects.create(name="fake_source")
|
self.source = Source.objects.create(name="fake_source")
|
||||||
|
|
||||||
|
@ -67,6 +70,7 @@ class TestUserWriteStage(APITestCase):
|
||||||
user_qs = User.objects.filter(username=plan.context[PLAN_CONTEXT_PROMPT]["username"])
|
user_qs = User.objects.filter(username=plan.context[PLAN_CONTEXT_PROMPT]["username"])
|
||||||
self.assertTrue(user_qs.exists())
|
self.assertTrue(user_qs.exists())
|
||||||
self.assertTrue(user_qs.first().check_password(password))
|
self.assertTrue(user_qs.first().check_password(password))
|
||||||
|
self.assertEqual(list(user_qs.first().ak_groups.all()), [self.group])
|
||||||
self.assertEqual(user_qs.first().attributes, {USER_ATTRIBUTE_SOURCES: [self.source.name]})
|
self.assertEqual(user_qs.first().attributes, {USER_ATTRIBUTE_SOURCES: [self.source.name]})
|
||||||
|
|
||||||
def test_user_update(self):
|
def test_user_update(self):
|
||||||
|
|
20
schema.yml
20
schema.yml
|
@ -17949,6 +17949,11 @@ paths:
|
||||||
name: create_users_as_inactive
|
name: create_users_as_inactive
|
||||||
schema:
|
schema:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
- in: query
|
||||||
|
name: create_users_group
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
- in: query
|
- in: query
|
||||||
name: name
|
name: name
|
||||||
schema:
|
schema:
|
||||||
|
@ -26628,6 +26633,11 @@ components:
|
||||||
create_users_as_inactive:
|
create_users_as_inactive:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: When set, newly created users are inactive and cannot login.
|
description: When set, newly created users are inactive and cannot login.
|
||||||
|
create_users_group:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
description: Optionally add newly created users to this group.
|
||||||
PatchedWebAuthnDeviceRequest:
|
PatchedWebAuthnDeviceRequest:
|
||||||
type: object
|
type: object
|
||||||
description: Serializer for WebAuthn authenticator devices
|
description: Serializer for WebAuthn authenticator devices
|
||||||
|
@ -29283,6 +29293,11 @@ components:
|
||||||
create_users_as_inactive:
|
create_users_as_inactive:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: When set, newly created users are inactive and cannot login.
|
description: When set, newly created users are inactive and cannot login.
|
||||||
|
create_users_group:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
description: Optionally add newly created users to this group.
|
||||||
required:
|
required:
|
||||||
- component
|
- component
|
||||||
- name
|
- name
|
||||||
|
@ -29302,6 +29317,11 @@ components:
|
||||||
create_users_as_inactive:
|
create_users_as_inactive:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: When set, newly created users are inactive and cannot login.
|
description: When set, newly created users are inactive and cannot login.
|
||||||
|
create_users_group:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
description: Optionally add newly created users to this group.
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
ValidationError:
|
ValidationError:
|
||||||
|
|
|
@ -1888,6 +1888,7 @@ msgstr "Go to previous page"
|
||||||
#: src/pages/policies/PolicyBindingForm.ts
|
#: src/pages/policies/PolicyBindingForm.ts
|
||||||
#: src/pages/policies/PolicyBindingForm.ts
|
#: src/pages/policies/PolicyBindingForm.ts
|
||||||
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
#: src/pages/stages/user_write/UserWriteStageForm.ts
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr "Group"
|
msgstr "Group"
|
||||||
|
|
||||||
|
@ -2371,6 +2372,7 @@ msgstr "Loading"
|
||||||
#: src/pages/stages/password/PasswordStageForm.ts
|
#: src/pages/stages/password/PasswordStageForm.ts
|
||||||
#: src/pages/stages/prompt/PromptStageForm.ts
|
#: src/pages/stages/prompt/PromptStageForm.ts
|
||||||
#: src/pages/stages/prompt/PromptStageForm.ts
|
#: src/pages/stages/prompt/PromptStageForm.ts
|
||||||
|
#: src/pages/stages/user_write/UserWriteStageForm.ts
|
||||||
#: src/pages/tenants/TenantForm.ts
|
#: src/pages/tenants/TenantForm.ts
|
||||||
#: src/pages/tenants/TenantForm.ts
|
#: src/pages/tenants/TenantForm.ts
|
||||||
#: src/pages/tenants/TenantForm.ts
|
#: src/pages/tenants/TenantForm.ts
|
||||||
|
@ -2644,6 +2646,10 @@ msgstr "Negates the outcome of the binding. Messages are unaffected."
|
||||||
msgid "New version available!"
|
msgid "New version available!"
|
||||||
msgstr "New version available!"
|
msgstr "New version available!"
|
||||||
|
|
||||||
|
#: src/pages/stages/user_write/UserWriteStageForm.ts
|
||||||
|
msgid "Newly created users are added to this group, if a group is selected."
|
||||||
|
msgstr "Newly created users are added to this group, if a group is selected."
|
||||||
|
|
||||||
#: src/elements/oauth/UserRefreshList.ts
|
#: src/elements/oauth/UserRefreshList.ts
|
||||||
#: src/pages/applications/ApplicationCheckAccessForm.ts
|
#: src/pages/applications/ApplicationCheckAccessForm.ts
|
||||||
#: src/pages/crypto/CertificateKeyPairListPage.ts
|
#: src/pages/crypto/CertificateKeyPairListPage.ts
|
||||||
|
|
|
@ -1880,6 +1880,7 @@ msgstr ""
|
||||||
#: src/pages/policies/PolicyBindingForm.ts
|
#: src/pages/policies/PolicyBindingForm.ts
|
||||||
#: src/pages/policies/PolicyBindingForm.ts
|
#: src/pages/policies/PolicyBindingForm.ts
|
||||||
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
#: src/pages/stages/user_write/UserWriteStageForm.ts
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2363,6 +2364,7 @@ msgstr ""
|
||||||
#: src/pages/stages/password/PasswordStageForm.ts
|
#: src/pages/stages/password/PasswordStageForm.ts
|
||||||
#: src/pages/stages/prompt/PromptStageForm.ts
|
#: src/pages/stages/prompt/PromptStageForm.ts
|
||||||
#: src/pages/stages/prompt/PromptStageForm.ts
|
#: src/pages/stages/prompt/PromptStageForm.ts
|
||||||
|
#: src/pages/stages/user_write/UserWriteStageForm.ts
|
||||||
#: src/pages/tenants/TenantForm.ts
|
#: src/pages/tenants/TenantForm.ts
|
||||||
#: src/pages/tenants/TenantForm.ts
|
#: src/pages/tenants/TenantForm.ts
|
||||||
#: src/pages/tenants/TenantForm.ts
|
#: src/pages/tenants/TenantForm.ts
|
||||||
|
@ -2636,6 +2638,10 @@ msgstr ""
|
||||||
msgid "New version available!"
|
msgid "New version available!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/pages/stages/user_write/UserWriteStageForm.ts
|
||||||
|
msgid "Newly created users are added to this group, if a group is selected."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/elements/oauth/UserRefreshList.ts
|
#: src/elements/oauth/UserRefreshList.ts
|
||||||
#: src/pages/applications/ApplicationCheckAccessForm.ts
|
#: src/pages/applications/ApplicationCheckAccessForm.ts
|
||||||
#: src/pages/crypto/CertificateKeyPairListPage.ts
|
#: src/pages/crypto/CertificateKeyPairListPage.ts
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { UserWriteStage, StagesApi } from "@goauthentik/api";
|
import { UserWriteStage, StagesApi, CoreApi } from "@goauthentik/api";
|
||||||
import { t } from "@lingui/macro";
|
import { t } from "@lingui/macro";
|
||||||
import { customElement } from "lit-element";
|
import { customElement } from "lit-element";
|
||||||
import { html, TemplateResult } from "lit-html";
|
import { html, TemplateResult } from "lit-html";
|
||||||
|
@ -8,6 +8,7 @@ import "../../../elements/forms/HorizontalFormElement";
|
||||||
import "../../../elements/forms/FormGroup";
|
import "../../../elements/forms/FormGroup";
|
||||||
import { ModelForm } from "../../../elements/forms/ModelForm";
|
import { ModelForm } from "../../../elements/forms/ModelForm";
|
||||||
import { first } from "../../../utils";
|
import { first } from "../../../utils";
|
||||||
|
import { until } from "lit-html/directives/until";
|
||||||
|
|
||||||
@customElement("ak-stage-user-write-form")
|
@customElement("ak-stage-user-write-form")
|
||||||
export class UserWriteStageForm extends ModelForm<UserWriteStage, string> {
|
export class UserWriteStageForm extends ModelForm<UserWriteStage, string> {
|
||||||
|
@ -70,6 +71,33 @@ export class UserWriteStageForm extends ModelForm<UserWriteStage, string> {
|
||||||
${t`Mark newly created users as inactive.`}
|
${t`Mark newly created users as inactive.`}
|
||||||
</p>
|
</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
|
<ak-form-element-horizontal label=${t`Group`} name="searchGroup">
|
||||||
|
<select class="pf-c-form-control">
|
||||||
|
<option
|
||||||
|
value=""
|
||||||
|
?selected=${this.instance?.createUsersGroup === undefined}
|
||||||
|
>
|
||||||
|
---------
|
||||||
|
</option>
|
||||||
|
${until(
|
||||||
|
new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then((groups) => {
|
||||||
|
return groups.results.map((group) => {
|
||||||
|
return html`<option
|
||||||
|
value=${ifDefined(group.pk)}
|
||||||
|
?selected=${this.instance?.createUsersGroup ===
|
||||||
|
group.pk}
|
||||||
|
>
|
||||||
|
${group.name}
|
||||||
|
</option>`;
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
html`<option>${t`Loading...`}</option>`,
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
<p class="pf-c-form__helper-text">
|
||||||
|
${t`Newly created users are added to this group, if a group is selected.`}
|
||||||
|
</p>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
</div>
|
</div>
|
||||||
</ak-form-group>
|
</ak-form-group>
|
||||||
</form>`;
|
</form>`;
|
||||||
|
|
Reference in a new issue