Skip to content

Commit

Permalink
stages/user_write: allow setting user type when creating new user (#7…
Browse files Browse the repository at this point in the history
…293)

Signed-off-by: Jens Langhammer <[email protected]>
  • Loading branch information
BeryJu authored Oct 26, 2023
1 parent 94ad839 commit 2805305
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 5 deletions.
1 change: 1 addition & 0 deletions authentik/stages/user_write/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Meta:
"user_creation_mode",
"create_users_as_inactive",
"create_users_group",
"user_type",
"user_path_template",
]

Expand Down
Original file line number Diff line number Diff line change
@@ -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",
),
),
]
6 changes: 5 additions & 1 deletion authentik/stages/user_write/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
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


Expand Down Expand Up @@ -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,
Expand Down
17 changes: 16 additions & 1 deletion authentik/stages/user_write/stage.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
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
Expand All @@ -22,6 +22,7 @@
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"


Expand Down Expand Up @@ -55,6 +56,19 @@ def ensure_user(self) -> tuple[Optional[User], bool]:
)
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 (
Expand All @@ -66,6 +80,7 @@ def ensure_user(self) -> tuple[Optional[User], bool]:
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(
Expand Down
10 changes: 10 additions & 0 deletions blueprints/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
20 changes: 20 additions & 0 deletions schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
45 changes: 44 additions & 1 deletion web/src/admin/stages/user_write/UserWriteStageForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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"
Expand Down
3 changes: 1 addition & 2 deletions web/src/admin/users/UserForm.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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> {
Expand Down
9 changes: 9 additions & 0 deletions web/xliff/fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7930,6 +7930,15 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
<target>&lt;No name set&gt;</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>
Expand Down
8 changes: 8 additions & 0 deletions website/docs/flow/context/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 2805305

Please sign in to comment.