stages/user_write: allow setting user type when creating new user (#7293)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
		| @ -15,6 +15,7 @@ class UserWriteStageSerializer(StageSerializer): | ||||
|             "user_creation_mode", | ||||
|             "create_users_as_inactive", | ||||
|             "create_users_group", | ||||
|             "user_type", | ||||
|             "user_path_template", | ||||
|         ] | ||||
|  | ||||
|  | ||||
| @ -0,0 +1,25 @@ | ||||
| # Generated by Django 4.2.6 on 2023-10-25 15:19 | ||||
|  | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|     dependencies = [ | ||||
|         ("authentik_stages_user_write", "0007_remove_userwritestage_can_create_users_and_more"), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name="userwritestage", | ||||
|             name="user_type", | ||||
|             field=models.TextField( | ||||
|                 choices=[ | ||||
|                     ("internal", "Internal"), | ||||
|                     ("external", "External"), | ||||
|                     ("service_account", "Service Account"), | ||||
|                     ("internal_service_account", "Internal Service Account"), | ||||
|                 ], | ||||
|                 default="external", | ||||
|             ), | ||||
|         ), | ||||
|     ] | ||||
| @ -5,7 +5,7 @@ from django.utils.translation import gettext_lazy as _ | ||||
| from django.views import View | ||||
| from rest_framework.serializers import BaseSerializer | ||||
|  | ||||
| from authentik.core.models import Group | ||||
| from authentik.core.models import Group, UserTypes | ||||
| from authentik.flows.models import Stage | ||||
|  | ||||
|  | ||||
| @ -39,6 +39,10 @@ class UserWriteStage(Stage): | ||||
|         help_text=_("Optionally add newly created users to this group."), | ||||
|     ) | ||||
|  | ||||
|     user_type = models.TextField( | ||||
|         choices=UserTypes.choices, | ||||
|         default=UserTypes.EXTERNAL, | ||||
|     ) | ||||
|     user_path_template = models.TextField( | ||||
|         default="", | ||||
|         blank=True, | ||||
|  | ||||
| @ -9,7 +9,7 @@ from django.utils.translation import gettext as _ | ||||
| from rest_framework.exceptions import ValidationError | ||||
|  | ||||
| from authentik.core.middleware import SESSION_KEY_IMPERSONATE_USER | ||||
| from authentik.core.models import USER_ATTRIBUTE_SOURCES, User, UserSourceConnection | ||||
| from authentik.core.models import USER_ATTRIBUTE_SOURCES, User, UserSourceConnection, UserTypes | ||||
| from authentik.core.sources.stage import PLAN_CONTEXT_SOURCES_CONNECTION | ||||
| from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER | ||||
| from authentik.flows.stage import StageView | ||||
| @ -22,6 +22,7 @@ from authentik.stages.user_write.models import UserCreationMode | ||||
| from authentik.stages.user_write.signals import user_write | ||||
|  | ||||
| PLAN_CONTEXT_GROUPS = "groups" | ||||
| PLAN_CONTEXT_USER_TYPE = "user_type" | ||||
| PLAN_CONTEXT_USER_PATH = "user_path" | ||||
|  | ||||
|  | ||||
| @ -55,6 +56,19 @@ class UserWriteStageView(StageView): | ||||
|         ) | ||||
|         if path == "": | ||||
|             path = User.default_path() | ||||
|  | ||||
|         try: | ||||
|             user_type = UserTypes( | ||||
|                 self.executor.plan.context.get( | ||||
|                     PLAN_CONTEXT_USER_TYPE, | ||||
|                     self.executor.current_stage.user_type, | ||||
|                 ) | ||||
|             ) | ||||
|         except ValueError: | ||||
|             user_type = self.executor.current_stage.user_type | ||||
|         if user_type == UserTypes.INTERNAL_SERVICE_ACCOUNT: | ||||
|             user_type = UserTypes.SERVICE_ACCOUNT | ||||
|  | ||||
|         if not self.request.user.is_anonymous: | ||||
|             self.executor.plan.context.setdefault(PLAN_CONTEXT_PENDING_USER, self.request.user) | ||||
|         if ( | ||||
| @ -66,6 +80,7 @@ class UserWriteStageView(StageView): | ||||
|             self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = User( | ||||
|                 is_active=not self.executor.current_stage.create_users_as_inactive, | ||||
|                 path=path, | ||||
|                 type=user_type, | ||||
|             ) | ||||
|             self.executor.plan.context[PLAN_CONTEXT_AUTHENTICATION_BACKEND] = BACKEND_INBUILT | ||||
|             self.logger.debug( | ||||
|  | ||||
| @ -8368,6 +8368,16 @@ | ||||
|                     "title": "Create users group", | ||||
|                     "description": "Optionally add newly created users to this group." | ||||
|                 }, | ||||
|                 "user_type": { | ||||
|                     "type": "string", | ||||
|                     "enum": [ | ||||
|                         "internal", | ||||
|                         "external", | ||||
|                         "service_account", | ||||
|                         "internal_service_account" | ||||
|                     ], | ||||
|                     "title": "User type" | ||||
|                 }, | ||||
|                 "user_path_template": { | ||||
|                     "type": "string", | ||||
|                     "title": "User path template" | ||||
|  | ||||
							
								
								
									
										20
									
								
								schema.yml
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								schema.yml
									
									
									
									
									
								
							| @ -27494,6 +27494,20 @@ paths: | ||||
|         name: user_path_template | ||||
|         schema: | ||||
|           type: string | ||||
|       - in: query | ||||
|         name: user_type | ||||
|         schema: | ||||
|           type: string | ||||
|           enum: | ||||
|           - external | ||||
|           - internal | ||||
|           - internal_service_account | ||||
|           - service_account | ||||
|         description: |- | ||||
|           * `internal` - Internal | ||||
|           * `external` - External | ||||
|           * `service_account` - Service Account | ||||
|           * `internal_service_account` - Internal Service Account | ||||
|       tags: | ||||
|       - stages | ||||
|       security: | ||||
| @ -38052,6 +38066,8 @@ components: | ||||
|           format: uuid | ||||
|           nullable: true | ||||
|           description: Optionally add newly created users to this group. | ||||
|         user_type: | ||||
|           $ref: '#/components/schemas/UserTypeEnum' | ||||
|         user_path_template: | ||||
|           type: string | ||||
|     PatchedWebAuthnDeviceRequest: | ||||
| @ -42422,6 +42438,8 @@ components: | ||||
|           format: uuid | ||||
|           nullable: true | ||||
|           description: Optionally add newly created users to this group. | ||||
|         user_type: | ||||
|           $ref: '#/components/schemas/UserTypeEnum' | ||||
|         user_path_template: | ||||
|           type: string | ||||
|       required: | ||||
| @ -42452,6 +42470,8 @@ components: | ||||
|           format: uuid | ||||
|           nullable: true | ||||
|           description: Optionally add newly created users to this group. | ||||
|         user_type: | ||||
|           $ref: '#/components/schemas/UserTypeEnum' | ||||
|         user_path_template: | ||||
|           type: string | ||||
|       required: | ||||
|  | ||||
| @ -12,7 +12,14 @@ import { TemplateResult, html } from "lit"; | ||||
| import { customElement } from "lit/decorators.js"; | ||||
| import { ifDefined } from "lit/directives/if-defined.js"; | ||||
|  | ||||
| import { CoreApi, CoreGroupsListRequest, Group, StagesApi, UserWriteStage } from "@goauthentik/api"; | ||||
| import { | ||||
|     CoreApi, | ||||
|     CoreGroupsListRequest, | ||||
|     Group, | ||||
|     StagesApi, | ||||
|     UserTypeEnum, | ||||
|     UserWriteStage, | ||||
| } from "@goauthentik/api"; | ||||
|  | ||||
| @customElement("ak-stage-user-write-form") | ||||
| export class UserWriteStageForm extends ModelForm<UserWriteStage, string> { | ||||
| @ -111,6 +118,42 @@ export class UserWriteStageForm extends ModelForm<UserWriteStage, string> { | ||||
|                             ${msg("Mark newly created users as inactive.")} | ||||
|                         </p> | ||||
|                     </ak-form-element-horizontal> | ||||
|                     <ak-form-element-horizontal | ||||
|                         label=${msg("User path template")} | ||||
|                         name="userPathTemplate" | ||||
|                     > | ||||
|                         <ak-radio | ||||
|                             .options=${[ | ||||
|                                 { | ||||
|                                     label: "Internal", | ||||
|                                     value: UserTypeEnum.Internal, | ||||
|                                     default: true, | ||||
|                                     description: html`${msg( | ||||
|                                         "Internal users might be users such as company employees, which will get access to the full Enterprise feature set.", | ||||
|                                     )}`, | ||||
|                                 }, | ||||
|                                 { | ||||
|                                     label: "External", | ||||
|                                     value: UserTypeEnum.External, | ||||
|                                     description: html`${msg( | ||||
|                                         "External users might be external consultants or B2C customers. These users don't get access to enterprise features.", | ||||
|                                     )}`, | ||||
|                                 }, | ||||
|                                 { | ||||
|                                     label: "Service account", | ||||
|                                     value: UserTypeEnum.ServiceAccount, | ||||
|                                     description: html`${msg( | ||||
|                                         "Service accounts should be used for machine-to-machine authentication or other automations.", | ||||
|                                     )}`, | ||||
|                                 }, | ||||
|                             ]} | ||||
|                             .value=${this.instance?.userType} | ||||
|                         > | ||||
|                         </ak-radio> | ||||
|                         <p class="pf-c-form__helper-text"> | ||||
|                             ${msg("User type used for newly created users.")} | ||||
|                         </p> | ||||
|                     </ak-form-element-horizontal> | ||||
|                     <ak-form-element-horizontal | ||||
|                         label=${msg("User path template")} | ||||
|                         name="userPathTemplate" | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| import "@goauthentik/admin/users/GroupSelectModal"; | ||||
| import { UserTypeEnum } from "@goauthentik/api/dist/models/UserTypeEnum"; | ||||
| import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; | ||||
| import { first } from "@goauthentik/common/utils"; | ||||
| import "@goauthentik/elements/CodeMirror"; | ||||
| @ -14,7 +13,7 @@ import { CSSResult, TemplateResult, css, html } from "lit"; | ||||
| import { customElement } from "lit/decorators.js"; | ||||
| import { ifDefined } from "lit/directives/if-defined.js"; | ||||
|  | ||||
| import { CoreApi, User } from "@goauthentik/api"; | ||||
| import { CoreApi, User, UserTypeEnum } from "@goauthentik/api"; | ||||
|  | ||||
| @customElement("ak-user-form") | ||||
| export class UserForm extends ModelForm<User, number> { | ||||
|  | ||||
| @ -7930,6 +7930,15 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti | ||||
| <trans-unit id="s0924f51b028233a3"> | ||||
|   <source><No name set></source> | ||||
|   <target><No name set></target> | ||||
| </trans-unit> | ||||
| <trans-unit id="s66313b45b69cfc88"> | ||||
|   <source>Check the release notes</source> | ||||
| </trans-unit> | ||||
| <trans-unit id="sb4d7bae2440d9781"> | ||||
|   <source>User Statistics</source> | ||||
| </trans-unit> | ||||
| <trans-unit id="s32babfed740fd3c1"> | ||||
|   <source>User type used for newly created users.</source> | ||||
| </trans-unit> | ||||
|     </body> | ||||
|   </file> | ||||
|  | ||||
| @ -120,6 +120,14 @@ If set, this must be a list of group objects and not group names. | ||||
|  | ||||
| Path the `pending_user` will be written to. If not set in the flow, falls back to the value set in the user_write stage, and otherwise to the `users` path. | ||||
|  | ||||
| ##### `user_type` (string) | ||||
|  | ||||
| :::info | ||||
| Requires authentik 2023.10 | ||||
| ::: | ||||
|  | ||||
| Type the `pending_user` will be created as. Must be one of `internal`, `external` or `service_account`. | ||||
|  | ||||
| #### Password stage | ||||
|  | ||||
| ##### `user_backend` (string) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens L
					Jens L