mirror of
https://github.com/goauthentik/authentik
synced 2026-05-05 22:52:42 +02:00
Compare commits
24 Commits
sdko/stage
...
enterprise
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d22c39e8e | ||
|
|
e939d60e18 | ||
|
|
88c458ba3b | ||
|
|
014e0516c3 | ||
|
|
4647294541 | ||
|
|
084194207d | ||
|
|
685684c89a | ||
|
|
f495747b2a | ||
|
|
6222531f2d | ||
|
|
787cdfb8f2 | ||
|
|
b761fd8c6d | ||
|
|
3ce09b96d7 | ||
|
|
0f3925bb4e | ||
|
|
498ebe8840 | ||
|
|
1aa57f732b | ||
|
|
77123ffce7 | ||
|
|
7919569056 | ||
|
|
4e09e82b2f | ||
|
|
1687949d71 | ||
|
|
5ed8444840 | ||
|
|
8447fad9c8 | ||
|
|
dd9c5cde6e | ||
|
|
66716b8296 | ||
|
|
7c65b8a8d3 |
@@ -1,5 +1,6 @@
|
||||
"""Tokens API Viewset"""
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
from django.utils.timezone import now
|
||||
@@ -18,12 +19,15 @@ from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.users import UserSerializer
|
||||
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
USER_ATTRIBUTE_TOKEN_EXPIRING,
|
||||
USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME,
|
||||
Token,
|
||||
TokenIntents,
|
||||
User,
|
||||
UserTypes,
|
||||
default_token_duration,
|
||||
default_token_key,
|
||||
)
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.events.utils import model_to_dict
|
||||
@@ -171,6 +175,40 @@ class TokenViewSet(UsedByMixin, ModelViewSet):
|
||||
Event.new(EventAction.SECRET_VIEW, secret=token).from_http(request) # noqa # nosec
|
||||
return Response(TokenViewSerializer({"key": token.key}).data)
|
||||
|
||||
@extend_schema(
|
||||
request=None,
|
||||
responses={
|
||||
200: TokenViewSerializer(many=False),
|
||||
403: OpenApiResponse(description="Not the token owner, agent owner, or superuser"),
|
||||
},
|
||||
)
|
||||
@action(detail=True, pagination_class=None, filter_backends=[], methods=["POST"])
|
||||
def rotate(self, request: Request, identifier: str) -> Response:
|
||||
"""Rotate the token key and reset the expiry to 24 hours. Only callable by the token
|
||||
owner, the owning agent's human owner, or a superuser."""
|
||||
token = (
|
||||
Token.objects.including_expired()
|
||||
.select_related("user")
|
||||
.filter(identifier=identifier)
|
||||
.first()
|
||||
)
|
||||
if not token:
|
||||
return Response(status=404)
|
||||
|
||||
if not request.user.is_superuser:
|
||||
is_token_owner = token.user_id == request.user.pk
|
||||
is_agent_owner = token.user.type == UserTypes.AGENT and str(
|
||||
request.user.pk
|
||||
) == token.user.attributes.get(USER_ATTRIBUTE_AGENT_OWNER_PK)
|
||||
if not is_token_owner and not is_agent_owner:
|
||||
return Response(status=403)
|
||||
|
||||
token.key = default_token_key()
|
||||
token.expires = now() + timedelta(hours=24)
|
||||
token.save()
|
||||
Event.new(EventAction.SECRET_ROTATE, secret=token).from_http(request) # noqa # nosec
|
||||
return Response(TokenViewSerializer({"key": token.key}).data)
|
||||
|
||||
@permission_required("authentik_core.set_token_key")
|
||||
@extend_schema(
|
||||
request=TokenSetKeySerializer(),
|
||||
|
||||
@@ -75,9 +75,13 @@ from authentik.core.middleware import (
|
||||
SESSION_KEY_IMPERSONATE_USER,
|
||||
)
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS,
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
USER_ATTRIBUTE_TOKEN_EXPIRING,
|
||||
USER_PATH_AGENT,
|
||||
USER_PATH_SERVICE_ACCOUNT,
|
||||
USERNAME_MAX_LENGTH,
|
||||
Application,
|
||||
Group,
|
||||
Session,
|
||||
Token,
|
||||
@@ -88,6 +92,7 @@ from authentik.core.models import (
|
||||
)
|
||||
from authentik.endpoints.connectors.agent.auth import AgentAuth
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.events.utils import model_to_dict, sanitize_dict
|
||||
from authentik.flows.exceptions import FlowNonApplicableException
|
||||
from authentik.flows.models import FlowToken
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner
|
||||
@@ -249,8 +254,25 @@ class UserSerializer(ModelSerializer):
|
||||
raise ValidationError(_("Can't change internal service account to other user type."))
|
||||
if not self.instance and user_type == UserTypes.INTERNAL_SERVICE_ACCOUNT.value:
|
||||
raise ValidationError(_("Setting a user to internal service account is not allowed."))
|
||||
if (
|
||||
self.instance
|
||||
and self.instance.type == UserTypes.AGENT
|
||||
and user_type != UserTypes.AGENT.value
|
||||
):
|
||||
raise ValidationError(_("Can't change agent user type."))
|
||||
return user_type
|
||||
|
||||
def validate_attributes(self, attrs: dict) -> dict:
|
||||
"""Prevent changes to agent owner"""
|
||||
if not self.instance:
|
||||
return attrs
|
||||
if self.instance.type == UserTypes.AGENT:
|
||||
existing_owner = self.instance.attributes.get(USER_ATTRIBUTE_AGENT_OWNER_PK)
|
||||
new_owner = attrs.get(USER_ATTRIBUTE_AGENT_OWNER_PK)
|
||||
if existing_owner is not None and new_owner != existing_owner:
|
||||
raise ValidationError(_("Can't change owner of agent user."))
|
||||
return attrs
|
||||
|
||||
def validate(self, attrs: dict) -> dict:
|
||||
if self.instance and self.instance.type == UserTypes.INTERNAL_SERVICE_ACCOUNT:
|
||||
raise ValidationError(_("Can't modify internal service account users"))
|
||||
@@ -405,6 +427,26 @@ class UserServiceAccountSerializer(PassiveSerializer):
|
||||
)
|
||||
|
||||
|
||||
class UserAgentSerializer(PassiveSerializer):
|
||||
"""Payload to create an agent user"""
|
||||
|
||||
name = CharField(max_length=150)
|
||||
owner = PrimaryKeyRelatedField(queryset=User.objects.all(), required=False, default=None)
|
||||
|
||||
|
||||
class UserAgentAllowedAppsSerializer(PassiveSerializer):
|
||||
"""Payload to replace an agent's allowed applications"""
|
||||
|
||||
allowed_apps = ListField(child=UUIDField())
|
||||
|
||||
|
||||
class UserAgentAllowedAppSerializer(PassiveSerializer):
|
||||
"""Payload to add or remove a single allowed application"""
|
||||
|
||||
app = UUIDField()
|
||||
action = ChoiceField(choices=[("add", "Add"), ("remove", "Remove")])
|
||||
|
||||
|
||||
class UserRecoveryLinkSerializer(PassiveSerializer):
|
||||
"""Payload to create a recovery link"""
|
||||
|
||||
@@ -691,6 +733,260 @@ class UserViewSet(
|
||||
status=500,
|
||||
)
|
||||
|
||||
@permission_required(
|
||||
None,
|
||||
["authentik_core.add_user", "authentik_core.add_token", "authentik_core.add_agent_user"],
|
||||
)
|
||||
@extend_schema(
|
||||
request=UserAgentSerializer,
|
||||
responses={
|
||||
200: inline_serializer(
|
||||
"UserAgentResponse",
|
||||
{
|
||||
"username": CharField(required=True),
|
||||
"token": CharField(required=True),
|
||||
"user_uid": CharField(required=True),
|
||||
"user_pk": IntegerField(required=True),
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
@action(
|
||||
detail=False,
|
||||
methods=["POST"],
|
||||
pagination_class=None,
|
||||
filter_backends=[],
|
||||
)
|
||||
@validate(UserAgentSerializer)
|
||||
def agent(self, request: Request, body: UserAgentSerializer) -> Response:
|
||||
"""Create a new agent user. Enterprise only. Caller must be an internal user."""
|
||||
from authentik.enterprise.license import LicenseKey
|
||||
|
||||
if not LicenseKey.cached_summary().status.is_valid:
|
||||
raise ValidationError(_("Enterprise is required to use this endpoint."))
|
||||
|
||||
if request.user.type != UserTypes.INTERNAL:
|
||||
raise ValidationError(_("Only internal users can create agent users."))
|
||||
|
||||
requested_owner = body.validated_data.get("owner")
|
||||
if requested_owner and not request.user.is_superuser:
|
||||
if requested_owner.pk != request.user.pk:
|
||||
raise ValidationError(
|
||||
_("Non-superusers can only create agents owned by themselves.")
|
||||
)
|
||||
owner = requested_owner or request.user
|
||||
|
||||
username = body.validated_data["name"]
|
||||
with atomic():
|
||||
try:
|
||||
user: User = User.objects.create(
|
||||
username=username,
|
||||
name=username,
|
||||
type=UserTypes.AGENT,
|
||||
attributes={
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK: str(owner.pk),
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS: [],
|
||||
},
|
||||
path=USER_PATH_AGENT,
|
||||
)
|
||||
user.set_unusable_password()
|
||||
user.save()
|
||||
|
||||
token = Token.objects.create(
|
||||
identifier=slugify(f"agent-{username}-token"),
|
||||
intent=TokenIntents.INTENT_API,
|
||||
user=user,
|
||||
expires=now() + timedelta(hours=24),
|
||||
expiring=True,
|
||||
)
|
||||
user.assign_perms_to_managed_role("authentik_core.view_token_key", token)
|
||||
|
||||
owner.assign_perms_to_managed_role("authentik_core.view_user", user)
|
||||
owner.assign_perms_to_managed_role("authentik_core.change_user", user)
|
||||
owner.assign_perms_to_managed_role("authentik_core.delete_user", user)
|
||||
owner.assign_perms_to_managed_role("authentik_core.view_user_applications", user)
|
||||
|
||||
Event.new(
|
||||
EventAction.MODEL_CREATED,
|
||||
model=sanitize_dict(model_to_dict(user)),
|
||||
agent_owner=sanitize_dict(model_to_dict(owner)),
|
||||
).from_http(request)
|
||||
|
||||
return Response(
|
||||
{
|
||||
"username": user.username,
|
||||
"user_uid": user.uid,
|
||||
"user_pk": user.pk,
|
||||
"token": token.key,
|
||||
}
|
||||
)
|
||||
except IntegrityError as exc:
|
||||
error_msg = str(exc).lower()
|
||||
if "unique" in error_msg:
|
||||
return Response(
|
||||
data={"non_field_errors": [_("A user with this username already exists")]},
|
||||
status=400,
|
||||
)
|
||||
else:
|
||||
LOGGER.warning("Agent user creation failed", exc=exc)
|
||||
return Response(
|
||||
data={"non_field_errors": [_("Unable to create user")]},
|
||||
status=400,
|
||||
)
|
||||
except (ValueError, TypeError) as exc:
|
||||
LOGGER.error("Unexpected error during agent user creation", exc=exc)
|
||||
return Response(
|
||||
data={"non_field_errors": [_("Unknown error occurred")]},
|
||||
status=500,
|
||||
)
|
||||
|
||||
@extend_schema(
|
||||
request=UserAgentAllowedAppsSerializer,
|
||||
responses={
|
||||
200: UserAgentAllowedAppsSerializer,
|
||||
400: OpenApiResponse(description="Invalid app UUIDs or owner lacks access"),
|
||||
403: OpenApiResponse(description="Not the agent's owner or superuser"),
|
||||
},
|
||||
)
|
||||
@action(
|
||||
detail=True,
|
||||
methods=["PUT"],
|
||||
url_path="agent_allowed_apps",
|
||||
url_name="agent-allowed-apps",
|
||||
pagination_class=None,
|
||||
filter_backends=[],
|
||||
)
|
||||
@validate(UserAgentAllowedAppsSerializer)
|
||||
def agent_allowed_apps(
|
||||
self, request: Request, pk: int, body: UserAgentAllowedAppsSerializer
|
||||
) -> Response:
|
||||
"""Replace the allowed application list for an agent user.
|
||||
Caller must be the agent's owner or a superuser."""
|
||||
from authentik.core.apps import AppAccessWithoutBindings
|
||||
from authentik.policies.engine import PolicyEngine
|
||||
|
||||
agent, owner = self._get_agent_and_owner(request)
|
||||
|
||||
app_uuids = body.validated_data["allowed_apps"]
|
||||
errors = []
|
||||
for app_uuid in app_uuids:
|
||||
try:
|
||||
app = Application.objects.get(pk=app_uuid)
|
||||
except Application.DoesNotExist:
|
||||
errors.append(str(app_uuid))
|
||||
continue
|
||||
engine = PolicyEngine(app, owner, request)
|
||||
engine.empty_result = AppAccessWithoutBindings.get()
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
if not engine.passing:
|
||||
errors.append(str(app_uuid))
|
||||
|
||||
if errors:
|
||||
return Response(
|
||||
data={
|
||||
"allowed_apps": [
|
||||
_(
|
||||
"Owner does not have access to application %(uuid)s "
|
||||
"or application does not exist."
|
||||
)
|
||||
% {"uuid": uuid}
|
||||
for uuid in errors
|
||||
]
|
||||
},
|
||||
status=400,
|
||||
)
|
||||
|
||||
agent.attributes[USER_ATTRIBUTE_AGENT_ALLOWED_APPS] = [str(u) for u in app_uuids]
|
||||
agent.save(update_fields=["attributes"])
|
||||
return Response({"allowed_apps": [str(u) for u in app_uuids]})
|
||||
|
||||
@extend_schema(
|
||||
request=UserAgentAllowedAppSerializer,
|
||||
responses={
|
||||
200: UserAgentAllowedAppsSerializer,
|
||||
204: OpenApiResponse(description="Application removed"),
|
||||
400: OpenApiResponse(description="Invalid app UUID or owner lacks access"),
|
||||
403: OpenApiResponse(description="Not the agent's owner or superuser"),
|
||||
},
|
||||
)
|
||||
@action(
|
||||
detail=True,
|
||||
methods=["PATCH"],
|
||||
url_path="agent_allowed_app",
|
||||
url_name="agent-allowed-app",
|
||||
pagination_class=None,
|
||||
filter_backends=[],
|
||||
)
|
||||
@validate(UserAgentAllowedAppSerializer)
|
||||
def agent_allowed_app(
|
||||
self, request: Request, pk: int, body: UserAgentAllowedAppSerializer
|
||||
) -> Response:
|
||||
"""Add or remove a single application from an agent's allowed list.
|
||||
Caller must be the agent's owner or a superuser."""
|
||||
from authentik.core.apps import AppAccessWithoutBindings
|
||||
from authentik.policies.engine import PolicyEngine
|
||||
|
||||
agent, owner = self._get_agent_and_owner(request)
|
||||
|
||||
app_uuid = str(body.validated_data["app"])
|
||||
action = body.validated_data["action"]
|
||||
current = agent.attributes.get(USER_ATTRIBUTE_AGENT_ALLOWED_APPS, [])
|
||||
|
||||
if action == "add":
|
||||
try:
|
||||
app = Application.objects.get(pk=app_uuid)
|
||||
except Application.DoesNotExist:
|
||||
return Response(
|
||||
data={"app": [_("Application does not exist.")]},
|
||||
status=400,
|
||||
)
|
||||
engine = PolicyEngine(app, owner, request)
|
||||
engine.empty_result = AppAccessWithoutBindings.get()
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
if not engine.passing:
|
||||
return Response(
|
||||
data={"app": [_("Owner does not have access to this application.")]},
|
||||
status=400,
|
||||
)
|
||||
if app_uuid not in current:
|
||||
current.append(app_uuid)
|
||||
agent.attributes[USER_ATTRIBUTE_AGENT_ALLOWED_APPS] = current
|
||||
agent.save(update_fields=["attributes"])
|
||||
return Response({"allowed_apps": current})
|
||||
|
||||
if action == "remove":
|
||||
if app_uuid in current:
|
||||
current.remove(app_uuid)
|
||||
agent.attributes[USER_ATTRIBUTE_AGENT_ALLOWED_APPS] = current
|
||||
agent.save(update_fields=["attributes"])
|
||||
return Response(status=204)
|
||||
|
||||
return Response(
|
||||
data={"action": [_("Invalid action.")]},
|
||||
status=400,
|
||||
)
|
||||
|
||||
def _get_agent_and_owner(self, request: Request) -> tuple[User, User]:
|
||||
"""Validate that the target is an agent and the caller is authorized."""
|
||||
agent: User = self.get_object()
|
||||
|
||||
if agent.type != UserTypes.AGENT:
|
||||
raise ValidationError(_("User is not an agent user."))
|
||||
|
||||
owner_pk = agent.attributes.get(USER_ATTRIBUTE_AGENT_OWNER_PK)
|
||||
is_owner = str(request.user.pk) == owner_pk
|
||||
if not request.user.is_superuser and not is_owner:
|
||||
raise ValidationError(_("Not the agent's owner or superuser."))
|
||||
|
||||
try:
|
||||
owner = User.objects.get(pk=owner_pk)
|
||||
except User.DoesNotExist as exc:
|
||||
raise ValidationError(_("Agent owner not found.")) from exc
|
||||
|
||||
return agent, owner
|
||||
|
||||
@extend_schema(responses={200: SessionUserSerializer(many=False)})
|
||||
@action(
|
||||
url_path="me",
|
||||
|
||||
@@ -18,6 +18,7 @@ class Command(TenantCommand):
|
||||
User.objects.exclude_anonymous()
|
||||
.exclude(type=UserTypes.SERVICE_ACCOUNT)
|
||||
.exclude(type=UserTypes.INTERNAL_SERVICE_ACCOUNT)
|
||||
.exclude(type=UserTypes.AGENT)
|
||||
)
|
||||
if options["usernames"] and options["all"]:
|
||||
self.stderr.write("--all and usernames specified, only one can be specified")
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Generated by Django 5.2.13 on 2026-04-13 21:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_core", "0057_remove_user_groups_remove_user_user_permissions_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="user",
|
||||
options={
|
||||
"permissions": [
|
||||
("reset_user_password", "Reset Password"),
|
||||
("impersonate", "Can impersonate other users"),
|
||||
("preview_user", "Can preview user data sent to providers"),
|
||||
("view_user_applications", "View applications the user has access to"),
|
||||
("add_agent_user", "Can create agent users"),
|
||||
],
|
||||
"verbose_name": "User",
|
||||
"verbose_name_plural": "Users",
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="type",
|
||||
field=models.TextField(
|
||||
choices=[
|
||||
("internal", "Internal"),
|
||||
("external", "External"),
|
||||
("service_account", "Service Account"),
|
||||
("internal_service_account", "Internal Service Account"),
|
||||
("agent", "Agent"),
|
||||
],
|
||||
default="internal",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -67,6 +67,10 @@ USER_ATTRIBUTE_CHANGE_USERNAME = f"{_USER_ATTR_PREFIX}/can-change-username"
|
||||
USER_ATTRIBUTE_CHANGE_NAME = f"{_USER_ATTR_PREFIX}/can-change-name"
|
||||
USER_ATTRIBUTE_CHANGE_EMAIL = f"{_USER_ATTR_PREFIX}/can-change-email"
|
||||
USER_PATH_SERVICE_ACCOUNT = f"{USER_PATH_SYSTEM_PREFIX}/service-accounts"
|
||||
_USER_ATTR_AGENT_PREFIX = f"{USER_PATH_SYSTEM_PREFIX}/agent"
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK = f"{_USER_ATTR_AGENT_PREFIX}/owner-pk"
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS = f"{_USER_ATTR_AGENT_PREFIX}/allowed-apps"
|
||||
USER_PATH_AGENT = f"{USER_PATH_SYSTEM_PREFIX}/agents"
|
||||
|
||||
options.DEFAULT_NAMES = options.DEFAULT_NAMES + (
|
||||
# used_by API that allows models to specify if they shadow an object
|
||||
@@ -126,6 +130,9 @@ class UserTypes(models.TextChoices):
|
||||
# accounts, such as outpost users
|
||||
INTERNAL_SERVICE_ACCOUNT = "internal_service_account"
|
||||
|
||||
# Enterprise-gated agent users owned by an internal user
|
||||
AGENT = "agent"
|
||||
|
||||
|
||||
class AttributesMixin(models.Model):
|
||||
"""Adds an attributes property to a model"""
|
||||
@@ -385,6 +392,7 @@ class User(SerializerModel, AttributesMixin, AbstractUser):
|
||||
("impersonate", _("Can impersonate other users")),
|
||||
("preview_user", _("Can preview user data sent to providers")),
|
||||
("view_user_applications", _("View applications the user has access to")),
|
||||
("add_agent_user", _("Can create agent users")),
|
||||
]
|
||||
indexes = [
|
||||
models.Index(fields=["last_login"]),
|
||||
|
||||
@@ -11,12 +11,14 @@ from django.http.request import HttpRequest
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
Application,
|
||||
AuthenticatedSession,
|
||||
BackchannelProvider,
|
||||
ExpiringModel,
|
||||
Session,
|
||||
User,
|
||||
UserTypes,
|
||||
default_token_duration,
|
||||
)
|
||||
from authentik.flows.apps import RefreshOtherFlowsAfterAuthentication
|
||||
@@ -69,6 +71,35 @@ def authenticated_session_delete(sender: type[Model], instance: AuthenticatedSes
|
||||
Session.objects.filter(session_key=instance.pk).delete()
|
||||
|
||||
|
||||
def _agent_qs_for_owner(owner_pk: int):
|
||||
"""Return a queryset of agent users belonging to the given owner pk"""
|
||||
return User.objects.filter(
|
||||
type=UserTypes.AGENT,
|
||||
attributes__contains={USER_ATTRIBUTE_AGENT_OWNER_PK: str(owner_pk)},
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_delete, sender=User)
|
||||
def user_delete_cascade_agents(sender: type[Model], instance: User, **_):
|
||||
"""Delete agent users when their owner is deleted"""
|
||||
_agent_qs_for_owner(instance.pk).delete()
|
||||
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def user_save_propagate_agent_active(
|
||||
sender: type[Model], instance: User, update_fields: frozenset[str] | None = None, **_
|
||||
):
|
||||
"""Propagate is_active changes to owned agent users"""
|
||||
if update_fields is not None and "is_active" not in update_fields:
|
||||
return
|
||||
agents = _agent_qs_for_owner(instance.pk)
|
||||
if not instance.is_active:
|
||||
Session.objects.filter(
|
||||
authenticatedsession__user__in=agents.filter(is_active=True)
|
||||
).delete()
|
||||
agents.update(is_active=instance.is_active)
|
||||
|
||||
|
||||
@receiver(pre_save)
|
||||
def backchannel_provider_pre_save(sender: type[Model], instance: Model, **_):
|
||||
"""Ensure backchannel providers have is_backchannel set to true"""
|
||||
|
||||
84
authentik/core/tests/test_agent_session.py
Normal file
84
authentik/core/tests/test_agent_session.py
Normal file
@@ -0,0 +1,84 @@
|
||||
"""Test agent token-to-session exchange"""
|
||||
|
||||
from django.urls.base import reverse
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
USER_PATH_AGENT,
|
||||
Token,
|
||||
TokenIntents,
|
||||
User,
|
||||
UserTypes,
|
||||
)
|
||||
from authentik.core.tests.utils import create_test_user
|
||||
from authentik.lib.generators import generate_id
|
||||
|
||||
|
||||
class TestAgentSession(APITestCase):
|
||||
"""Test agent token-to-session exchange"""
|
||||
|
||||
def _create_agent_with_token(self):
|
||||
owner = create_test_user()
|
||||
agent = User.objects.create(
|
||||
username=generate_id(),
|
||||
type=UserTypes.AGENT,
|
||||
attributes={USER_ATTRIBUTE_AGENT_OWNER_PK: str(owner.pk)},
|
||||
path=USER_PATH_AGENT,
|
||||
)
|
||||
agent.set_unusable_password()
|
||||
agent.save()
|
||||
token = Token.objects.create(
|
||||
identifier=generate_id(),
|
||||
intent=TokenIntents.INTENT_API,
|
||||
user=agent,
|
||||
expiring=True,
|
||||
)
|
||||
return owner, agent, token
|
||||
|
||||
def test_session_exchange_success(self):
|
||||
"""Valid agent token creates a session"""
|
||||
_owner, _agent, token = self._create_agent_with_token()
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:agent-session"),
|
||||
data={"key": token.key},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 204)
|
||||
|
||||
def test_session_exchange_invalid_token(self):
|
||||
"""Invalid token key is rejected"""
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:agent-session"),
|
||||
data={"key": "nonexistent-key"},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_session_exchange_non_agent(self):
|
||||
"""Token belonging to a non-agent user is rejected"""
|
||||
user = create_test_user()
|
||||
token = Token.objects.create(
|
||||
identifier=generate_id(),
|
||||
intent=TokenIntents.INTENT_API,
|
||||
user=user,
|
||||
expiring=True,
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:agent-session"),
|
||||
data={"key": token.key},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_session_exchange_inactive_agent(self):
|
||||
"""Inactive agent is rejected"""
|
||||
_owner, agent, token = self._create_agent_with_token()
|
||||
agent.is_active = False
|
||||
agent.save(update_fields=["is_active"])
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:agent-session"),
|
||||
data={"key": token.key},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
@@ -199,6 +199,50 @@ class TestTokenAPI(APITestCase):
|
||||
self.assertEqual(body["results"][0]["identifier"], token_should.identifier)
|
||||
self.assertEqual(body["results"][1]["identifier"], token_should_not.identifier)
|
||||
|
||||
def test_token_rotate_by_owner(self):
|
||||
"""Token owner can rotate their own token"""
|
||||
token = Token.objects.create(
|
||||
identifier=generate_id(),
|
||||
intent=TokenIntents.INTENT_API,
|
||||
user=self.user,
|
||||
expiring=True,
|
||||
)
|
||||
original_key = token.key
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:token-rotate", kwargs={"identifier": token.identifier}),
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
token.refresh_from_db()
|
||||
self.assertNotEqual(token.key, original_key)
|
||||
self.assertEqual(token.key, loads(response.content)["key"])
|
||||
|
||||
def test_token_rotate_by_superuser(self):
|
||||
"""Superuser can rotate any token"""
|
||||
token = Token.objects.create(
|
||||
identifier=generate_id(),
|
||||
intent=TokenIntents.INTENT_API,
|
||||
user=self.user,
|
||||
expiring=True,
|
||||
)
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:token-rotate", kwargs={"identifier": token.identifier}),
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_token_rotate_unauthorized(self):
|
||||
"""Non-owner cannot rotate another user's token"""
|
||||
token = Token.objects.create(
|
||||
identifier=generate_id(),
|
||||
intent=TokenIntents.INTENT_API,
|
||||
user=self.admin,
|
||||
expiring=True,
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:token-rotate", kwargs={"identifier": token.identifier}),
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_serializer_no_request(self):
|
||||
"""Test serializer without request"""
|
||||
self.assertTrue(
|
||||
|
||||
@@ -2,7 +2,14 @@
|
||||
|
||||
from django.test.testcases import TestCase
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
USER_PATH_AGENT,
|
||||
AuthenticatedSession,
|
||||
Session,
|
||||
User,
|
||||
UserTypes,
|
||||
)
|
||||
from authentik.events.models import Event
|
||||
from authentik.lib.generators import generate_id
|
||||
|
||||
@@ -33,3 +40,93 @@ class TestUsers(TestCase):
|
||||
self.assertEqual(Event.objects.count(), 1)
|
||||
user.ak_groups.all()
|
||||
self.assertEqual(Event.objects.count(), 1)
|
||||
|
||||
|
||||
class TestAgentUserSignals(TestCase):
|
||||
"""Test signals related to agent user lifecycle"""
|
||||
|
||||
def _create_owner(self):
|
||||
owner = User.objects.create(username=generate_id())
|
||||
owner.set_unusable_password()
|
||||
owner.save()
|
||||
return owner
|
||||
|
||||
def _create_agent(self, owner):
|
||||
agent = User.objects.create(
|
||||
username=generate_id(),
|
||||
type=UserTypes.AGENT,
|
||||
attributes={USER_ATTRIBUTE_AGENT_OWNER_PK: str(owner.pk)},
|
||||
path=USER_PATH_AGENT,
|
||||
)
|
||||
agent.set_unusable_password()
|
||||
agent.save()
|
||||
return agent
|
||||
|
||||
def test_delete_owner_cascades_to_agents(self):
|
||||
"""Deleting an owner also deletes all their agent users"""
|
||||
owner = self._create_owner()
|
||||
agent1 = self._create_agent(owner)
|
||||
agent2 = self._create_agent(owner)
|
||||
other_owner = self._create_owner()
|
||||
other_agent = self._create_agent(other_owner)
|
||||
|
||||
owner.delete()
|
||||
|
||||
self.assertFalse(User.objects.filter(pk=agent1.pk).exists())
|
||||
self.assertFalse(User.objects.filter(pk=agent2.pk).exists())
|
||||
self.assertTrue(User.objects.filter(pk=other_agent.pk).exists())
|
||||
|
||||
def test_deactivate_owner_deactivates_agents(self):
|
||||
"""Setting an owner inactive also marks all their agents inactive"""
|
||||
owner = self._create_owner()
|
||||
agent = self._create_agent(owner)
|
||||
|
||||
owner.is_active = False
|
||||
owner.save(update_fields=["is_active"])
|
||||
|
||||
agent.refresh_from_db()
|
||||
self.assertFalse(agent.is_active)
|
||||
|
||||
def test_reactivate_owner_reactivates_agents(self):
|
||||
"""Setting an owner active again also re-activates their agents"""
|
||||
owner = self._create_owner()
|
||||
owner.is_active = False
|
||||
owner.save(update_fields=["is_active"])
|
||||
agent = self._create_agent(owner)
|
||||
agent.is_active = False
|
||||
agent.save(update_fields=["is_active"])
|
||||
|
||||
owner.is_active = True
|
||||
owner.save(update_fields=["is_active"])
|
||||
|
||||
agent.refresh_from_db()
|
||||
self.assertTrue(agent.is_active)
|
||||
|
||||
def test_unrelated_owner_save_does_not_affect_agents(self):
|
||||
"""Saving an owner without changing is_active does not touch agents"""
|
||||
owner = self._create_owner()
|
||||
agent = self._create_agent(owner)
|
||||
agent.is_active = False
|
||||
agent.save(update_fields=["is_active"])
|
||||
|
||||
owner.name = generate_id()
|
||||
owner.save(update_fields=["name"])
|
||||
|
||||
agent.refresh_from_db()
|
||||
self.assertFalse(agent.is_active)
|
||||
|
||||
def test_deactivate_owner_clears_agent_sessions(self):
|
||||
"""Deactivating an owner removes authenticated sessions for their agents"""
|
||||
owner = self._create_owner()
|
||||
agent = self._create_agent(owner)
|
||||
session = Session.objects.create(
|
||||
session_key=generate_id(),
|
||||
last_ip="255.255.255.255",
|
||||
last_user_agent="",
|
||||
)
|
||||
AuthenticatedSession.objects.create(user=agent, session=session)
|
||||
|
||||
owner.is_active = False
|
||||
owner.save(update_fields=["is_active"])
|
||||
|
||||
self.assertFalse(Session.objects.filter(pk=session.pk).exists())
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from json import loads
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from django.urls.base import reverse
|
||||
from django.utils.timezone import now
|
||||
@@ -9,10 +10,15 @@ from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.brands.models import Brand
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS,
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
USER_ATTRIBUTE_TOKEN_EXPIRING,
|
||||
USER_PATH_AGENT,
|
||||
Application,
|
||||
AuthenticatedSession,
|
||||
Session,
|
||||
Token,
|
||||
TokenIntents,
|
||||
User,
|
||||
UserTypes,
|
||||
)
|
||||
@@ -878,3 +884,249 @@ class TestUsersAPI(APITestCase):
|
||||
self.assertIn(user2.pk, pks)
|
||||
# Verify user2 comes before user1 in descending order
|
||||
self.assertLess(pks.index(user2.pk), pks.index(user1.pk))
|
||||
|
||||
|
||||
class TestAgentUserAPI(APITestCase):
|
||||
"""Test agent user API"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.admin = create_test_admin_user()
|
||||
self.user = create_test_user()
|
||||
self.owner = create_test_user()
|
||||
self.owner.assign_perms_to_managed_role("authentik_core.add_agent_user")
|
||||
self.owner.assign_perms_to_managed_role("authentik_core.add_user")
|
||||
self.owner.assign_perms_to_managed_role("authentik_core.add_token")
|
||||
|
||||
def _create_agent(self, name="test-agent", owner=None):
|
||||
owner = owner or self.admin
|
||||
agent = User.objects.create(
|
||||
username=name,
|
||||
name=name,
|
||||
type=UserTypes.AGENT,
|
||||
attributes={
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK: str(owner.pk),
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS: [],
|
||||
},
|
||||
path=USER_PATH_AGENT,
|
||||
)
|
||||
agent.set_unusable_password()
|
||||
agent.save()
|
||||
return agent
|
||||
|
||||
def test_agent_create(self):
|
||||
"""Non-admin owner with correct permissions can create an agent"""
|
||||
self.client.force_login(self.owner)
|
||||
with patch(
|
||||
"authentik.enterprise.license.LicenseKey.cached_summary",
|
||||
MagicMock(return_value=MagicMock(status=MagicMock(is_valid=True))),
|
||||
):
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:user-agent"),
|
||||
data={"name": "test-agent"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
agent = User.objects.get(username="test-agent")
|
||||
self.assertEqual(agent.type, UserTypes.AGENT)
|
||||
self.assertEqual(agent.path, USER_PATH_AGENT)
|
||||
self.assertEqual(agent.attributes.get(USER_ATTRIBUTE_AGENT_OWNER_PK), str(self.owner.pk))
|
||||
self.assertEqual(agent.attributes.get(USER_ATTRIBUTE_AGENT_ALLOWED_APPS), [])
|
||||
self.assertFalse(agent.has_usable_password())
|
||||
token = Token.objects.filter(user=agent, intent=TokenIntents.INTENT_API).first()
|
||||
self.assertIsNotNone(token)
|
||||
self.assertTrue(token.expiring)
|
||||
|
||||
def test_agent_create_no_license(self):
|
||||
"""Agent creation is rejected without a valid enterprise license"""
|
||||
self.client.force_login(self.owner)
|
||||
with patch(
|
||||
"authentik.enterprise.license.LicenseKey.cached_summary",
|
||||
MagicMock(return_value=MagicMock(status=MagicMock(is_valid=False))),
|
||||
):
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:user-agent"),
|
||||
data={"name": "test-agent"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_agent_create_non_internal_user(self):
|
||||
"""Only internal users can create agent users"""
|
||||
self.owner.type = UserTypes.EXTERNAL
|
||||
self.owner.save(update_fields=["type"])
|
||||
self.client.force_login(self.owner)
|
||||
with patch(
|
||||
"authentik.enterprise.license.LicenseKey.cached_summary",
|
||||
MagicMock(return_value=MagicMock(status=MagicMock(is_valid=True))),
|
||||
):
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:user-agent"),
|
||||
data={"name": "test-agent"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_agent_create_no_permission(self):
|
||||
"""User without add_agent_user permission is rejected"""
|
||||
self.client.force_login(self.user)
|
||||
with patch(
|
||||
"authentik.enterprise.license.LicenseKey.cached_summary",
|
||||
MagicMock(return_value=MagicMock(status=MagicMock(is_valid=True))),
|
||||
):
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:user-agent"),
|
||||
data={"name": "test-agent"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_agent_create_duplicate(self):
|
||||
"""Duplicate agent username returns a user-friendly error"""
|
||||
self._create_agent("test-agent-dup")
|
||||
self.client.force_login(self.owner)
|
||||
with patch(
|
||||
"authentik.enterprise.license.LicenseKey.cached_summary",
|
||||
MagicMock(return_value=MagicMock(status=MagicMock(is_valid=True))),
|
||||
):
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:user-agent"),
|
||||
data={"name": "test-agent-dup"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_agent_type_cannot_be_changed(self):
|
||||
"""Agent user type cannot be changed via the users API"""
|
||||
agent = self._create_agent()
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.patch(
|
||||
reverse("authentik_api:user-detail", kwargs={"pk": agent.pk}),
|
||||
data={"type": UserTypes.INTERNAL},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_agent_owner_cannot_be_changed(self):
|
||||
"""Agent owner cannot be changed via the users API"""
|
||||
agent = self._create_agent()
|
||||
other = create_test_user()
|
||||
self.client.force_login(self.admin)
|
||||
new_attrs = dict(agent.attributes)
|
||||
new_attrs[USER_ATTRIBUTE_AGENT_OWNER_PK] = str(other.pk)
|
||||
response = self.client.patch(
|
||||
reverse("authentik_api:user-detail", kwargs={"pk": agent.pk}),
|
||||
data={"attributes": new_attrs},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_agent_allowed_apps_update(self):
|
||||
"""Owner can update the agent's allowed apps list"""
|
||||
agent = self._create_agent(owner=self.admin)
|
||||
app = Application.objects.create(name=generate_id(), slug=generate_id())
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.put(
|
||||
reverse("authentik_api:user-agent-allowed-apps", kwargs={"pk": agent.pk}),
|
||||
data={"allowed_apps": [str(app.pk)]},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
agent.refresh_from_db()
|
||||
self.assertIn(str(app.pk), agent.attributes[USER_ATTRIBUTE_AGENT_ALLOWED_APPS])
|
||||
|
||||
def test_agent_allowed_apps_update_unauthorized(self):
|
||||
"""Non-owner, non-superuser is rejected when updating allowed apps"""
|
||||
other = create_test_user()
|
||||
agent = self._create_agent(owner=other)
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.put(
|
||||
reverse("authentik_api:user-agent-allowed-apps", kwargs={"pk": agent.pk}),
|
||||
data={"allowed_apps": []},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_agent_allowed_apps_update_non_agent(self):
|
||||
"""Endpoint rejects non-agent users"""
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.put(
|
||||
reverse("authentik_api:user-agent-allowed-apps", kwargs={"pk": self.user.pk}),
|
||||
data={"allowed_apps": []},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_agent_allowed_app_add(self):
|
||||
"""PATCH add: owner can add a single app to agent's allowed list"""
|
||||
agent = self._create_agent(owner=self.admin)
|
||||
app = Application.objects.create(name=generate_id(), slug=generate_id())
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.patch(
|
||||
reverse("authentik_api:user-agent-allowed-app", kwargs={"pk": agent.pk}),
|
||||
data={"app": str(app.pk), "action": "add"},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
agent.refresh_from_db()
|
||||
self.assertIn(str(app.pk), agent.attributes[USER_ATTRIBUTE_AGENT_ALLOWED_APPS])
|
||||
|
||||
def test_agent_allowed_app_add_duplicate(self):
|
||||
"""PATCH add: adding an already-allowed app is idempotent"""
|
||||
agent = self._create_agent(owner=self.admin)
|
||||
app = Application.objects.create(name=generate_id(), slug=generate_id())
|
||||
agent.attributes[USER_ATTRIBUTE_AGENT_ALLOWED_APPS] = [str(app.pk)]
|
||||
agent.save(update_fields=["attributes"])
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.patch(
|
||||
reverse("authentik_api:user-agent-allowed-app", kwargs={"pk": agent.pk}),
|
||||
data={"app": str(app.pk), "action": "add"},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
agent.refresh_from_db()
|
||||
self.assertEqual(agent.attributes[USER_ATTRIBUTE_AGENT_ALLOWED_APPS].count(str(app.pk)), 1)
|
||||
|
||||
def test_agent_allowed_app_remove(self):
|
||||
"""PATCH remove: owner can remove a single app from agent's allowed list"""
|
||||
agent = self._create_agent(owner=self.admin)
|
||||
app = Application.objects.create(name=generate_id(), slug=generate_id())
|
||||
agent.attributes[USER_ATTRIBUTE_AGENT_ALLOWED_APPS] = [str(app.pk)]
|
||||
agent.save(update_fields=["attributes"])
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.patch(
|
||||
reverse("authentik_api:user-agent-allowed-app", kwargs={"pk": agent.pk}),
|
||||
data={"app": str(app.pk), "action": "remove"},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 204)
|
||||
agent.refresh_from_db()
|
||||
self.assertNotIn(str(app.pk), agent.attributes[USER_ATTRIBUTE_AGENT_ALLOWED_APPS])
|
||||
|
||||
def test_agent_allowed_app_add_nonexistent(self):
|
||||
"""PATCH add: nonexistent app UUID is rejected"""
|
||||
agent = self._create_agent(owner=self.admin)
|
||||
self.client.force_login(self.admin)
|
||||
response = self.client.patch(
|
||||
reverse("authentik_api:user-agent-allowed-app", kwargs={"pk": agent.pk}),
|
||||
data={"app": "00000000-0000-0000-0000-000000000000", "action": "add"},
|
||||
content_type="application/json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_token_rotate_by_agent_owner(self):
|
||||
"""Non-admin owner can rotate the agent's token"""
|
||||
self.client.force_login(self.owner)
|
||||
with patch(
|
||||
"authentik.enterprise.license.LicenseKey.cached_summary",
|
||||
MagicMock(return_value=MagicMock(status=MagicMock(is_valid=True))),
|
||||
):
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:user-agent"),
|
||||
data={"name": "rotate-test-agent"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
token = Token.objects.get(
|
||||
user__username="rotate-test-agent", intent=TokenIntents.INTENT_API
|
||||
)
|
||||
original_key = token.key
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:token-rotate", kwargs={"identifier": token.identifier}),
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
token.refresh_from_db()
|
||||
self.assertNotEqual(token.key, original_key)
|
||||
|
||||
@@ -19,6 +19,7 @@ from authentik.core.api.sources import (
|
||||
from authentik.core.api.tokens import TokenViewSet
|
||||
from authentik.core.api.transactional_applications import TransactionalApplicationView
|
||||
from authentik.core.api.users import UserViewSet
|
||||
from authentik.core.views.agent_session import AgentSessionView
|
||||
from authentik.core.views.apps import RedirectToAppLaunch
|
||||
from authentik.core.views.debug import AccessDeniedView
|
||||
from authentik.core.views.interface import (
|
||||
@@ -79,6 +80,11 @@ api_urlpatterns = [
|
||||
TransactionalApplicationView.as_view(),
|
||||
name="core-transactional-application",
|
||||
),
|
||||
path(
|
||||
"core/agent/session/",
|
||||
AgentSessionView.as_view(),
|
||||
name="agent-session",
|
||||
),
|
||||
("core/groups", GroupViewSet),
|
||||
("core/users", UserViewSet),
|
||||
("core/tokens", TokenViewSet),
|
||||
|
||||
50
authentik/core/views/agent_session.py
Normal file
50
authentik/core/views/agent_session.py
Normal file
@@ -0,0 +1,50 @@
|
||||
"""Agent token-to-session exchange view"""
|
||||
|
||||
from django.contrib.auth import login
|
||||
from rest_framework.authentication import BaseAuthentication
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from authentik.core.models import AuthenticatedSession, Token, TokenIntents, UserTypes
|
||||
from authentik.stages.password import BACKEND_INBUILT
|
||||
|
||||
|
||||
class NoAuthentication(BaseAuthentication):
|
||||
"""Explicitly skip DRF authentication; the view authenticates via the request body."""
|
||||
|
||||
def authenticate(self, request):
|
||||
return None
|
||||
|
||||
|
||||
class AgentSessionView(APIView):
|
||||
"""Exchange an agent's API token for an authenticated session."""
|
||||
|
||||
authentication_classes = [NoAuthentication]
|
||||
permission_classes = [AllowAny]
|
||||
|
||||
def post(self, request: Request) -> Response:
|
||||
key = request.data.get("key")
|
||||
if not key:
|
||||
return Response({"detail": "Key is required."}, status=400)
|
||||
|
||||
token = (
|
||||
Token.objects.filter(key=key, intent=TokenIntents.INTENT_API)
|
||||
.select_related("user")
|
||||
.first()
|
||||
)
|
||||
if not token:
|
||||
return Response({"detail": "Invalid token."}, status=400)
|
||||
if token.is_expired:
|
||||
return Response({"detail": "Token has expired."}, status=403)
|
||||
if token.user.type != UserTypes.AGENT:
|
||||
return Response({"detail": "Token does not belong to an agent user."}, status=400)
|
||||
if not token.user.is_active:
|
||||
return Response({"detail": "Agent user is inactive."}, status=403)
|
||||
|
||||
login(request._request, token.user, backend=BACKEND_INBUILT)
|
||||
session = AuthenticatedSession.from_request(request._request, token.user)
|
||||
if session:
|
||||
session.save()
|
||||
return Response(status=204)
|
||||
@@ -30,6 +30,7 @@ class RootRedirectView(RedirectView):
|
||||
UserTypes.EXTERNAL,
|
||||
UserTypes.SERVICE_ACCOUNT,
|
||||
UserTypes.INTERNAL_SERVICE_ACCOUNT,
|
||||
UserTypes.AGENT,
|
||||
):
|
||||
brand: Brand = request.brand
|
||||
if brand.default_application:
|
||||
@@ -70,6 +71,7 @@ class BrandDefaultRedirectView(InterfaceView):
|
||||
UserTypes.EXTERNAL,
|
||||
UserTypes.SERVICE_ACCOUNT,
|
||||
UserTypes.INTERNAL_SERVICE_ACCOUNT,
|
||||
UserTypes.AGENT,
|
||||
):
|
||||
brand: Brand = request.brand
|
||||
if brand.default_application:
|
||||
|
||||
@@ -141,8 +141,10 @@ class GoogleWorkspaceProvider(OutgoingSyncProvider, BackchannelProvider):
|
||||
# according to the provider's settings
|
||||
base = User.objects.all().exclude_anonymous().filter(**kwargs)
|
||||
if self.exclude_users_service_account:
|
||||
base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude(
|
||||
type=UserTypes.INTERNAL_SERVICE_ACCOUNT
|
||||
base = (
|
||||
base.exclude(type=UserTypes.SERVICE_ACCOUNT)
|
||||
.exclude(type=UserTypes.INTERNAL_SERVICE_ACCOUNT)
|
||||
.exclude(type=UserTypes.AGENT)
|
||||
)
|
||||
if self.filter_group:
|
||||
base = base.filter(groups__in=[self.filter_group])
|
||||
|
||||
@@ -130,8 +130,10 @@ class MicrosoftEntraProvider(OutgoingSyncProvider, BackchannelProvider):
|
||||
# according to the provider's settings
|
||||
base = User.objects.all().exclude_anonymous().filter(**kwargs)
|
||||
if self.exclude_users_service_account:
|
||||
base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude(
|
||||
type=UserTypes.INTERNAL_SERVICE_ACCOUNT
|
||||
base = (
|
||||
base.exclude(type=UserTypes.SERVICE_ACCOUNT)
|
||||
.exclude(type=UserTypes.INTERNAL_SERVICE_ACCOUNT)
|
||||
.exclude(type=UserTypes.AGENT)
|
||||
)
|
||||
if self.filter_group:
|
||||
base = base.filter(groups__in=[self.filter_group])
|
||||
|
||||
@@ -6,6 +6,18 @@ from dramatiq.actor import actor
|
||||
from authentik.enterprise.license import LicenseKey
|
||||
|
||||
|
||||
def _deactivate_agent_users():
|
||||
"""Mark all active agent users inactive and remove their sessions when the enterprise
|
||||
license is not valid. Called after each license usage recording."""
|
||||
from authentik.core.models import Session, User, UserTypes
|
||||
|
||||
agents = User.objects.filter(type=UserTypes.AGENT, is_active=True)
|
||||
Session.objects.filter(authenticatedsession__user__in=agents).delete()
|
||||
agents.update(is_active=False)
|
||||
|
||||
|
||||
@actor(description=_("Update enterprise license status."))
|
||||
def enterprise_update_usage():
|
||||
LicenseKey.get_total().record_usage()
|
||||
usage = LicenseKey.get_total().record_usage()
|
||||
if not usage.status.is_valid:
|
||||
_deactivate_agent_users()
|
||||
|
||||
64
authentik/enterprise/tests/test_tasks.py
Normal file
64
authentik/enterprise/tests/test_tasks.py
Normal file
@@ -0,0 +1,64 @@
|
||||
"""Enterprise task tests"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
USER_PATH_AGENT,
|
||||
User,
|
||||
UserTypes,
|
||||
)
|
||||
from authentik.lib.generators import generate_id
|
||||
|
||||
|
||||
class TestDeactivateAgentUsers(TestCase):
|
||||
"""Tests for _deactivate_agent_users enterprise task"""
|
||||
|
||||
def _create_agent(self, owner):
|
||||
agent = User.objects.create(
|
||||
username=generate_id(),
|
||||
type=UserTypes.AGENT,
|
||||
attributes={USER_ATTRIBUTE_AGENT_OWNER_PK: str(owner.pk)},
|
||||
path=USER_PATH_AGENT,
|
||||
is_active=True,
|
||||
)
|
||||
agent.set_unusable_password()
|
||||
agent.save()
|
||||
return agent
|
||||
|
||||
def test_deactivates_all_active_agents(self):
|
||||
"""_deactivate_agent_users marks all active agent users inactive"""
|
||||
from authentik.enterprise.tasks import _deactivate_agent_users
|
||||
|
||||
owner = User.objects.create(username=generate_id())
|
||||
agent1 = self._create_agent(owner)
|
||||
agent2 = self._create_agent(owner)
|
||||
|
||||
_deactivate_agent_users()
|
||||
|
||||
agent1.refresh_from_db()
|
||||
agent2.refresh_from_db()
|
||||
self.assertFalse(agent1.is_active)
|
||||
self.assertFalse(agent2.is_active)
|
||||
|
||||
def test_does_not_deactivate_non_agents(self):
|
||||
"""_deactivate_agent_users does not affect non-agent service accounts"""
|
||||
from authentik.enterprise.tasks import _deactivate_agent_users
|
||||
|
||||
sa = User.objects.create(
|
||||
username=generate_id(),
|
||||
type=UserTypes.SERVICE_ACCOUNT,
|
||||
is_active=True,
|
||||
)
|
||||
internal = User.objects.create(
|
||||
username=generate_id(),
|
||||
type=UserTypes.INTERNAL,
|
||||
is_active=True,
|
||||
)
|
||||
|
||||
_deactivate_agent_users()
|
||||
|
||||
sa.refresh_from_db()
|
||||
internal.refresh_from_db()
|
||||
self.assertTrue(sa.is_active)
|
||||
self.assertTrue(internal.is_active)
|
||||
@@ -31,7 +31,7 @@ from authentik.policies.types import PolicyRequest
|
||||
# Special keys which are *not* cleaned, even when the default filter
|
||||
# is matched
|
||||
ALLOWED_SPECIAL_KEYS = re.compile(
|
||||
r"passing|password_change_date|^auth_method(_args)?$",
|
||||
r"passing|password_change_date|^auth_method(_args)?$|^goauthentik\.io/agent/",
|
||||
flags=re.I,
|
||||
)
|
||||
|
||||
|
||||
@@ -202,9 +202,51 @@ class PolicyEngine:
|
||||
).observe(proc_info.result._exec_time)
|
||||
return self
|
||||
|
||||
def _check_agent_access(self) -> PolicyResult | None:
|
||||
"""For agent users accessing an Application, enforce allowed_apps + owner access.
|
||||
Returns a deny PolicyResult if the agent should be blocked, or None to continue
|
||||
with normal policy evaluation."""
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS,
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
Application,
|
||||
UserTypes,
|
||||
)
|
||||
|
||||
user = self.request.user
|
||||
if not hasattr(user, "type") or user.type != UserTypes.AGENT:
|
||||
return None
|
||||
if not isinstance(self.__pbm, Application):
|
||||
return None
|
||||
|
||||
allowed_apps = user.attributes.get(USER_ATTRIBUTE_AGENT_ALLOWED_APPS, [])
|
||||
if str(self.__pbm.pk) not in allowed_apps:
|
||||
return PolicyResult(False, "Agent does not have access to this application.")
|
||||
|
||||
owner_pk = user.attributes.get(USER_ATTRIBUTE_AGENT_OWNER_PK)
|
||||
if not owner_pk:
|
||||
return PolicyResult(False, "Agent has no owner configured.")
|
||||
|
||||
owner = User.objects.filter(pk=owner_pk).first()
|
||||
if not owner:
|
||||
return PolicyResult(False, "Agent owner does not exist.")
|
||||
|
||||
from authentik.core.apps import AppAccessWithoutBindings
|
||||
|
||||
owner_engine = PolicyEngine(self.__pbm, owner)
|
||||
owner_engine.empty_result = AppAccessWithoutBindings.get()
|
||||
owner_engine.use_cache = False
|
||||
owner_engine.build()
|
||||
if not owner_engine.passing:
|
||||
return PolicyResult(False, "Agent owner does not have access to this application.")
|
||||
return None
|
||||
|
||||
@property
|
||||
def result(self) -> PolicyResult:
|
||||
"""Get policy-checking result"""
|
||||
agent_result = self._check_agent_access()
|
||||
if agent_result is not None:
|
||||
return agent_result
|
||||
self.__processes.sort(key=lambda x: x.binding.order)
|
||||
process_results: list[PolicyResult] = [x.result for x in self.__processes if x.result]
|
||||
all_results = list(process_results + self.__cached_policies)
|
||||
|
||||
@@ -50,6 +50,12 @@ class PolicyEvaluator(BaseEvaluator):
|
||||
self._context["ak_client_ip"] = ip_address(
|
||||
request.obj.client_ip or ClientIPMiddleware.default_ip
|
||||
)
|
||||
from authentik.core.models import Application # noqa: PLC0415
|
||||
|
||||
if request.obj and isinstance(request.obj, Application):
|
||||
self._context["has_access_to_application"] = self._make_has_access_to_application(
|
||||
request
|
||||
)
|
||||
|
||||
def set_http_request(self, request: HttpRequest):
|
||||
"""Update context based on http request"""
|
||||
@@ -58,6 +64,46 @@ class PolicyEvaluator(BaseEvaluator):
|
||||
self._context["ak_client_ip"] = ip_address(ClientIPMiddleware.get_client_ip(request))
|
||||
self._context["http_request"] = request
|
||||
|
||||
def _make_has_access_to_application(self, request: PolicyRequest):
|
||||
"""Return a no-argument callable that checks whether the current agent user's owner
|
||||
has access to the application currently being evaluated (request.obj)."""
|
||||
|
||||
def has_access_to_application() -> bool:
|
||||
from authentik.core.apps import AppAccessWithoutBindings
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS,
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
User,
|
||||
UserTypes,
|
||||
)
|
||||
from authentik.policies.engine import PolicyEngine
|
||||
|
||||
user = request.user
|
||||
app = request.obj
|
||||
|
||||
if user.type != UserTypes.AGENT:
|
||||
return False
|
||||
|
||||
owner_pk = user.attributes.get(USER_ATTRIBUTE_AGENT_OWNER_PK)
|
||||
if not owner_pk:
|
||||
return False
|
||||
|
||||
allowed_apps = user.attributes.get(USER_ATTRIBUTE_AGENT_ALLOWED_APPS, [])
|
||||
if str(app.pk) not in allowed_apps:
|
||||
return False
|
||||
|
||||
owner = User.objects.filter(pk=owner_pk).first()
|
||||
if not owner:
|
||||
return False
|
||||
|
||||
engine = PolicyEngine(app, owner)
|
||||
engine.empty_result = AppAccessWithoutBindings.get()
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
return engine.passing
|
||||
|
||||
return has_access_to_application
|
||||
|
||||
def handle_error(self, exc: Exception, expression_source: str):
|
||||
"""Exception Handler"""
|
||||
raise PolicyException(exc)
|
||||
|
||||
@@ -5,7 +5,14 @@ from guardian.shortcuts import get_anonymous_user
|
||||
from rest_framework.serializers import ValidationError
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.core.models import Application
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS,
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
USER_PATH_AGENT,
|
||||
Application,
|
||||
User,
|
||||
UserTypes,
|
||||
)
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.policies.exceptions import PolicyException
|
||||
from authentik.policies.expression.api import ExpressionPolicySerializer
|
||||
@@ -135,6 +142,84 @@ class TestEvaluator(TestCase):
|
||||
self.assertEqual(res.messages, ("/", "/", "/"))
|
||||
|
||||
|
||||
class TestHasAccessToApplication(TestCase):
|
||||
"""Tests for has_access_to_application policy context helper"""
|
||||
|
||||
def setUp(self):
|
||||
self.factory = RequestFactory()
|
||||
self.app = Application.objects.create(name=generate_id(), slug=generate_id())
|
||||
self.owner = User.objects.create(username=generate_id())
|
||||
|
||||
def _create_agent(self, allowed_apps=None):
|
||||
return User.objects.create(
|
||||
username=generate_id(),
|
||||
type=UserTypes.AGENT,
|
||||
attributes={
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK: str(self.owner.pk),
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS: allowed_apps if allowed_apps is not None else [],
|
||||
},
|
||||
path=USER_PATH_AGENT,
|
||||
)
|
||||
|
||||
def _evaluator_with(self, user, obj=None):
|
||||
request = PolicyRequest(user=user)
|
||||
request.obj = obj or self.app
|
||||
request.http_request = self.factory.get("/")
|
||||
evaluator = PolicyEvaluator("test")
|
||||
evaluator.set_policy_request(request)
|
||||
return evaluator
|
||||
|
||||
def test_not_injected_for_non_application_obj(self):
|
||||
"""has_access_to_application is not injected when obj is not an Application"""
|
||||
agent = self._create_agent(allowed_apps=[str(self.app.pk)])
|
||||
request = PolicyRequest(user=agent)
|
||||
request.obj = None
|
||||
evaluator = PolicyEvaluator("test")
|
||||
evaluator.set_policy_request(request)
|
||||
self.assertNotIn("has_access_to_application", evaluator._context)
|
||||
|
||||
def test_injected_for_application_obj(self):
|
||||
"""has_access_to_application is injected when obj is an Application"""
|
||||
agent = self._create_agent(allowed_apps=[str(self.app.pk)])
|
||||
evaluator = self._evaluator_with(agent)
|
||||
self.assertIn("has_access_to_application", evaluator._context)
|
||||
|
||||
def test_non_agent_returns_false(self):
|
||||
"""Returns False when the current user is not an agent"""
|
||||
evaluator = self._evaluator_with(self.owner)
|
||||
result = evaluator._context["has_access_to_application"]()
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_app_not_in_allowed_list_returns_false(self):
|
||||
"""Returns False when the application is not in the agent's allowed apps list"""
|
||||
agent = self._create_agent(allowed_apps=[])
|
||||
evaluator = self._evaluator_with(agent)
|
||||
result = evaluator._context["has_access_to_application"]()
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_missing_owner_returns_false(self):
|
||||
"""Returns False when the owner pk points to a non-existent user"""
|
||||
agent = User.objects.create(
|
||||
username=generate_id(),
|
||||
type=UserTypes.AGENT,
|
||||
attributes={
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK: "999999",
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS: [str(self.app.pk)],
|
||||
},
|
||||
path=USER_PATH_AGENT,
|
||||
)
|
||||
evaluator = self._evaluator_with(agent)
|
||||
result = evaluator._context["has_access_to_application"]()
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_no_attributes_returns_false(self):
|
||||
"""Returns False when the user has no attributes"""
|
||||
user = get_anonymous_user()
|
||||
evaluator = self._evaluator_with(user)
|
||||
result = evaluator._context["has_access_to_application"]()
|
||||
self.assertFalse(result)
|
||||
|
||||
|
||||
class TestExpressionPolicyAPI(APITestCase):
|
||||
"""Test expression policy's API"""
|
||||
|
||||
|
||||
@@ -5,7 +5,15 @@ from django.db import connections
|
||||
from django.test import TestCase
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
|
||||
from authentik.core.models import Group
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS,
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK,
|
||||
USER_PATH_AGENT,
|
||||
Application,
|
||||
Group,
|
||||
User,
|
||||
UserTypes,
|
||||
)
|
||||
from authentik.core.tests.utils import create_test_user
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.policies.dummy.models import DummyPolicy
|
||||
@@ -209,3 +217,93 @@ class TestPolicyEngine(TestCase):
|
||||
engine.build()
|
||||
self.assertLess(ctx.final_queries, 1000)
|
||||
self.assertTrue(engine.result.passing)
|
||||
|
||||
def test_anonymous_user(self):
|
||||
"""AnonymousUser (no type attribute) does not break policy evaluation"""
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
|
||||
pbm = PolicyBindingModel.objects.create()
|
||||
engine = PolicyEngine(pbm, AnonymousUser())
|
||||
engine.empty_result = True
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
self.assertTrue(engine.passing)
|
||||
|
||||
|
||||
class TestPolicyEngineAgent(TestCase):
|
||||
"""PolicyEngine agent access enforcement tests"""
|
||||
|
||||
def setUp(self):
|
||||
clear_policy_cache()
|
||||
self.owner = create_test_user()
|
||||
self.app = Application.objects.create(name=generate_id(), slug=generate_id())
|
||||
|
||||
def _create_agent(self, allowed_apps=None):
|
||||
return User.objects.create(
|
||||
username=generate_id(),
|
||||
type=UserTypes.AGENT,
|
||||
attributes={
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK: str(self.owner.pk),
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS: allowed_apps if allowed_apps is not None else [],
|
||||
},
|
||||
path=USER_PATH_AGENT,
|
||||
)
|
||||
|
||||
def test_agent_allowed_app_passes(self):
|
||||
"""Agent with app in allowed_apps and owner access passes"""
|
||||
agent = self._create_agent(allowed_apps=[str(self.app.pk)])
|
||||
engine = PolicyEngine(self.app, agent)
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
self.assertTrue(engine.passing)
|
||||
|
||||
def test_agent_disallowed_app_denied(self):
|
||||
"""Agent without app in allowed_apps is denied"""
|
||||
agent = self._create_agent(allowed_apps=[])
|
||||
engine = PolicyEngine(self.app, agent)
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
self.assertFalse(engine.passing)
|
||||
|
||||
def test_agent_empty_allowed_apps_denied(self):
|
||||
"""Agent with empty allowed_apps is denied even for unbound apps"""
|
||||
agent = self._create_agent()
|
||||
engine = PolicyEngine(self.app, agent)
|
||||
engine.empty_result = True
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
self.assertFalse(engine.passing)
|
||||
|
||||
def test_non_agent_unaffected(self):
|
||||
"""Non-agent users are not affected by agent access check"""
|
||||
engine = PolicyEngine(self.app, self.owner)
|
||||
engine.empty_result = True
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
self.assertTrue(engine.passing)
|
||||
|
||||
def test_agent_missing_owner_denied(self):
|
||||
"""Agent with non-existent owner is denied"""
|
||||
agent = User.objects.create(
|
||||
username=generate_id(),
|
||||
type=UserTypes.AGENT,
|
||||
attributes={
|
||||
USER_ATTRIBUTE_AGENT_OWNER_PK: "999999",
|
||||
USER_ATTRIBUTE_AGENT_ALLOWED_APPS: [str(self.app.pk)],
|
||||
},
|
||||
path=USER_PATH_AGENT,
|
||||
)
|
||||
engine = PolicyEngine(self.app, agent)
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
self.assertFalse(engine.passing)
|
||||
|
||||
def test_agent_non_application_target_unaffected(self):
|
||||
"""Agent check only applies to Application targets"""
|
||||
agent = self._create_agent(allowed_apps=[])
|
||||
pbm = PolicyBindingModel.objects.create()
|
||||
engine = PolicyEngine(pbm, agent)
|
||||
engine.empty_result = True
|
||||
engine.use_cache = False
|
||||
engine.build()
|
||||
self.assertTrue(engine.passing)
|
||||
|
||||
@@ -188,8 +188,10 @@ class SCIMProvider(OutgoingSyncProvider, BackchannelProvider):
|
||||
# according to the provider's settings
|
||||
base = User.objects.all().exclude_anonymous().filter(**kwargs)
|
||||
if self.exclude_users_service_account:
|
||||
base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude(
|
||||
type=UserTypes.INTERNAL_SERVICE_ACCOUNT
|
||||
base = (
|
||||
base.exclude(type=UserTypes.SERVICE_ACCOUNT)
|
||||
.exclude(type=UserTypes.INTERNAL_SERVICE_ACCOUNT)
|
||||
.exclude(type=UserTypes.AGENT)
|
||||
)
|
||||
|
||||
# Filter users by their access to the backchannel application if an application is set
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Generated by Django 5.2.13 on 2026-04-13 21:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_stages_user_write", "0008_userwritestage_user_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="userwritestage",
|
||||
name="user_type",
|
||||
field=models.TextField(
|
||||
choices=[
|
||||
("internal", "Internal"),
|
||||
("external", "External"),
|
||||
("service_account", "Service Account"),
|
||||
("internal_service_account", "Internal Service Account"),
|
||||
("agent", "Agent"),
|
||||
],
|
||||
default="external",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -5520,7 +5520,8 @@
|
||||
"internal",
|
||||
"external",
|
||||
"service_account",
|
||||
"internal_service_account"
|
||||
"internal_service_account",
|
||||
"agent"
|
||||
],
|
||||
"title": "Type"
|
||||
},
|
||||
@@ -5545,6 +5546,7 @@
|
||||
"authentik_brands.change_brand",
|
||||
"authentik_brands.delete_brand",
|
||||
"authentik_brands.view_brand",
|
||||
"authentik_core.add_agent_user",
|
||||
"authentik_core.add_application",
|
||||
"authentik_core.add_applicationentitlement",
|
||||
"authentik_core.add_authenticatedsession",
|
||||
@@ -6257,6 +6259,7 @@
|
||||
"permission": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"add_agent_user",
|
||||
"add_user",
|
||||
"change_user",
|
||||
"delete_user",
|
||||
@@ -11212,6 +11215,7 @@
|
||||
"authentik_brands.change_brand",
|
||||
"authentik_brands.delete_brand",
|
||||
"authentik_brands.view_brand",
|
||||
"authentik_core.add_agent_user",
|
||||
"authentik_core.add_application",
|
||||
"authentik_core.add_applicationentitlement",
|
||||
"authentik_core.add_authenticatedsession",
|
||||
@@ -15976,7 +15980,8 @@
|
||||
"internal",
|
||||
"external",
|
||||
"service_account",
|
||||
"internal_service_account"
|
||||
"internal_service_account",
|
||||
"agent"
|
||||
],
|
||||
"title": "User type"
|
||||
},
|
||||
|
||||
585
packages/client-go/api_core.go
generated
585
packages/client-go/api_core.go
generated
@@ -25,6 +25,115 @@ import (
|
||||
// CoreAPIService CoreAPI service
|
||||
type CoreAPIService service
|
||||
|
||||
type ApiCoreAgentSessionCreateRequest struct {
|
||||
ctx context.Context
|
||||
ApiService *CoreAPIService
|
||||
}
|
||||
|
||||
func (r ApiCoreAgentSessionCreateRequest) Execute() (*http.Response, error) {
|
||||
return r.ApiService.CoreAgentSessionCreateExecute(r)
|
||||
}
|
||||
|
||||
/*
|
||||
CoreAgentSessionCreate Method for CoreAgentSessionCreate
|
||||
|
||||
Exchange an agent's API token for an authenticated session.
|
||||
|
||||
@param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
|
||||
@return ApiCoreAgentSessionCreateRequest
|
||||
*/
|
||||
func (a *CoreAPIService) CoreAgentSessionCreate(ctx context.Context) ApiCoreAgentSessionCreateRequest {
|
||||
return ApiCoreAgentSessionCreateRequest{
|
||||
ApiService: a,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute executes the request
|
||||
func (a *CoreAPIService) CoreAgentSessionCreateExecute(r ApiCoreAgentSessionCreateRequest) (*http.Response, error) {
|
||||
var (
|
||||
localVarHTTPMethod = http.MethodPost
|
||||
localVarPostBody interface{}
|
||||
formFiles []formFile
|
||||
)
|
||||
|
||||
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CoreAPIService.CoreAgentSessionCreate")
|
||||
if err != nil {
|
||||
return nil, &GenericOpenAPIError{error: err.Error()}
|
||||
}
|
||||
|
||||
localVarPath := localBasePath + "/core/agent/session/"
|
||||
|
||||
localVarHeaderParams := make(map[string]string)
|
||||
localVarQueryParams := url.Values{}
|
||||
localVarFormParams := url.Values{}
|
||||
|
||||
// to determine the Content-Type header
|
||||
localVarHTTPContentTypes := []string{}
|
||||
|
||||
// set Content-Type header
|
||||
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
|
||||
if localVarHTTPContentType != "" {
|
||||
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
localVarHTTPHeaderAccepts := []string{"application/json"}
|
||||
|
||||
// set Accept header
|
||||
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
|
||||
if localVarHTTPHeaderAccept != "" {
|
||||
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
|
||||
}
|
||||
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
localVarHTTPResponse, err := a.client.callAPI(req)
|
||||
if err != nil || localVarHTTPResponse == nil {
|
||||
return localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
localVarBody, err := io.ReadAll(localVarHTTPResponse.Body)
|
||||
localVarHTTPResponse.Body.Close()
|
||||
localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody))
|
||||
if err != nil {
|
||||
return localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
if localVarHTTPResponse.StatusCode >= 300 {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: localVarHTTPResponse.Status,
|
||||
}
|
||||
if localVarHTTPResponse.StatusCode == 400 {
|
||||
var v ValidationError
|
||||
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr.error = err.Error()
|
||||
return localVarHTTPResponse, newErr
|
||||
}
|
||||
newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v)
|
||||
newErr.model = v
|
||||
return localVarHTTPResponse, newErr
|
||||
}
|
||||
if localVarHTTPResponse.StatusCode == 403 {
|
||||
var v GenericError
|
||||
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr.error = err.Error()
|
||||
return localVarHTTPResponse, newErr
|
||||
}
|
||||
newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v)
|
||||
newErr.model = v
|
||||
}
|
||||
return localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
return localVarHTTPResponse, nil
|
||||
}
|
||||
|
||||
type ApiCoreApplicationEntitlementsCreateRequest struct {
|
||||
ctx context.Context
|
||||
ApiService *CoreAPIService
|
||||
@@ -6066,6 +6175,121 @@ func (a *CoreAPIService) CoreTokensRetrieveExecute(r ApiCoreTokensRetrieveReques
|
||||
return localVarReturnValue, localVarHTTPResponse, nil
|
||||
}
|
||||
|
||||
type ApiCoreTokensRotateCreateRequest struct {
|
||||
ctx context.Context
|
||||
ApiService *CoreAPIService
|
||||
identifier string
|
||||
}
|
||||
|
||||
func (r ApiCoreTokensRotateCreateRequest) Execute() (*TokenView, *http.Response, error) {
|
||||
return r.ApiService.CoreTokensRotateCreateExecute(r)
|
||||
}
|
||||
|
||||
/*
|
||||
CoreTokensRotateCreate Method for CoreTokensRotateCreate
|
||||
|
||||
Rotate the token key and reset the expiry to 24 hours. Only callable by the token
|
||||
owner, the owning agent's human owner, or a superuser.
|
||||
|
||||
@param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
|
||||
@param identifier
|
||||
@return ApiCoreTokensRotateCreateRequest
|
||||
*/
|
||||
func (a *CoreAPIService) CoreTokensRotateCreate(ctx context.Context, identifier string) ApiCoreTokensRotateCreateRequest {
|
||||
return ApiCoreTokensRotateCreateRequest{
|
||||
ApiService: a,
|
||||
ctx: ctx,
|
||||
identifier: identifier,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute executes the request
|
||||
//
|
||||
// @return TokenView
|
||||
func (a *CoreAPIService) CoreTokensRotateCreateExecute(r ApiCoreTokensRotateCreateRequest) (*TokenView, *http.Response, error) {
|
||||
var (
|
||||
localVarHTTPMethod = http.MethodPost
|
||||
localVarPostBody interface{}
|
||||
formFiles []formFile
|
||||
localVarReturnValue *TokenView
|
||||
)
|
||||
|
||||
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CoreAPIService.CoreTokensRotateCreate")
|
||||
if err != nil {
|
||||
return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()}
|
||||
}
|
||||
|
||||
localVarPath := localBasePath + "/core/tokens/{identifier}/rotate/"
|
||||
localVarPath = strings.Replace(localVarPath, "{"+"identifier"+"}", url.PathEscape(parameterValueToString(r.identifier, "identifier")), -1)
|
||||
|
||||
localVarHeaderParams := make(map[string]string)
|
||||
localVarQueryParams := url.Values{}
|
||||
localVarFormParams := url.Values{}
|
||||
|
||||
// to determine the Content-Type header
|
||||
localVarHTTPContentTypes := []string{}
|
||||
|
||||
// set Content-Type header
|
||||
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
|
||||
if localVarHTTPContentType != "" {
|
||||
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
localVarHTTPHeaderAccepts := []string{"application/json"}
|
||||
|
||||
// set Accept header
|
||||
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
|
||||
if localVarHTTPHeaderAccept != "" {
|
||||
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
|
||||
}
|
||||
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles)
|
||||
if err != nil {
|
||||
return localVarReturnValue, nil, err
|
||||
}
|
||||
|
||||
localVarHTTPResponse, err := a.client.callAPI(req)
|
||||
if err != nil || localVarHTTPResponse == nil {
|
||||
return localVarReturnValue, localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
localVarBody, err := io.ReadAll(localVarHTTPResponse.Body)
|
||||
localVarHTTPResponse.Body.Close()
|
||||
localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody))
|
||||
if err != nil {
|
||||
return localVarReturnValue, localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
if localVarHTTPResponse.StatusCode >= 300 {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: localVarHTTPResponse.Status,
|
||||
}
|
||||
if localVarHTTPResponse.StatusCode == 400 {
|
||||
var v ValidationError
|
||||
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr.error = err.Error()
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v)
|
||||
newErr.model = v
|
||||
}
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: err.Error(),
|
||||
}
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
return localVarReturnValue, localVarHTTPResponse, nil
|
||||
}
|
||||
|
||||
type ApiCoreTokensSetKeyCreateRequest struct {
|
||||
ctx context.Context
|
||||
ApiService *CoreAPIService
|
||||
@@ -7240,6 +7464,367 @@ func (a *CoreAPIService) CoreUserConsentUsedByListExecute(r ApiCoreUserConsentUs
|
||||
return localVarReturnValue, localVarHTTPResponse, nil
|
||||
}
|
||||
|
||||
type ApiCoreUsersAgentAllowedAppPartialUpdateRequest struct {
|
||||
ctx context.Context
|
||||
ApiService *CoreAPIService
|
||||
id int32
|
||||
patchedUserAgentAllowedAppRequest *PatchedUserAgentAllowedAppRequest
|
||||
}
|
||||
|
||||
func (r ApiCoreUsersAgentAllowedAppPartialUpdateRequest) PatchedUserAgentAllowedAppRequest(patchedUserAgentAllowedAppRequest PatchedUserAgentAllowedAppRequest) ApiCoreUsersAgentAllowedAppPartialUpdateRequest {
|
||||
r.patchedUserAgentAllowedAppRequest = &patchedUserAgentAllowedAppRequest
|
||||
return r
|
||||
}
|
||||
|
||||
func (r ApiCoreUsersAgentAllowedAppPartialUpdateRequest) Execute() (*UserAgentAllowedApps, *http.Response, error) {
|
||||
return r.ApiService.CoreUsersAgentAllowedAppPartialUpdateExecute(r)
|
||||
}
|
||||
|
||||
/*
|
||||
CoreUsersAgentAllowedAppPartialUpdate Method for CoreUsersAgentAllowedAppPartialUpdate
|
||||
|
||||
Add or remove a single application from an agent's allowed list.
|
||||
Caller must be the agent's owner or a superuser.
|
||||
|
||||
@param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
|
||||
@param id A unique integer value identifying this User.
|
||||
@return ApiCoreUsersAgentAllowedAppPartialUpdateRequest
|
||||
*/
|
||||
func (a *CoreAPIService) CoreUsersAgentAllowedAppPartialUpdate(ctx context.Context, id int32) ApiCoreUsersAgentAllowedAppPartialUpdateRequest {
|
||||
return ApiCoreUsersAgentAllowedAppPartialUpdateRequest{
|
||||
ApiService: a,
|
||||
ctx: ctx,
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute executes the request
|
||||
//
|
||||
// @return UserAgentAllowedApps
|
||||
func (a *CoreAPIService) CoreUsersAgentAllowedAppPartialUpdateExecute(r ApiCoreUsersAgentAllowedAppPartialUpdateRequest) (*UserAgentAllowedApps, *http.Response, error) {
|
||||
var (
|
||||
localVarHTTPMethod = http.MethodPatch
|
||||
localVarPostBody interface{}
|
||||
formFiles []formFile
|
||||
localVarReturnValue *UserAgentAllowedApps
|
||||
)
|
||||
|
||||
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CoreAPIService.CoreUsersAgentAllowedAppPartialUpdate")
|
||||
if err != nil {
|
||||
return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()}
|
||||
}
|
||||
|
||||
localVarPath := localBasePath + "/core/users/{id}/agent_allowed_app/"
|
||||
localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1)
|
||||
|
||||
localVarHeaderParams := make(map[string]string)
|
||||
localVarQueryParams := url.Values{}
|
||||
localVarFormParams := url.Values{}
|
||||
|
||||
// to determine the Content-Type header
|
||||
localVarHTTPContentTypes := []string{"application/json"}
|
||||
|
||||
// set Content-Type header
|
||||
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
|
||||
if localVarHTTPContentType != "" {
|
||||
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
localVarHTTPHeaderAccepts := []string{"application/json"}
|
||||
|
||||
// set Accept header
|
||||
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
|
||||
if localVarHTTPHeaderAccept != "" {
|
||||
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
|
||||
}
|
||||
// body params
|
||||
localVarPostBody = r.patchedUserAgentAllowedAppRequest
|
||||
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles)
|
||||
if err != nil {
|
||||
return localVarReturnValue, nil, err
|
||||
}
|
||||
|
||||
localVarHTTPResponse, err := a.client.callAPI(req)
|
||||
if err != nil || localVarHTTPResponse == nil {
|
||||
return localVarReturnValue, localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
localVarBody, err := io.ReadAll(localVarHTTPResponse.Body)
|
||||
localVarHTTPResponse.Body.Close()
|
||||
localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody))
|
||||
if err != nil {
|
||||
return localVarReturnValue, localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
if localVarHTTPResponse.StatusCode >= 300 {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: localVarHTTPResponse.Status,
|
||||
}
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: err.Error(),
|
||||
}
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
return localVarReturnValue, localVarHTTPResponse, nil
|
||||
}
|
||||
|
||||
type ApiCoreUsersAgentAllowedAppsUpdateRequest struct {
|
||||
ctx context.Context
|
||||
ApiService *CoreAPIService
|
||||
id int32
|
||||
userAgentAllowedAppsRequest *UserAgentAllowedAppsRequest
|
||||
}
|
||||
|
||||
func (r ApiCoreUsersAgentAllowedAppsUpdateRequest) UserAgentAllowedAppsRequest(userAgentAllowedAppsRequest UserAgentAllowedAppsRequest) ApiCoreUsersAgentAllowedAppsUpdateRequest {
|
||||
r.userAgentAllowedAppsRequest = &userAgentAllowedAppsRequest
|
||||
return r
|
||||
}
|
||||
|
||||
func (r ApiCoreUsersAgentAllowedAppsUpdateRequest) Execute() (*UserAgentAllowedApps, *http.Response, error) {
|
||||
return r.ApiService.CoreUsersAgentAllowedAppsUpdateExecute(r)
|
||||
}
|
||||
|
||||
/*
|
||||
CoreUsersAgentAllowedAppsUpdate Method for CoreUsersAgentAllowedAppsUpdate
|
||||
|
||||
Replace the allowed application list for an agent user.
|
||||
Caller must be the agent's owner or a superuser.
|
||||
|
||||
@param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
|
||||
@param id A unique integer value identifying this User.
|
||||
@return ApiCoreUsersAgentAllowedAppsUpdateRequest
|
||||
*/
|
||||
func (a *CoreAPIService) CoreUsersAgentAllowedAppsUpdate(ctx context.Context, id int32) ApiCoreUsersAgentAllowedAppsUpdateRequest {
|
||||
return ApiCoreUsersAgentAllowedAppsUpdateRequest{
|
||||
ApiService: a,
|
||||
ctx: ctx,
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute executes the request
|
||||
//
|
||||
// @return UserAgentAllowedApps
|
||||
func (a *CoreAPIService) CoreUsersAgentAllowedAppsUpdateExecute(r ApiCoreUsersAgentAllowedAppsUpdateRequest) (*UserAgentAllowedApps, *http.Response, error) {
|
||||
var (
|
||||
localVarHTTPMethod = http.MethodPut
|
||||
localVarPostBody interface{}
|
||||
formFiles []formFile
|
||||
localVarReturnValue *UserAgentAllowedApps
|
||||
)
|
||||
|
||||
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CoreAPIService.CoreUsersAgentAllowedAppsUpdate")
|
||||
if err != nil {
|
||||
return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()}
|
||||
}
|
||||
|
||||
localVarPath := localBasePath + "/core/users/{id}/agent_allowed_apps/"
|
||||
localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1)
|
||||
|
||||
localVarHeaderParams := make(map[string]string)
|
||||
localVarQueryParams := url.Values{}
|
||||
localVarFormParams := url.Values{}
|
||||
if r.userAgentAllowedAppsRequest == nil {
|
||||
return localVarReturnValue, nil, reportError("userAgentAllowedAppsRequest is required and must be specified")
|
||||
}
|
||||
|
||||
// to determine the Content-Type header
|
||||
localVarHTTPContentTypes := []string{"application/json"}
|
||||
|
||||
// set Content-Type header
|
||||
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
|
||||
if localVarHTTPContentType != "" {
|
||||
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
localVarHTTPHeaderAccepts := []string{"application/json"}
|
||||
|
||||
// set Accept header
|
||||
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
|
||||
if localVarHTTPHeaderAccept != "" {
|
||||
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
|
||||
}
|
||||
// body params
|
||||
localVarPostBody = r.userAgentAllowedAppsRequest
|
||||
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles)
|
||||
if err != nil {
|
||||
return localVarReturnValue, nil, err
|
||||
}
|
||||
|
||||
localVarHTTPResponse, err := a.client.callAPI(req)
|
||||
if err != nil || localVarHTTPResponse == nil {
|
||||
return localVarReturnValue, localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
localVarBody, err := io.ReadAll(localVarHTTPResponse.Body)
|
||||
localVarHTTPResponse.Body.Close()
|
||||
localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody))
|
||||
if err != nil {
|
||||
return localVarReturnValue, localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
if localVarHTTPResponse.StatusCode >= 300 {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: localVarHTTPResponse.Status,
|
||||
}
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: err.Error(),
|
||||
}
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
return localVarReturnValue, localVarHTTPResponse, nil
|
||||
}
|
||||
|
||||
type ApiCoreUsersAgentCreateRequest struct {
|
||||
ctx context.Context
|
||||
ApiService *CoreAPIService
|
||||
userAgentRequest *UserAgentRequest
|
||||
}
|
||||
|
||||
func (r ApiCoreUsersAgentCreateRequest) UserAgentRequest(userAgentRequest UserAgentRequest) ApiCoreUsersAgentCreateRequest {
|
||||
r.userAgentRequest = &userAgentRequest
|
||||
return r
|
||||
}
|
||||
|
||||
func (r ApiCoreUsersAgentCreateRequest) Execute() (*UserAgentResponse, *http.Response, error) {
|
||||
return r.ApiService.CoreUsersAgentCreateExecute(r)
|
||||
}
|
||||
|
||||
/*
|
||||
CoreUsersAgentCreate Method for CoreUsersAgentCreate
|
||||
|
||||
Create a new agent user. Enterprise only. Caller must be an internal user.
|
||||
|
||||
@param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
|
||||
@return ApiCoreUsersAgentCreateRequest
|
||||
*/
|
||||
func (a *CoreAPIService) CoreUsersAgentCreate(ctx context.Context) ApiCoreUsersAgentCreateRequest {
|
||||
return ApiCoreUsersAgentCreateRequest{
|
||||
ApiService: a,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute executes the request
|
||||
//
|
||||
// @return UserAgentResponse
|
||||
func (a *CoreAPIService) CoreUsersAgentCreateExecute(r ApiCoreUsersAgentCreateRequest) (*UserAgentResponse, *http.Response, error) {
|
||||
var (
|
||||
localVarHTTPMethod = http.MethodPost
|
||||
localVarPostBody interface{}
|
||||
formFiles []formFile
|
||||
localVarReturnValue *UserAgentResponse
|
||||
)
|
||||
|
||||
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "CoreAPIService.CoreUsersAgentCreate")
|
||||
if err != nil {
|
||||
return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()}
|
||||
}
|
||||
|
||||
localVarPath := localBasePath + "/core/users/agent/"
|
||||
|
||||
localVarHeaderParams := make(map[string]string)
|
||||
localVarQueryParams := url.Values{}
|
||||
localVarFormParams := url.Values{}
|
||||
if r.userAgentRequest == nil {
|
||||
return localVarReturnValue, nil, reportError("userAgentRequest is required and must be specified")
|
||||
}
|
||||
|
||||
// to determine the Content-Type header
|
||||
localVarHTTPContentTypes := []string{"application/json"}
|
||||
|
||||
// set Content-Type header
|
||||
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
|
||||
if localVarHTTPContentType != "" {
|
||||
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
localVarHTTPHeaderAccepts := []string{"application/json"}
|
||||
|
||||
// set Accept header
|
||||
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
|
||||
if localVarHTTPHeaderAccept != "" {
|
||||
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
|
||||
}
|
||||
// body params
|
||||
localVarPostBody = r.userAgentRequest
|
||||
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles)
|
||||
if err != nil {
|
||||
return localVarReturnValue, nil, err
|
||||
}
|
||||
|
||||
localVarHTTPResponse, err := a.client.callAPI(req)
|
||||
if err != nil || localVarHTTPResponse == nil {
|
||||
return localVarReturnValue, localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
localVarBody, err := io.ReadAll(localVarHTTPResponse.Body)
|
||||
localVarHTTPResponse.Body.Close()
|
||||
localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody))
|
||||
if err != nil {
|
||||
return localVarReturnValue, localVarHTTPResponse, err
|
||||
}
|
||||
|
||||
if localVarHTTPResponse.StatusCode >= 300 {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: localVarHTTPResponse.Status,
|
||||
}
|
||||
if localVarHTTPResponse.StatusCode == 400 {
|
||||
var v ValidationError
|
||||
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr.error = err.Error()
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v)
|
||||
newErr.model = v
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
if localVarHTTPResponse.StatusCode == 403 {
|
||||
var v GenericError
|
||||
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr.error = err.Error()
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v)
|
||||
newErr.model = v
|
||||
}
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr := &GenericOpenAPIError{
|
||||
body: localVarBody,
|
||||
error: err.Error(),
|
||||
}
|
||||
return localVarReturnValue, localVarHTTPResponse, newErr
|
||||
}
|
||||
|
||||
return localVarReturnValue, localVarHTTPResponse, nil
|
||||
}
|
||||
|
||||
type ApiCoreUsersCreateRequest struct {
|
||||
ctx context.Context
|
||||
ApiService *CoreAPIService
|
||||
|
||||
191
packages/client-go/model_patched_user_agent_allowed_app_request.go
generated
Normal file
191
packages/client-go/model_patched_user_agent_allowed_app_request.go
generated
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// checks if the PatchedUserAgentAllowedAppRequest type satisfies the MappedNullable interface at compile time
|
||||
var _ MappedNullable = &PatchedUserAgentAllowedAppRequest{}
|
||||
|
||||
// PatchedUserAgentAllowedAppRequest Payload to add or remove a single allowed application
|
||||
type PatchedUserAgentAllowedAppRequest struct {
|
||||
App *string `json:"app,omitempty"`
|
||||
Action *UserAgentAllowedAppActionEnum `json:"action,omitempty"`
|
||||
AdditionalProperties map[string]interface{}
|
||||
}
|
||||
|
||||
type _PatchedUserAgentAllowedAppRequest PatchedUserAgentAllowedAppRequest
|
||||
|
||||
// NewPatchedUserAgentAllowedAppRequest instantiates a new PatchedUserAgentAllowedAppRequest object
|
||||
// This constructor will assign default values to properties that have it defined,
|
||||
// and makes sure properties required by API are set, but the set of arguments
|
||||
// will change when the set of required properties is changed
|
||||
func NewPatchedUserAgentAllowedAppRequest() *PatchedUserAgentAllowedAppRequest {
|
||||
this := PatchedUserAgentAllowedAppRequest{}
|
||||
return &this
|
||||
}
|
||||
|
||||
// NewPatchedUserAgentAllowedAppRequestWithDefaults instantiates a new PatchedUserAgentAllowedAppRequest object
|
||||
// This constructor will only assign default values to properties that have it defined,
|
||||
// but it doesn't guarantee that properties required by API are set
|
||||
func NewPatchedUserAgentAllowedAppRequestWithDefaults() *PatchedUserAgentAllowedAppRequest {
|
||||
this := PatchedUserAgentAllowedAppRequest{}
|
||||
return &this
|
||||
}
|
||||
|
||||
// GetApp returns the App field value if set, zero value otherwise.
|
||||
func (o *PatchedUserAgentAllowedAppRequest) GetApp() string {
|
||||
if o == nil || IsNil(o.App) {
|
||||
var ret string
|
||||
return ret
|
||||
}
|
||||
return *o.App
|
||||
}
|
||||
|
||||
// GetAppOk returns a tuple with the App field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *PatchedUserAgentAllowedAppRequest) GetAppOk() (*string, bool) {
|
||||
if o == nil || IsNil(o.App) {
|
||||
return nil, false
|
||||
}
|
||||
return o.App, true
|
||||
}
|
||||
|
||||
// HasApp returns a boolean if a field has been set.
|
||||
func (o *PatchedUserAgentAllowedAppRequest) HasApp() bool {
|
||||
if o != nil && !IsNil(o.App) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetApp gets a reference to the given string and assigns it to the App field.
|
||||
func (o *PatchedUserAgentAllowedAppRequest) SetApp(v string) {
|
||||
o.App = &v
|
||||
}
|
||||
|
||||
// GetAction returns the Action field value if set, zero value otherwise.
|
||||
func (o *PatchedUserAgentAllowedAppRequest) GetAction() UserAgentAllowedAppActionEnum {
|
||||
if o == nil || IsNil(o.Action) {
|
||||
var ret UserAgentAllowedAppActionEnum
|
||||
return ret
|
||||
}
|
||||
return *o.Action
|
||||
}
|
||||
|
||||
// GetActionOk returns a tuple with the Action field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *PatchedUserAgentAllowedAppRequest) GetActionOk() (*UserAgentAllowedAppActionEnum, bool) {
|
||||
if o == nil || IsNil(o.Action) {
|
||||
return nil, false
|
||||
}
|
||||
return o.Action, true
|
||||
}
|
||||
|
||||
// HasAction returns a boolean if a field has been set.
|
||||
func (o *PatchedUserAgentAllowedAppRequest) HasAction() bool {
|
||||
if o != nil && !IsNil(o.Action) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetAction gets a reference to the given UserAgentAllowedAppActionEnum and assigns it to the Action field.
|
||||
func (o *PatchedUserAgentAllowedAppRequest) SetAction(v UserAgentAllowedAppActionEnum) {
|
||||
o.Action = &v
|
||||
}
|
||||
|
||||
func (o PatchedUserAgentAllowedAppRequest) MarshalJSON() ([]byte, error) {
|
||||
toSerialize, err := o.ToMap()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return json.Marshal(toSerialize)
|
||||
}
|
||||
|
||||
func (o PatchedUserAgentAllowedAppRequest) ToMap() (map[string]interface{}, error) {
|
||||
toSerialize := map[string]interface{}{}
|
||||
if !IsNil(o.App) {
|
||||
toSerialize["app"] = o.App
|
||||
}
|
||||
if !IsNil(o.Action) {
|
||||
toSerialize["action"] = o.Action
|
||||
}
|
||||
|
||||
for key, value := range o.AdditionalProperties {
|
||||
toSerialize[key] = value
|
||||
}
|
||||
|
||||
return toSerialize, nil
|
||||
}
|
||||
|
||||
func (o *PatchedUserAgentAllowedAppRequest) UnmarshalJSON(data []byte) (err error) {
|
||||
varPatchedUserAgentAllowedAppRequest := _PatchedUserAgentAllowedAppRequest{}
|
||||
|
||||
err = json.Unmarshal(data, &varPatchedUserAgentAllowedAppRequest)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*o = PatchedUserAgentAllowedAppRequest(varPatchedUserAgentAllowedAppRequest)
|
||||
|
||||
additionalProperties := make(map[string]interface{})
|
||||
|
||||
if err = json.Unmarshal(data, &additionalProperties); err == nil {
|
||||
delete(additionalProperties, "app")
|
||||
delete(additionalProperties, "action")
|
||||
o.AdditionalProperties = additionalProperties
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type NullablePatchedUserAgentAllowedAppRequest struct {
|
||||
value *PatchedUserAgentAllowedAppRequest
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullablePatchedUserAgentAllowedAppRequest) Get() *PatchedUserAgentAllowedAppRequest {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullablePatchedUserAgentAllowedAppRequest) Set(val *PatchedUserAgentAllowedAppRequest) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullablePatchedUserAgentAllowedAppRequest) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullablePatchedUserAgentAllowedAppRequest) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullablePatchedUserAgentAllowedAppRequest(val *PatchedUserAgentAllowedAppRequest) *NullablePatchedUserAgentAllowedAppRequest {
|
||||
return &NullablePatchedUserAgentAllowedAppRequest{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullablePatchedUserAgentAllowedAppRequest) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullablePatchedUserAgentAllowedAppRequest) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
111
packages/client-go/model_user_agent_allowed_app_action_enum.go
generated
Normal file
111
packages/client-go/model_user_agent_allowed_app_action_enum.go
generated
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// UserAgentAllowedAppActionEnum the model 'UserAgentAllowedAppActionEnum'
|
||||
type UserAgentAllowedAppActionEnum string
|
||||
|
||||
// List of UserAgentAllowedAppActionEnum
|
||||
const (
|
||||
USERAGENTALLOWEDAPPACTIONENUM_ADD UserAgentAllowedAppActionEnum = "add"
|
||||
USERAGENTALLOWEDAPPACTIONENUM_REMOVE UserAgentAllowedAppActionEnum = "remove"
|
||||
)
|
||||
|
||||
// All allowed values of UserAgentAllowedAppActionEnum enum
|
||||
var AllowedUserAgentAllowedAppActionEnumEnumValues = []UserAgentAllowedAppActionEnum{
|
||||
"add",
|
||||
"remove",
|
||||
}
|
||||
|
||||
func (v *UserAgentAllowedAppActionEnum) UnmarshalJSON(src []byte) error {
|
||||
var value string
|
||||
err := json.Unmarshal(src, &value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
enumTypeValue := UserAgentAllowedAppActionEnum(value)
|
||||
for _, existing := range AllowedUserAgentAllowedAppActionEnumEnumValues {
|
||||
if existing == enumTypeValue {
|
||||
*v = enumTypeValue
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("%+v is not a valid UserAgentAllowedAppActionEnum", value)
|
||||
}
|
||||
|
||||
// NewUserAgentAllowedAppActionEnumFromValue returns a pointer to a valid UserAgentAllowedAppActionEnum
|
||||
// for the value passed as argument, or an error if the value passed is not allowed by the enum
|
||||
func NewUserAgentAllowedAppActionEnumFromValue(v string) (*UserAgentAllowedAppActionEnum, error) {
|
||||
ev := UserAgentAllowedAppActionEnum(v)
|
||||
if ev.IsValid() {
|
||||
return &ev, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid value '%v' for UserAgentAllowedAppActionEnum: valid values are %v", v, AllowedUserAgentAllowedAppActionEnumEnumValues)
|
||||
}
|
||||
}
|
||||
|
||||
// IsValid return true if the value is valid for the enum, false otherwise
|
||||
func (v UserAgentAllowedAppActionEnum) IsValid() bool {
|
||||
for _, existing := range AllowedUserAgentAllowedAppActionEnumEnumValues {
|
||||
if existing == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Ptr returns reference to UserAgentAllowedAppActionEnum value
|
||||
func (v UserAgentAllowedAppActionEnum) Ptr() *UserAgentAllowedAppActionEnum {
|
||||
return &v
|
||||
}
|
||||
|
||||
type NullableUserAgentAllowedAppActionEnum struct {
|
||||
value *UserAgentAllowedAppActionEnum
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableUserAgentAllowedAppActionEnum) Get() *UserAgentAllowedAppActionEnum {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentAllowedAppActionEnum) Set(val *UserAgentAllowedAppActionEnum) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableUserAgentAllowedAppActionEnum) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentAllowedAppActionEnum) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableUserAgentAllowedAppActionEnum(val *UserAgentAllowedAppActionEnum) *NullableUserAgentAllowedAppActionEnum {
|
||||
return &NullableUserAgentAllowedAppActionEnum{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableUserAgentAllowedAppActionEnum) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentAllowedAppActionEnum) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
167
packages/client-go/model_user_agent_allowed_apps.go
generated
Normal file
167
packages/client-go/model_user_agent_allowed_apps.go
generated
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// checks if the UserAgentAllowedApps type satisfies the MappedNullable interface at compile time
|
||||
var _ MappedNullable = &UserAgentAllowedApps{}
|
||||
|
||||
// UserAgentAllowedApps Payload to replace an agent's allowed applications
|
||||
type UserAgentAllowedApps struct {
|
||||
AllowedApps []string `json:"allowed_apps"`
|
||||
AdditionalProperties map[string]interface{}
|
||||
}
|
||||
|
||||
type _UserAgentAllowedApps UserAgentAllowedApps
|
||||
|
||||
// NewUserAgentAllowedApps instantiates a new UserAgentAllowedApps object
|
||||
// This constructor will assign default values to properties that have it defined,
|
||||
// and makes sure properties required by API are set, but the set of arguments
|
||||
// will change when the set of required properties is changed
|
||||
func NewUserAgentAllowedApps(allowedApps []string) *UserAgentAllowedApps {
|
||||
this := UserAgentAllowedApps{}
|
||||
this.AllowedApps = allowedApps
|
||||
return &this
|
||||
}
|
||||
|
||||
// NewUserAgentAllowedAppsWithDefaults instantiates a new UserAgentAllowedApps object
|
||||
// This constructor will only assign default values to properties that have it defined,
|
||||
// but it doesn't guarantee that properties required by API are set
|
||||
func NewUserAgentAllowedAppsWithDefaults() *UserAgentAllowedApps {
|
||||
this := UserAgentAllowedApps{}
|
||||
return &this
|
||||
}
|
||||
|
||||
// GetAllowedApps returns the AllowedApps field value
|
||||
func (o *UserAgentAllowedApps) GetAllowedApps() []string {
|
||||
if o == nil {
|
||||
var ret []string
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.AllowedApps
|
||||
}
|
||||
|
||||
// GetAllowedAppsOk returns a tuple with the AllowedApps field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *UserAgentAllowedApps) GetAllowedAppsOk() ([]string, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.AllowedApps, true
|
||||
}
|
||||
|
||||
// SetAllowedApps sets field value
|
||||
func (o *UserAgentAllowedApps) SetAllowedApps(v []string) {
|
||||
o.AllowedApps = v
|
||||
}
|
||||
|
||||
func (o UserAgentAllowedApps) MarshalJSON() ([]byte, error) {
|
||||
toSerialize, err := o.ToMap()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return json.Marshal(toSerialize)
|
||||
}
|
||||
|
||||
func (o UserAgentAllowedApps) ToMap() (map[string]interface{}, error) {
|
||||
toSerialize := map[string]interface{}{}
|
||||
toSerialize["allowed_apps"] = o.AllowedApps
|
||||
|
||||
for key, value := range o.AdditionalProperties {
|
||||
toSerialize[key] = value
|
||||
}
|
||||
|
||||
return toSerialize, nil
|
||||
}
|
||||
|
||||
func (o *UserAgentAllowedApps) UnmarshalJSON(data []byte) (err error) {
|
||||
// This validates that all required properties are included in the JSON object
|
||||
// by unmarshalling the object into a generic map with string keys and checking
|
||||
// that every required field exists as a key in the generic map.
|
||||
requiredProperties := []string{
|
||||
"allowed_apps",
|
||||
}
|
||||
|
||||
allProperties := make(map[string]interface{})
|
||||
|
||||
err = json.Unmarshal(data, &allProperties)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, requiredProperty := range requiredProperties {
|
||||
if _, exists := allProperties[requiredProperty]; !exists {
|
||||
return fmt.Errorf("no value given for required property %v", requiredProperty)
|
||||
}
|
||||
}
|
||||
|
||||
varUserAgentAllowedApps := _UserAgentAllowedApps{}
|
||||
|
||||
err = json.Unmarshal(data, &varUserAgentAllowedApps)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*o = UserAgentAllowedApps(varUserAgentAllowedApps)
|
||||
|
||||
additionalProperties := make(map[string]interface{})
|
||||
|
||||
if err = json.Unmarshal(data, &additionalProperties); err == nil {
|
||||
delete(additionalProperties, "allowed_apps")
|
||||
o.AdditionalProperties = additionalProperties
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type NullableUserAgentAllowedApps struct {
|
||||
value *UserAgentAllowedApps
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableUserAgentAllowedApps) Get() *UserAgentAllowedApps {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentAllowedApps) Set(val *UserAgentAllowedApps) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableUserAgentAllowedApps) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentAllowedApps) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableUserAgentAllowedApps(val *UserAgentAllowedApps) *NullableUserAgentAllowedApps {
|
||||
return &NullableUserAgentAllowedApps{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableUserAgentAllowedApps) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentAllowedApps) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
167
packages/client-go/model_user_agent_allowed_apps_request.go
generated
Normal file
167
packages/client-go/model_user_agent_allowed_apps_request.go
generated
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// checks if the UserAgentAllowedAppsRequest type satisfies the MappedNullable interface at compile time
|
||||
var _ MappedNullable = &UserAgentAllowedAppsRequest{}
|
||||
|
||||
// UserAgentAllowedAppsRequest Payload to replace an agent's allowed applications
|
||||
type UserAgentAllowedAppsRequest struct {
|
||||
AllowedApps []string `json:"allowed_apps"`
|
||||
AdditionalProperties map[string]interface{}
|
||||
}
|
||||
|
||||
type _UserAgentAllowedAppsRequest UserAgentAllowedAppsRequest
|
||||
|
||||
// NewUserAgentAllowedAppsRequest instantiates a new UserAgentAllowedAppsRequest object
|
||||
// This constructor will assign default values to properties that have it defined,
|
||||
// and makes sure properties required by API are set, but the set of arguments
|
||||
// will change when the set of required properties is changed
|
||||
func NewUserAgentAllowedAppsRequest(allowedApps []string) *UserAgentAllowedAppsRequest {
|
||||
this := UserAgentAllowedAppsRequest{}
|
||||
this.AllowedApps = allowedApps
|
||||
return &this
|
||||
}
|
||||
|
||||
// NewUserAgentAllowedAppsRequestWithDefaults instantiates a new UserAgentAllowedAppsRequest object
|
||||
// This constructor will only assign default values to properties that have it defined,
|
||||
// but it doesn't guarantee that properties required by API are set
|
||||
func NewUserAgentAllowedAppsRequestWithDefaults() *UserAgentAllowedAppsRequest {
|
||||
this := UserAgentAllowedAppsRequest{}
|
||||
return &this
|
||||
}
|
||||
|
||||
// GetAllowedApps returns the AllowedApps field value
|
||||
func (o *UserAgentAllowedAppsRequest) GetAllowedApps() []string {
|
||||
if o == nil {
|
||||
var ret []string
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.AllowedApps
|
||||
}
|
||||
|
||||
// GetAllowedAppsOk returns a tuple with the AllowedApps field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *UserAgentAllowedAppsRequest) GetAllowedAppsOk() ([]string, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.AllowedApps, true
|
||||
}
|
||||
|
||||
// SetAllowedApps sets field value
|
||||
func (o *UserAgentAllowedAppsRequest) SetAllowedApps(v []string) {
|
||||
o.AllowedApps = v
|
||||
}
|
||||
|
||||
func (o UserAgentAllowedAppsRequest) MarshalJSON() ([]byte, error) {
|
||||
toSerialize, err := o.ToMap()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return json.Marshal(toSerialize)
|
||||
}
|
||||
|
||||
func (o UserAgentAllowedAppsRequest) ToMap() (map[string]interface{}, error) {
|
||||
toSerialize := map[string]interface{}{}
|
||||
toSerialize["allowed_apps"] = o.AllowedApps
|
||||
|
||||
for key, value := range o.AdditionalProperties {
|
||||
toSerialize[key] = value
|
||||
}
|
||||
|
||||
return toSerialize, nil
|
||||
}
|
||||
|
||||
func (o *UserAgentAllowedAppsRequest) UnmarshalJSON(data []byte) (err error) {
|
||||
// This validates that all required properties are included in the JSON object
|
||||
// by unmarshalling the object into a generic map with string keys and checking
|
||||
// that every required field exists as a key in the generic map.
|
||||
requiredProperties := []string{
|
||||
"allowed_apps",
|
||||
}
|
||||
|
||||
allProperties := make(map[string]interface{})
|
||||
|
||||
err = json.Unmarshal(data, &allProperties)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, requiredProperty := range requiredProperties {
|
||||
if _, exists := allProperties[requiredProperty]; !exists {
|
||||
return fmt.Errorf("no value given for required property %v", requiredProperty)
|
||||
}
|
||||
}
|
||||
|
||||
varUserAgentAllowedAppsRequest := _UserAgentAllowedAppsRequest{}
|
||||
|
||||
err = json.Unmarshal(data, &varUserAgentAllowedAppsRequest)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*o = UserAgentAllowedAppsRequest(varUserAgentAllowedAppsRequest)
|
||||
|
||||
additionalProperties := make(map[string]interface{})
|
||||
|
||||
if err = json.Unmarshal(data, &additionalProperties); err == nil {
|
||||
delete(additionalProperties, "allowed_apps")
|
||||
o.AdditionalProperties = additionalProperties
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type NullableUserAgentAllowedAppsRequest struct {
|
||||
value *UserAgentAllowedAppsRequest
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableUserAgentAllowedAppsRequest) Get() *UserAgentAllowedAppsRequest {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentAllowedAppsRequest) Set(val *UserAgentAllowedAppsRequest) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableUserAgentAllowedAppsRequest) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentAllowedAppsRequest) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableUserAgentAllowedAppsRequest(val *UserAgentAllowedAppsRequest) *NullableUserAgentAllowedAppsRequest {
|
||||
return &NullableUserAgentAllowedAppsRequest{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableUserAgentAllowedAppsRequest) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentAllowedAppsRequest) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
204
packages/client-go/model_user_agent_request.go
generated
Normal file
204
packages/client-go/model_user_agent_request.go
generated
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// checks if the UserAgentRequest type satisfies the MappedNullable interface at compile time
|
||||
var _ MappedNullable = &UserAgentRequest{}
|
||||
|
||||
// UserAgentRequest Payload to create an agent user
|
||||
type UserAgentRequest struct {
|
||||
Name string `json:"name"`
|
||||
Owner *int32 `json:"owner,omitempty"`
|
||||
AdditionalProperties map[string]interface{}
|
||||
}
|
||||
|
||||
type _UserAgentRequest UserAgentRequest
|
||||
|
||||
// NewUserAgentRequest instantiates a new UserAgentRequest object
|
||||
// This constructor will assign default values to properties that have it defined,
|
||||
// and makes sure properties required by API are set, but the set of arguments
|
||||
// will change when the set of required properties is changed
|
||||
func NewUserAgentRequest(name string) *UserAgentRequest {
|
||||
this := UserAgentRequest{}
|
||||
this.Name = name
|
||||
return &this
|
||||
}
|
||||
|
||||
// NewUserAgentRequestWithDefaults instantiates a new UserAgentRequest object
|
||||
// This constructor will only assign default values to properties that have it defined,
|
||||
// but it doesn't guarantee that properties required by API are set
|
||||
func NewUserAgentRequestWithDefaults() *UserAgentRequest {
|
||||
this := UserAgentRequest{}
|
||||
return &this
|
||||
}
|
||||
|
||||
// GetName returns the Name field value
|
||||
func (o *UserAgentRequest) GetName() string {
|
||||
if o == nil {
|
||||
var ret string
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.Name
|
||||
}
|
||||
|
||||
// GetNameOk returns a tuple with the Name field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *UserAgentRequest) GetNameOk() (*string, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Name, true
|
||||
}
|
||||
|
||||
// SetName sets field value
|
||||
func (o *UserAgentRequest) SetName(v string) {
|
||||
o.Name = v
|
||||
}
|
||||
|
||||
// GetOwner returns the Owner field value if set, zero value otherwise.
|
||||
func (o *UserAgentRequest) GetOwner() int32 {
|
||||
if o == nil || IsNil(o.Owner) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.Owner
|
||||
}
|
||||
|
||||
// GetOwnerOk returns a tuple with the Owner field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *UserAgentRequest) GetOwnerOk() (*int32, bool) {
|
||||
if o == nil || IsNil(o.Owner) {
|
||||
return nil, false
|
||||
}
|
||||
return o.Owner, true
|
||||
}
|
||||
|
||||
// HasOwner returns a boolean if a field has been set.
|
||||
func (o *UserAgentRequest) HasOwner() bool {
|
||||
if o != nil && !IsNil(o.Owner) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetOwner gets a reference to the given int32 and assigns it to the Owner field.
|
||||
func (o *UserAgentRequest) SetOwner(v int32) {
|
||||
o.Owner = &v
|
||||
}
|
||||
|
||||
func (o UserAgentRequest) MarshalJSON() ([]byte, error) {
|
||||
toSerialize, err := o.ToMap()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return json.Marshal(toSerialize)
|
||||
}
|
||||
|
||||
func (o UserAgentRequest) ToMap() (map[string]interface{}, error) {
|
||||
toSerialize := map[string]interface{}{}
|
||||
toSerialize["name"] = o.Name
|
||||
if !IsNil(o.Owner) {
|
||||
toSerialize["owner"] = o.Owner
|
||||
}
|
||||
|
||||
for key, value := range o.AdditionalProperties {
|
||||
toSerialize[key] = value
|
||||
}
|
||||
|
||||
return toSerialize, nil
|
||||
}
|
||||
|
||||
func (o *UserAgentRequest) UnmarshalJSON(data []byte) (err error) {
|
||||
// This validates that all required properties are included in the JSON object
|
||||
// by unmarshalling the object into a generic map with string keys and checking
|
||||
// that every required field exists as a key in the generic map.
|
||||
requiredProperties := []string{
|
||||
"name",
|
||||
}
|
||||
|
||||
allProperties := make(map[string]interface{})
|
||||
|
||||
err = json.Unmarshal(data, &allProperties)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, requiredProperty := range requiredProperties {
|
||||
if _, exists := allProperties[requiredProperty]; !exists {
|
||||
return fmt.Errorf("no value given for required property %v", requiredProperty)
|
||||
}
|
||||
}
|
||||
|
||||
varUserAgentRequest := _UserAgentRequest{}
|
||||
|
||||
err = json.Unmarshal(data, &varUserAgentRequest)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*o = UserAgentRequest(varUserAgentRequest)
|
||||
|
||||
additionalProperties := make(map[string]interface{})
|
||||
|
||||
if err = json.Unmarshal(data, &additionalProperties); err == nil {
|
||||
delete(additionalProperties, "name")
|
||||
delete(additionalProperties, "owner")
|
||||
o.AdditionalProperties = additionalProperties
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type NullableUserAgentRequest struct {
|
||||
value *UserAgentRequest
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableUserAgentRequest) Get() *UserAgentRequest {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentRequest) Set(val *UserAgentRequest) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableUserAgentRequest) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentRequest) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableUserAgentRequest(val *UserAgentRequest) *NullableUserAgentRequest {
|
||||
return &NullableUserAgentRequest{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableUserAgentRequest) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentRequest) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
254
packages/client-go/model_user_agent_response.go
generated
Normal file
254
packages/client-go/model_user_agent_response.go
generated
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// checks if the UserAgentResponse type satisfies the MappedNullable interface at compile time
|
||||
var _ MappedNullable = &UserAgentResponse{}
|
||||
|
||||
// UserAgentResponse struct for UserAgentResponse
|
||||
type UserAgentResponse struct {
|
||||
Username string `json:"username"`
|
||||
Token string `json:"token"`
|
||||
UserUid string `json:"user_uid"`
|
||||
UserPk int32 `json:"user_pk"`
|
||||
AdditionalProperties map[string]interface{}
|
||||
}
|
||||
|
||||
type _UserAgentResponse UserAgentResponse
|
||||
|
||||
// NewUserAgentResponse instantiates a new UserAgentResponse object
|
||||
// This constructor will assign default values to properties that have it defined,
|
||||
// and makes sure properties required by API are set, but the set of arguments
|
||||
// will change when the set of required properties is changed
|
||||
func NewUserAgentResponse(username string, token string, userUid string, userPk int32) *UserAgentResponse {
|
||||
this := UserAgentResponse{}
|
||||
this.Username = username
|
||||
this.Token = token
|
||||
this.UserUid = userUid
|
||||
this.UserPk = userPk
|
||||
return &this
|
||||
}
|
||||
|
||||
// NewUserAgentResponseWithDefaults instantiates a new UserAgentResponse object
|
||||
// This constructor will only assign default values to properties that have it defined,
|
||||
// but it doesn't guarantee that properties required by API are set
|
||||
func NewUserAgentResponseWithDefaults() *UserAgentResponse {
|
||||
this := UserAgentResponse{}
|
||||
return &this
|
||||
}
|
||||
|
||||
// GetUsername returns the Username field value
|
||||
func (o *UserAgentResponse) GetUsername() string {
|
||||
if o == nil {
|
||||
var ret string
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.Username
|
||||
}
|
||||
|
||||
// GetUsernameOk returns a tuple with the Username field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *UserAgentResponse) GetUsernameOk() (*string, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Username, true
|
||||
}
|
||||
|
||||
// SetUsername sets field value
|
||||
func (o *UserAgentResponse) SetUsername(v string) {
|
||||
o.Username = v
|
||||
}
|
||||
|
||||
// GetToken returns the Token field value
|
||||
func (o *UserAgentResponse) GetToken() string {
|
||||
if o == nil {
|
||||
var ret string
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.Token
|
||||
}
|
||||
|
||||
// GetTokenOk returns a tuple with the Token field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *UserAgentResponse) GetTokenOk() (*string, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Token, true
|
||||
}
|
||||
|
||||
// SetToken sets field value
|
||||
func (o *UserAgentResponse) SetToken(v string) {
|
||||
o.Token = v
|
||||
}
|
||||
|
||||
// GetUserUid returns the UserUid field value
|
||||
func (o *UserAgentResponse) GetUserUid() string {
|
||||
if o == nil {
|
||||
var ret string
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.UserUid
|
||||
}
|
||||
|
||||
// GetUserUidOk returns a tuple with the UserUid field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *UserAgentResponse) GetUserUidOk() (*string, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.UserUid, true
|
||||
}
|
||||
|
||||
// SetUserUid sets field value
|
||||
func (o *UserAgentResponse) SetUserUid(v string) {
|
||||
o.UserUid = v
|
||||
}
|
||||
|
||||
// GetUserPk returns the UserPk field value
|
||||
func (o *UserAgentResponse) GetUserPk() int32 {
|
||||
if o == nil {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.UserPk
|
||||
}
|
||||
|
||||
// GetUserPkOk returns a tuple with the UserPk field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *UserAgentResponse) GetUserPkOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.UserPk, true
|
||||
}
|
||||
|
||||
// SetUserPk sets field value
|
||||
func (o *UserAgentResponse) SetUserPk(v int32) {
|
||||
o.UserPk = v
|
||||
}
|
||||
|
||||
func (o UserAgentResponse) MarshalJSON() ([]byte, error) {
|
||||
toSerialize, err := o.ToMap()
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return json.Marshal(toSerialize)
|
||||
}
|
||||
|
||||
func (o UserAgentResponse) ToMap() (map[string]interface{}, error) {
|
||||
toSerialize := map[string]interface{}{}
|
||||
toSerialize["username"] = o.Username
|
||||
toSerialize["token"] = o.Token
|
||||
toSerialize["user_uid"] = o.UserUid
|
||||
toSerialize["user_pk"] = o.UserPk
|
||||
|
||||
for key, value := range o.AdditionalProperties {
|
||||
toSerialize[key] = value
|
||||
}
|
||||
|
||||
return toSerialize, nil
|
||||
}
|
||||
|
||||
func (o *UserAgentResponse) UnmarshalJSON(data []byte) (err error) {
|
||||
// This validates that all required properties are included in the JSON object
|
||||
// by unmarshalling the object into a generic map with string keys and checking
|
||||
// that every required field exists as a key in the generic map.
|
||||
requiredProperties := []string{
|
||||
"username",
|
||||
"token",
|
||||
"user_uid",
|
||||
"user_pk",
|
||||
}
|
||||
|
||||
allProperties := make(map[string]interface{})
|
||||
|
||||
err = json.Unmarshal(data, &allProperties)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, requiredProperty := range requiredProperties {
|
||||
if _, exists := allProperties[requiredProperty]; !exists {
|
||||
return fmt.Errorf("no value given for required property %v", requiredProperty)
|
||||
}
|
||||
}
|
||||
|
||||
varUserAgentResponse := _UserAgentResponse{}
|
||||
|
||||
err = json.Unmarshal(data, &varUserAgentResponse)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*o = UserAgentResponse(varUserAgentResponse)
|
||||
|
||||
additionalProperties := make(map[string]interface{})
|
||||
|
||||
if err = json.Unmarshal(data, &additionalProperties); err == nil {
|
||||
delete(additionalProperties, "username")
|
||||
delete(additionalProperties, "token")
|
||||
delete(additionalProperties, "user_uid")
|
||||
delete(additionalProperties, "user_pk")
|
||||
o.AdditionalProperties = additionalProperties
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type NullableUserAgentResponse struct {
|
||||
value *UserAgentResponse
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableUserAgentResponse) Get() *UserAgentResponse {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentResponse) Set(val *UserAgentResponse) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableUserAgentResponse) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentResponse) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableUserAgentResponse(val *UserAgentResponse) *NullableUserAgentResponse {
|
||||
return &NullableUserAgentResponse{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableUserAgentResponse) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableUserAgentResponse) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
2
packages/client-go/model_user_type_enum.go
generated
2
packages/client-go/model_user_type_enum.go
generated
@@ -25,6 +25,7 @@ const (
|
||||
USERTYPEENUM_EXTERNAL UserTypeEnum = "external"
|
||||
USERTYPEENUM_SERVICE_ACCOUNT UserTypeEnum = "service_account"
|
||||
USERTYPEENUM_INTERNAL_SERVICE_ACCOUNT UserTypeEnum = "internal_service_account"
|
||||
USERTYPEENUM_AGENT UserTypeEnum = "agent"
|
||||
)
|
||||
|
||||
// All allowed values of UserTypeEnum enum
|
||||
@@ -33,6 +34,7 @@ var AllowedUserTypeEnumEnumValues = []UserTypeEnum{
|
||||
"external",
|
||||
"service_account",
|
||||
"internal_service_account",
|
||||
"agent",
|
||||
}
|
||||
|
||||
func (v *UserTypeEnum) UnmarshalJSON(src []byte) error {
|
||||
|
||||
334
packages/client-rust/src/apis/core_api.rs
generated
334
packages/client-rust/src/apis/core_api.rs
generated
@@ -12,6 +12,15 @@ use serde::{Deserialize, Serialize, de::Error as _};
|
||||
use super::{ContentType, Error, configuration};
|
||||
use crate::{apis::ResponseContent, models};
|
||||
|
||||
/// struct for typed errors of method [`core_agent_session_create`]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CoreAgentSessionCreateError {
|
||||
Status400(models::ValidationError),
|
||||
Status403(models::GenericError),
|
||||
UnknownValue(serde_json::Value),
|
||||
}
|
||||
|
||||
/// struct for typed errors of method [`core_application_entitlements_create`]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
@@ -392,6 +401,15 @@ pub enum CoreTokensRetrieveError {
|
||||
UnknownValue(serde_json::Value),
|
||||
}
|
||||
|
||||
/// struct for typed errors of method [`core_tokens_rotate_create`]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CoreTokensRotateCreateError {
|
||||
Status403(),
|
||||
Status400(models::ValidationError),
|
||||
UnknownValue(serde_json::Value),
|
||||
}
|
||||
|
||||
/// struct for typed errors of method [`core_tokens_set_key_create`]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
@@ -475,6 +493,33 @@ pub enum CoreUserConsentUsedByListError {
|
||||
UnknownValue(serde_json::Value),
|
||||
}
|
||||
|
||||
/// struct for typed errors of method [`core_users_agent_allowed_app_partial_update`]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CoreUsersAgentAllowedAppPartialUpdateError {
|
||||
Status400(),
|
||||
Status403(),
|
||||
UnknownValue(serde_json::Value),
|
||||
}
|
||||
|
||||
/// struct for typed errors of method [`core_users_agent_allowed_apps_update`]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CoreUsersAgentAllowedAppsUpdateError {
|
||||
Status400(),
|
||||
Status403(),
|
||||
UnknownValue(serde_json::Value),
|
||||
}
|
||||
|
||||
/// struct for typed errors of method [`core_users_agent_create`]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CoreUsersAgentCreateError {
|
||||
Status400(models::ValidationError),
|
||||
Status403(models::GenericError),
|
||||
UnknownValue(serde_json::Value),
|
||||
}
|
||||
|
||||
/// struct for typed errors of method [`core_users_create`]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
@@ -619,6 +664,37 @@ pub enum CoreUsersUsedByListError {
|
||||
UnknownValue(serde_json::Value),
|
||||
}
|
||||
|
||||
/// Exchange an agent's API token for an authenticated session.
|
||||
pub async fn core_agent_session_create(
|
||||
configuration: &configuration::Configuration,
|
||||
) -> Result<(), Error<CoreAgentSessionCreateError>> {
|
||||
let uri_str = format!("{}/core/agent/session/", configuration.base_path);
|
||||
let mut req_builder = configuration
|
||||
.client
|
||||
.request(reqwest::Method::POST, &uri_str);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||
}
|
||||
|
||||
let req = req_builder.build()?;
|
||||
let resp = configuration.client.execute(req).await?;
|
||||
|
||||
let status = resp.status();
|
||||
|
||||
if !status.is_client_error() && !status.is_server_error() {
|
||||
Ok(())
|
||||
} else {
|
||||
let content = resp.text().await?;
|
||||
let entity: Option<CoreAgentSessionCreateError> = serde_json::from_str(&content).ok();
|
||||
Err(Error::ResponseError(ResponseContent {
|
||||
status,
|
||||
content,
|
||||
entity,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// ApplicationEntitlement Viewset
|
||||
pub async fn core_application_entitlements_create(
|
||||
configuration: &configuration::Configuration,
|
||||
@@ -3481,6 +3557,70 @@ pub async fn core_tokens_retrieve(
|
||||
}
|
||||
}
|
||||
|
||||
/// Rotate the token key and reset the expiry to 24 hours. Only callable by the token owner, the
|
||||
/// owning agent's human owner, or a superuser.
|
||||
pub async fn core_tokens_rotate_create(
|
||||
configuration: &configuration::Configuration,
|
||||
identifier: &str,
|
||||
) -> Result<models::TokenView, Error<CoreTokensRotateCreateError>> {
|
||||
// add a prefix to parameters to efficiently prevent name collisions
|
||||
let p_path_identifier = identifier;
|
||||
|
||||
let uri_str = format!(
|
||||
"{}/core/tokens/{identifier}/rotate/",
|
||||
configuration.base_path,
|
||||
identifier = crate::apis::urlencode(p_path_identifier)
|
||||
);
|
||||
let mut req_builder = configuration
|
||||
.client
|
||||
.request(reqwest::Method::POST, &uri_str);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||
}
|
||||
if let Some(ref token) = configuration.bearer_access_token {
|
||||
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||
};
|
||||
|
||||
let req = req_builder.build()?;
|
||||
let resp = configuration.client.execute(req).await?;
|
||||
|
||||
let status = resp.status();
|
||||
let content_type = resp
|
||||
.headers()
|
||||
.get("content-type")
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.unwrap_or("application/octet-stream");
|
||||
let content_type = super::ContentType::from(content_type);
|
||||
|
||||
if !status.is_client_error() && !status.is_server_error() {
|
||||
let content = resp.text().await?;
|
||||
match content_type {
|
||||
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||
ContentType::Text => {
|
||||
return Err(Error::from(serde_json::Error::custom(
|
||||
"Received `text/plain` content type response that cannot be converted to \
|
||||
`models::TokenView`",
|
||||
)));
|
||||
}
|
||||
ContentType::Unsupported(unknown_type) => {
|
||||
return Err(Error::from(serde_json::Error::custom(format!(
|
||||
"Received `{unknown_type}` content type response that cannot be converted to \
|
||||
`models::TokenView`"
|
||||
))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let content = resp.text().await?;
|
||||
let entity: Option<CoreTokensRotateCreateError> = serde_json::from_str(&content).ok();
|
||||
Err(Error::ResponseError(ResponseContent {
|
||||
status,
|
||||
content,
|
||||
entity,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Set token key. Action is logged as event. `authentik_core.set_token_key` permission is required.
|
||||
pub async fn core_tokens_set_key_create(
|
||||
configuration: &configuration::Configuration,
|
||||
@@ -4024,6 +4164,200 @@ pub async fn core_user_consent_used_by_list(
|
||||
}
|
||||
}
|
||||
|
||||
/// Add or remove a single application from an agent's allowed list. Caller must be the agent's
|
||||
/// owner or a superuser.
|
||||
pub async fn core_users_agent_allowed_app_partial_update(
|
||||
configuration: &configuration::Configuration,
|
||||
id: i32,
|
||||
patched_user_agent_allowed_app_request: Option<models::PatchedUserAgentAllowedAppRequest>,
|
||||
) -> Result<models::UserAgentAllowedApps, Error<CoreUsersAgentAllowedAppPartialUpdateError>> {
|
||||
// add a prefix to parameters to efficiently prevent name collisions
|
||||
let p_path_id = id;
|
||||
let p_body_patched_user_agent_allowed_app_request = patched_user_agent_allowed_app_request;
|
||||
|
||||
let uri_str = format!(
|
||||
"{}/core/users/{id}/agent_allowed_app/",
|
||||
configuration.base_path,
|
||||
id = p_path_id
|
||||
);
|
||||
let mut req_builder = configuration
|
||||
.client
|
||||
.request(reqwest::Method::PATCH, &uri_str);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||
}
|
||||
if let Some(ref token) = configuration.bearer_access_token {
|
||||
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||
};
|
||||
req_builder = req_builder.json(&p_body_patched_user_agent_allowed_app_request);
|
||||
|
||||
let req = req_builder.build()?;
|
||||
let resp = configuration.client.execute(req).await?;
|
||||
|
||||
let status = resp.status();
|
||||
let content_type = resp
|
||||
.headers()
|
||||
.get("content-type")
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.unwrap_or("application/octet-stream");
|
||||
let content_type = super::ContentType::from(content_type);
|
||||
|
||||
if !status.is_client_error() && !status.is_server_error() {
|
||||
let content = resp.text().await?;
|
||||
match content_type {
|
||||
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||
ContentType::Text => {
|
||||
return Err(Error::from(serde_json::Error::custom(
|
||||
"Received `text/plain` content type response that cannot be converted to \
|
||||
`models::UserAgentAllowedApps`",
|
||||
)));
|
||||
}
|
||||
ContentType::Unsupported(unknown_type) => {
|
||||
return Err(Error::from(serde_json::Error::custom(format!(
|
||||
"Received `{unknown_type}` content type response that cannot be converted to \
|
||||
`models::UserAgentAllowedApps`"
|
||||
))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let content = resp.text().await?;
|
||||
let entity: Option<CoreUsersAgentAllowedAppPartialUpdateError> =
|
||||
serde_json::from_str(&content).ok();
|
||||
Err(Error::ResponseError(ResponseContent {
|
||||
status,
|
||||
content,
|
||||
entity,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace the allowed application list for an agent user. Caller must be the agent's owner or a
|
||||
/// superuser.
|
||||
pub async fn core_users_agent_allowed_apps_update(
|
||||
configuration: &configuration::Configuration,
|
||||
id: i32,
|
||||
user_agent_allowed_apps_request: models::UserAgentAllowedAppsRequest,
|
||||
) -> Result<models::UserAgentAllowedApps, Error<CoreUsersAgentAllowedAppsUpdateError>> {
|
||||
// add a prefix to parameters to efficiently prevent name collisions
|
||||
let p_path_id = id;
|
||||
let p_body_user_agent_allowed_apps_request = user_agent_allowed_apps_request;
|
||||
|
||||
let uri_str = format!(
|
||||
"{}/core/users/{id}/agent_allowed_apps/",
|
||||
configuration.base_path,
|
||||
id = p_path_id
|
||||
);
|
||||
let mut req_builder = configuration.client.request(reqwest::Method::PUT, &uri_str);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||
}
|
||||
if let Some(ref token) = configuration.bearer_access_token {
|
||||
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||
};
|
||||
req_builder = req_builder.json(&p_body_user_agent_allowed_apps_request);
|
||||
|
||||
let req = req_builder.build()?;
|
||||
let resp = configuration.client.execute(req).await?;
|
||||
|
||||
let status = resp.status();
|
||||
let content_type = resp
|
||||
.headers()
|
||||
.get("content-type")
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.unwrap_or("application/octet-stream");
|
||||
let content_type = super::ContentType::from(content_type);
|
||||
|
||||
if !status.is_client_error() && !status.is_server_error() {
|
||||
let content = resp.text().await?;
|
||||
match content_type {
|
||||
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||
ContentType::Text => {
|
||||
return Err(Error::from(serde_json::Error::custom(
|
||||
"Received `text/plain` content type response that cannot be converted to \
|
||||
`models::UserAgentAllowedApps`",
|
||||
)));
|
||||
}
|
||||
ContentType::Unsupported(unknown_type) => {
|
||||
return Err(Error::from(serde_json::Error::custom(format!(
|
||||
"Received `{unknown_type}` content type response that cannot be converted to \
|
||||
`models::UserAgentAllowedApps`"
|
||||
))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let content = resp.text().await?;
|
||||
let entity: Option<CoreUsersAgentAllowedAppsUpdateError> =
|
||||
serde_json::from_str(&content).ok();
|
||||
Err(Error::ResponseError(ResponseContent {
|
||||
status,
|
||||
content,
|
||||
entity,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new agent user. Enterprise only. Caller must be an internal user.
|
||||
pub async fn core_users_agent_create(
|
||||
configuration: &configuration::Configuration,
|
||||
user_agent_request: models::UserAgentRequest,
|
||||
) -> Result<models::UserAgentResponse, Error<CoreUsersAgentCreateError>> {
|
||||
// add a prefix to parameters to efficiently prevent name collisions
|
||||
let p_body_user_agent_request = user_agent_request;
|
||||
|
||||
let uri_str = format!("{}/core/users/agent/", configuration.base_path);
|
||||
let mut req_builder = configuration
|
||||
.client
|
||||
.request(reqwest::Method::POST, &uri_str);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
|
||||
}
|
||||
if let Some(ref token) = configuration.bearer_access_token {
|
||||
req_builder = req_builder.bearer_auth(token.to_owned());
|
||||
};
|
||||
req_builder = req_builder.json(&p_body_user_agent_request);
|
||||
|
||||
let req = req_builder.build()?;
|
||||
let resp = configuration.client.execute(req).await?;
|
||||
|
||||
let status = resp.status();
|
||||
let content_type = resp
|
||||
.headers()
|
||||
.get("content-type")
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.unwrap_or("application/octet-stream");
|
||||
let content_type = super::ContentType::from(content_type);
|
||||
|
||||
if !status.is_client_error() && !status.is_server_error() {
|
||||
let content = resp.text().await?;
|
||||
match content_type {
|
||||
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
|
||||
ContentType::Text => {
|
||||
return Err(Error::from(serde_json::Error::custom(
|
||||
"Received `text/plain` content type response that cannot be converted to \
|
||||
`models::UserAgentResponse`",
|
||||
)));
|
||||
}
|
||||
ContentType::Unsupported(unknown_type) => {
|
||||
return Err(Error::from(serde_json::Error::custom(format!(
|
||||
"Received `{unknown_type}` content type response that cannot be converted to \
|
||||
`models::UserAgentResponse`"
|
||||
))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let content = resp.text().await?;
|
||||
let entity: Option<CoreUsersAgentCreateError> = serde_json::from_str(&content).ok();
|
||||
Err(Error::ResponseError(ResponseContent {
|
||||
status,
|
||||
content,
|
||||
entity,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// User Viewset
|
||||
pub async fn core_users_create(
|
||||
configuration: &configuration::Configuration,
|
||||
|
||||
12
packages/client-rust/src/models/mod.rs
generated
12
packages/client-rust/src/models/mod.rs
generated
@@ -1252,6 +1252,8 @@ pub mod patched_totp_device_request;
|
||||
pub use self::patched_totp_device_request::PatchedTotpDeviceRequest;
|
||||
pub mod patched_unique_password_policy_request;
|
||||
pub use self::patched_unique_password_policy_request::PatchedUniquePasswordPolicyRequest;
|
||||
pub mod patched_user_agent_allowed_app_request;
|
||||
pub use self::patched_user_agent_allowed_app_request::PatchedUserAgentAllowedAppRequest;
|
||||
pub mod patched_user_delete_stage_request;
|
||||
pub use self::patched_user_delete_stage_request::PatchedUserDeleteStageRequest;
|
||||
pub mod patched_user_kerberos_source_connection_request;
|
||||
@@ -1634,6 +1636,16 @@ pub mod user_account_request;
|
||||
pub use self::user_account_request::UserAccountRequest;
|
||||
pub mod user_account_serializer_for_role_request;
|
||||
pub use self::user_account_serializer_for_role_request::UserAccountSerializerForRoleRequest;
|
||||
pub mod user_agent_allowed_app_action_enum;
|
||||
pub use self::user_agent_allowed_app_action_enum::UserAgentAllowedAppActionEnum;
|
||||
pub mod user_agent_allowed_apps;
|
||||
pub use self::user_agent_allowed_apps::UserAgentAllowedApps;
|
||||
pub mod user_agent_allowed_apps_request;
|
||||
pub use self::user_agent_allowed_apps_request::UserAgentAllowedAppsRequest;
|
||||
pub mod user_agent_request;
|
||||
pub use self::user_agent_request::UserAgentRequest;
|
||||
pub mod user_agent_response;
|
||||
pub use self::user_agent_response::UserAgentResponse;
|
||||
pub mod user_attribute_enum;
|
||||
pub use self::user_attribute_enum::UserAttributeEnum;
|
||||
pub mod user_consent;
|
||||
|
||||
30
packages/client-rust/src/models/patched_user_agent_allowed_app_request.rs
generated
Normal file
30
packages/client-rust/src/models/patched_user_agent_allowed_app_request.rs
generated
Normal file
@@ -0,0 +1,30 @@
|
||||
// authentik
|
||||
//
|
||||
// Making authentication simple.
|
||||
//
|
||||
// The version of the OpenAPI document: 2026.5.0-rc1
|
||||
// Contact: hello@goauthentik.io
|
||||
// Generated by: https://openapi-generator.tech
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::models;
|
||||
|
||||
/// PatchedUserAgentAllowedAppRequest : Payload to add or remove a single allowed application
|
||||
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PatchedUserAgentAllowedAppRequest {
|
||||
#[serde(rename = "app", skip_serializing_if = "Option::is_none")]
|
||||
pub app: Option<uuid::Uuid>,
|
||||
#[serde(rename = "action", skip_serializing_if = "Option::is_none")]
|
||||
pub action: Option<models::UserAgentAllowedAppActionEnum>,
|
||||
}
|
||||
|
||||
impl PatchedUserAgentAllowedAppRequest {
|
||||
/// Payload to add or remove a single allowed application
|
||||
pub fn new() -> PatchedUserAgentAllowedAppRequest {
|
||||
PatchedUserAgentAllowedAppRequest {
|
||||
app: None,
|
||||
action: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
35
packages/client-rust/src/models/user_agent_allowed_app_action_enum.rs
generated
Normal file
35
packages/client-rust/src/models/user_agent_allowed_app_action_enum.rs
generated
Normal file
@@ -0,0 +1,35 @@
|
||||
// authentik
|
||||
//
|
||||
// Making authentication simple.
|
||||
//
|
||||
// The version of the OpenAPI document: 2026.5.0-rc1
|
||||
// Contact: hello@goauthentik.io
|
||||
// Generated by: https://openapi-generator.tech
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::models;
|
||||
|
||||
///
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
pub enum UserAgentAllowedAppActionEnum {
|
||||
#[serde(rename = "add")]
|
||||
Add,
|
||||
#[serde(rename = "remove")]
|
||||
Remove,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for UserAgentAllowedAppActionEnum {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Add => write!(f, "add"),
|
||||
Self::Remove => write!(f, "remove"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for UserAgentAllowedAppActionEnum {
|
||||
fn default() -> UserAgentAllowedAppActionEnum {
|
||||
Self::Add
|
||||
}
|
||||
}
|
||||
25
packages/client-rust/src/models/user_agent_allowed_apps.rs
generated
Normal file
25
packages/client-rust/src/models/user_agent_allowed_apps.rs
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
// authentik
|
||||
//
|
||||
// Making authentication simple.
|
||||
//
|
||||
// The version of the OpenAPI document: 2026.5.0-rc1
|
||||
// Contact: hello@goauthentik.io
|
||||
// Generated by: https://openapi-generator.tech
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::models;
|
||||
|
||||
/// UserAgentAllowedApps : Payload to replace an agent's allowed applications
|
||||
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct UserAgentAllowedApps {
|
||||
#[serde(rename = "allowed_apps")]
|
||||
pub allowed_apps: Vec<uuid::Uuid>,
|
||||
}
|
||||
|
||||
impl UserAgentAllowedApps {
|
||||
/// Payload to replace an agent's allowed applications
|
||||
pub fn new(allowed_apps: Vec<uuid::Uuid>) -> UserAgentAllowedApps {
|
||||
UserAgentAllowedApps { allowed_apps }
|
||||
}
|
||||
}
|
||||
25
packages/client-rust/src/models/user_agent_allowed_apps_request.rs
generated
Normal file
25
packages/client-rust/src/models/user_agent_allowed_apps_request.rs
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
// authentik
|
||||
//
|
||||
// Making authentication simple.
|
||||
//
|
||||
// The version of the OpenAPI document: 2026.5.0-rc1
|
||||
// Contact: hello@goauthentik.io
|
||||
// Generated by: https://openapi-generator.tech
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::models;
|
||||
|
||||
/// UserAgentAllowedAppsRequest : Payload to replace an agent's allowed applications
|
||||
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct UserAgentAllowedAppsRequest {
|
||||
#[serde(rename = "allowed_apps")]
|
||||
pub allowed_apps: Vec<uuid::Uuid>,
|
||||
}
|
||||
|
||||
impl UserAgentAllowedAppsRequest {
|
||||
/// Payload to replace an agent's allowed applications
|
||||
pub fn new(allowed_apps: Vec<uuid::Uuid>) -> UserAgentAllowedAppsRequest {
|
||||
UserAgentAllowedAppsRequest { allowed_apps }
|
||||
}
|
||||
}
|
||||
27
packages/client-rust/src/models/user_agent_request.rs
generated
Normal file
27
packages/client-rust/src/models/user_agent_request.rs
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
// authentik
|
||||
//
|
||||
// Making authentication simple.
|
||||
//
|
||||
// The version of the OpenAPI document: 2026.5.0-rc1
|
||||
// Contact: hello@goauthentik.io
|
||||
// Generated by: https://openapi-generator.tech
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::models;
|
||||
|
||||
/// UserAgentRequest : Payload to create an agent user
|
||||
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct UserAgentRequest {
|
||||
#[serde(rename = "name")]
|
||||
pub name: String,
|
||||
#[serde(rename = "owner", skip_serializing_if = "Option::is_none")]
|
||||
pub owner: Option<i32>,
|
||||
}
|
||||
|
||||
impl UserAgentRequest {
|
||||
/// Payload to create an agent user
|
||||
pub fn new(name: String) -> UserAgentRequest {
|
||||
UserAgentRequest { name, owner: None }
|
||||
}
|
||||
}
|
||||
39
packages/client-rust/src/models/user_agent_response.rs
generated
Normal file
39
packages/client-rust/src/models/user_agent_response.rs
generated
Normal file
@@ -0,0 +1,39 @@
|
||||
// authentik
|
||||
//
|
||||
// Making authentication simple.
|
||||
//
|
||||
// The version of the OpenAPI document: 2026.5.0-rc1
|
||||
// Contact: hello@goauthentik.io
|
||||
// Generated by: https://openapi-generator.tech
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::models;
|
||||
|
||||
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct UserAgentResponse {
|
||||
#[serde(rename = "username")]
|
||||
pub username: String,
|
||||
#[serde(rename = "token")]
|
||||
pub token: String,
|
||||
#[serde(rename = "user_uid")]
|
||||
pub user_uid: String,
|
||||
#[serde(rename = "user_pk")]
|
||||
pub user_pk: i32,
|
||||
}
|
||||
|
||||
impl UserAgentResponse {
|
||||
pub fn new(
|
||||
username: String,
|
||||
token: String,
|
||||
user_uid: String,
|
||||
user_pk: i32,
|
||||
) -> UserAgentResponse {
|
||||
UserAgentResponse {
|
||||
username,
|
||||
token,
|
||||
user_uid,
|
||||
user_pk,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ pub enum UserTypeEnum {
|
||||
ServiceAccount,
|
||||
#[serde(rename = "internal_service_account")]
|
||||
InternalServiceAccount,
|
||||
#[serde(rename = "agent")]
|
||||
Agent,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for UserTypeEnum {
|
||||
@@ -30,6 +32,7 @@ impl std::fmt::Display for UserTypeEnum {
|
||||
Self::External => write!(f, "external"),
|
||||
Self::ServiceAccount => write!(f, "service_account"),
|
||||
Self::InternalServiceAccount => write!(f, "internal_service_account"),
|
||||
Self::Agent => write!(f, "agent"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
354
packages/client-ts/src/apis/CoreApi.ts
generated
354
packages/client-ts/src/apis/CoreApi.ts
generated
@@ -41,6 +41,7 @@ import type {
|
||||
PatchedBrandRequest,
|
||||
PatchedGroupRequest,
|
||||
PatchedTokenRequest,
|
||||
PatchedUserAgentAllowedAppRequest,
|
||||
PatchedUserRequest,
|
||||
PolicyTestResult,
|
||||
SessionUser,
|
||||
@@ -53,6 +54,10 @@ import type {
|
||||
UsedBy,
|
||||
User,
|
||||
UserAccountRequest,
|
||||
UserAgentAllowedApps,
|
||||
UserAgentAllowedAppsRequest,
|
||||
UserAgentRequest,
|
||||
UserAgentResponse,
|
||||
UserConsent,
|
||||
UserPasswordSetRequest,
|
||||
UserPath,
|
||||
@@ -91,6 +96,7 @@ import {
|
||||
PatchedBrandRequestToJSON,
|
||||
PatchedGroupRequestToJSON,
|
||||
PatchedTokenRequestToJSON,
|
||||
PatchedUserAgentAllowedAppRequestToJSON,
|
||||
PatchedUserRequestToJSON,
|
||||
PolicyTestResultFromJSON,
|
||||
SessionUserFromJSON,
|
||||
@@ -102,6 +108,10 @@ import {
|
||||
TransactionApplicationResponseFromJSON,
|
||||
UsedByFromJSON,
|
||||
UserAccountRequestToJSON,
|
||||
UserAgentAllowedAppsFromJSON,
|
||||
UserAgentAllowedAppsRequestToJSON,
|
||||
UserAgentRequestToJSON,
|
||||
UserAgentResponseFromJSON,
|
||||
UserConsentFromJSON,
|
||||
UserFromJSON,
|
||||
UserPasswordSetRequestToJSON,
|
||||
@@ -358,6 +368,10 @@ export interface CoreTokensRetrieveRequest {
|
||||
identifier: string;
|
||||
}
|
||||
|
||||
export interface CoreTokensRotateCreateRequest {
|
||||
identifier: string;
|
||||
}
|
||||
|
||||
export interface CoreTokensSetKeyCreateRequest {
|
||||
identifier: string;
|
||||
tokenSetKeyRequest: TokenSetKeyRequest;
|
||||
@@ -401,6 +415,20 @@ export interface CoreUserConsentUsedByListRequest {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface CoreUsersAgentAllowedAppPartialUpdateRequest {
|
||||
id: number;
|
||||
patchedUserAgentAllowedAppRequest?: PatchedUserAgentAllowedAppRequest;
|
||||
}
|
||||
|
||||
export interface CoreUsersAgentAllowedAppsUpdateRequest {
|
||||
id: number;
|
||||
userAgentAllowedAppsRequest: UserAgentAllowedAppsRequest;
|
||||
}
|
||||
|
||||
export interface CoreUsersAgentCreateRequest {
|
||||
userAgentRequest: UserAgentRequest;
|
||||
}
|
||||
|
||||
export interface CoreUsersCreateRequest {
|
||||
userRequest: UserRequest;
|
||||
}
|
||||
@@ -521,6 +549,45 @@ export interface CoreUsersUsedByListRequest {
|
||||
*
|
||||
*/
|
||||
export class CoreApi extends runtime.BaseAPI {
|
||||
/**
|
||||
* Creates request options for coreAgentSessionCreate without sending the request
|
||||
*/
|
||||
async coreAgentSessionCreateRequestOpts(): Promise<runtime.RequestOpts> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
let urlPath = `/core/agent/session/`;
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "POST",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Exchange an agent\'s API token for an authenticated session.
|
||||
*/
|
||||
async coreAgentSessionCreateRaw(
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<void>> {
|
||||
const requestOptions = await this.coreAgentSessionCreateRequestOpts();
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.VoidApiResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exchange an agent\'s API token for an authenticated session.
|
||||
*/
|
||||
async coreAgentSessionCreate(
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<void> {
|
||||
await this.coreAgentSessionCreateRaw(initOverrides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for coreApplicationEntitlementsCreate without sending the request
|
||||
*/
|
||||
@@ -3575,6 +3642,70 @@ export class CoreApi extends runtime.BaseAPI {
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for coreTokensRotateCreate without sending the request
|
||||
*/
|
||||
async coreTokensRotateCreateRequestOpts(
|
||||
requestParameters: CoreTokensRotateCreateRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["identifier"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"identifier",
|
||||
'Required parameter "identifier" was null or undefined when calling coreTokensRotateCreate().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/core/tokens/{identifier}/rotate/`;
|
||||
urlPath = urlPath.replace(
|
||||
`{${"identifier"}}`,
|
||||
encodeURIComponent(String(requestParameters["identifier"])),
|
||||
);
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "POST",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the token key and reset the expiry to 24 hours. Only callable by the token owner, the owning agent\'s human owner, or a superuser.
|
||||
*/
|
||||
async coreTokensRotateCreateRaw(
|
||||
requestParameters: CoreTokensRotateCreateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<TokenView>> {
|
||||
const requestOptions = await this.coreTokensRotateCreateRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => TokenViewFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the token key and reset the expiry to 24 hours. Only callable by the token owner, the owning agent\'s human owner, or a superuser.
|
||||
*/
|
||||
async coreTokensRotateCreate(
|
||||
requestParameters: CoreTokensRotateCreateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<TokenView> {
|
||||
const response = await this.coreTokensRotateCreateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for coreTokensSetKeyCreate without sending the request
|
||||
*/
|
||||
@@ -4182,6 +4313,229 @@ export class CoreApi extends runtime.BaseAPI {
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for coreUsersAgentAllowedAppPartialUpdate without sending the request
|
||||
*/
|
||||
async coreUsersAgentAllowedAppPartialUpdateRequestOpts(
|
||||
requestParameters: CoreUsersAgentAllowedAppPartialUpdateRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["id"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"id",
|
||||
'Required parameter "id" was null or undefined when calling coreUsersAgentAllowedAppPartialUpdate().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters["Content-Type"] = "application/json";
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/core/users/{id}/agent_allowed_app/`;
|
||||
urlPath = urlPath.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters["id"])));
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "PATCH",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: PatchedUserAgentAllowedAppRequestToJSON(
|
||||
requestParameters["patchedUserAgentAllowedAppRequest"],
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or remove a single application from an agent\'s allowed list. Caller must be the agent\'s owner or a superuser.
|
||||
*/
|
||||
async coreUsersAgentAllowedAppPartialUpdateRaw(
|
||||
requestParameters: CoreUsersAgentAllowedAppPartialUpdateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<UserAgentAllowedApps>> {
|
||||
const requestOptions =
|
||||
await this.coreUsersAgentAllowedAppPartialUpdateRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) =>
|
||||
UserAgentAllowedAppsFromJSON(jsonValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or remove a single application from an agent\'s allowed list. Caller must be the agent\'s owner or a superuser.
|
||||
*/
|
||||
async coreUsersAgentAllowedAppPartialUpdate(
|
||||
requestParameters: CoreUsersAgentAllowedAppPartialUpdateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<UserAgentAllowedApps | null | undefined> {
|
||||
const response = await this.coreUsersAgentAllowedAppPartialUpdateRaw(
|
||||
requestParameters,
|
||||
initOverrides,
|
||||
);
|
||||
switch (response.raw.status) {
|
||||
case 200:
|
||||
return await response.value();
|
||||
case 204:
|
||||
return null;
|
||||
default:
|
||||
return await response.value();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for coreUsersAgentAllowedAppsUpdate without sending the request
|
||||
*/
|
||||
async coreUsersAgentAllowedAppsUpdateRequestOpts(
|
||||
requestParameters: CoreUsersAgentAllowedAppsUpdateRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["id"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"id",
|
||||
'Required parameter "id" was null or undefined when calling coreUsersAgentAllowedAppsUpdate().',
|
||||
);
|
||||
}
|
||||
|
||||
if (requestParameters["userAgentAllowedAppsRequest"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"userAgentAllowedAppsRequest",
|
||||
'Required parameter "userAgentAllowedAppsRequest" was null or undefined when calling coreUsersAgentAllowedAppsUpdate().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters["Content-Type"] = "application/json";
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/core/users/{id}/agent_allowed_apps/`;
|
||||
urlPath = urlPath.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters["id"])));
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "PUT",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: UserAgentAllowedAppsRequestToJSON(
|
||||
requestParameters["userAgentAllowedAppsRequest"],
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the allowed application list for an agent user. Caller must be the agent\'s owner or a superuser.
|
||||
*/
|
||||
async coreUsersAgentAllowedAppsUpdateRaw(
|
||||
requestParameters: CoreUsersAgentAllowedAppsUpdateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<UserAgentAllowedApps>> {
|
||||
const requestOptions =
|
||||
await this.coreUsersAgentAllowedAppsUpdateRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) =>
|
||||
UserAgentAllowedAppsFromJSON(jsonValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the allowed application list for an agent user. Caller must be the agent\'s owner or a superuser.
|
||||
*/
|
||||
async coreUsersAgentAllowedAppsUpdate(
|
||||
requestParameters: CoreUsersAgentAllowedAppsUpdateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<UserAgentAllowedApps> {
|
||||
const response = await this.coreUsersAgentAllowedAppsUpdateRaw(
|
||||
requestParameters,
|
||||
initOverrides,
|
||||
);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for coreUsersAgentCreate without sending the request
|
||||
*/
|
||||
async coreUsersAgentCreateRequestOpts(
|
||||
requestParameters: CoreUsersAgentCreateRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["userAgentRequest"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"userAgentRequest",
|
||||
'Required parameter "userAgentRequest" was null or undefined when calling coreUsersAgentCreate().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters["Content-Type"] = "application/json";
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/core/users/agent/`;
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "POST",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: UserAgentRequestToJSON(requestParameters["userAgentRequest"]),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new agent user. Enterprise only. Caller must be an internal user.
|
||||
*/
|
||||
async coreUsersAgentCreateRaw(
|
||||
requestParameters: CoreUsersAgentCreateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<UserAgentResponse>> {
|
||||
const requestOptions = await this.coreUsersAgentCreateRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) =>
|
||||
UserAgentResponseFromJSON(jsonValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new agent user. Enterprise only. Caller must be an internal user.
|
||||
*/
|
||||
async coreUsersAgentCreate(
|
||||
requestParameters: CoreUsersAgentCreateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<UserAgentResponse> {
|
||||
const response = await this.coreUsersAgentCreateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for coreUsersCreate without sending the request
|
||||
*/
|
||||
|
||||
90
packages/client-ts/src/models/PatchedUserAgentAllowedAppRequest.ts
generated
Normal file
90
packages/client-ts/src/models/PatchedUserAgentAllowedAppRequest.ts
generated
Normal file
@@ -0,0 +1,90 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import type { UserAgentAllowedAppActionEnum } from "./UserAgentAllowedAppActionEnum";
|
||||
import {
|
||||
UserAgentAllowedAppActionEnumFromJSON,
|
||||
UserAgentAllowedAppActionEnumToJSON,
|
||||
} from "./UserAgentAllowedAppActionEnum";
|
||||
|
||||
/**
|
||||
* Payload to add or remove a single allowed application
|
||||
* @export
|
||||
* @interface PatchedUserAgentAllowedAppRequest
|
||||
*/
|
||||
export interface PatchedUserAgentAllowedAppRequest {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedUserAgentAllowedAppRequest
|
||||
*/
|
||||
app?: string;
|
||||
/**
|
||||
*
|
||||
* @type {UserAgentAllowedAppActionEnum}
|
||||
* @memberof PatchedUserAgentAllowedAppRequest
|
||||
*/
|
||||
action?: UserAgentAllowedAppActionEnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the PatchedUserAgentAllowedAppRequest interface.
|
||||
*/
|
||||
export function instanceOfPatchedUserAgentAllowedAppRequest(
|
||||
value: object,
|
||||
): value is PatchedUserAgentAllowedAppRequest {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function PatchedUserAgentAllowedAppRequestFromJSON(
|
||||
json: any,
|
||||
): PatchedUserAgentAllowedAppRequest {
|
||||
return PatchedUserAgentAllowedAppRequestFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function PatchedUserAgentAllowedAppRequestFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): PatchedUserAgentAllowedAppRequest {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
app: json["app"] == null ? undefined : json["app"],
|
||||
action:
|
||||
json["action"] == null
|
||||
? undefined
|
||||
: UserAgentAllowedAppActionEnumFromJSON(json["action"]),
|
||||
};
|
||||
}
|
||||
|
||||
export function PatchedUserAgentAllowedAppRequestToJSON(
|
||||
json: any,
|
||||
): PatchedUserAgentAllowedAppRequest {
|
||||
return PatchedUserAgentAllowedAppRequestToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function PatchedUserAgentAllowedAppRequestToJSONTyped(
|
||||
value?: PatchedUserAgentAllowedAppRequest | null,
|
||||
ignoreDiscriminator: boolean = false,
|
||||
): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
app: value["app"],
|
||||
action: UserAgentAllowedAppActionEnumToJSON(value["action"]),
|
||||
};
|
||||
}
|
||||
63
packages/client-ts/src/models/UserAgentAllowedAppActionEnum.ts
generated
Normal file
63
packages/client-ts/src/models/UserAgentAllowedAppActionEnum.ts
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
export const UserAgentAllowedAppActionEnum = {
|
||||
Add: "add",
|
||||
Remove: "remove",
|
||||
UnknownDefaultOpenApi: "11184809",
|
||||
} as const;
|
||||
export type UserAgentAllowedAppActionEnum =
|
||||
(typeof UserAgentAllowedAppActionEnum)[keyof typeof UserAgentAllowedAppActionEnum];
|
||||
|
||||
export function instanceOfUserAgentAllowedAppActionEnum(value: any): boolean {
|
||||
for (const key in UserAgentAllowedAppActionEnum) {
|
||||
if (Object.prototype.hasOwnProperty.call(UserAgentAllowedAppActionEnum, key)) {
|
||||
if (
|
||||
UserAgentAllowedAppActionEnum[key as keyof typeof UserAgentAllowedAppActionEnum] ===
|
||||
value
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppActionEnumFromJSON(json: any): UserAgentAllowedAppActionEnum {
|
||||
return UserAgentAllowedAppActionEnumFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppActionEnumFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): UserAgentAllowedAppActionEnum {
|
||||
return json as UserAgentAllowedAppActionEnum;
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppActionEnumToJSON(
|
||||
value?: UserAgentAllowedAppActionEnum | null,
|
||||
): any {
|
||||
return value as any;
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppActionEnumToJSONTyped(
|
||||
value: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): UserAgentAllowedAppActionEnum {
|
||||
return value as UserAgentAllowedAppActionEnum;
|
||||
}
|
||||
68
packages/client-ts/src/models/UserAgentAllowedApps.ts
generated
Normal file
68
packages/client-ts/src/models/UserAgentAllowedApps.ts
generated
Normal file
@@ -0,0 +1,68 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Payload to replace an agent's allowed applications
|
||||
* @export
|
||||
* @interface UserAgentAllowedApps
|
||||
*/
|
||||
export interface UserAgentAllowedApps {
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof UserAgentAllowedApps
|
||||
*/
|
||||
allowedApps: Array<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the UserAgentAllowedApps interface.
|
||||
*/
|
||||
export function instanceOfUserAgentAllowedApps(value: object): value is UserAgentAllowedApps {
|
||||
if (!("allowedApps" in value) || value["allowedApps"] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppsFromJSON(json: any): UserAgentAllowedApps {
|
||||
return UserAgentAllowedAppsFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppsFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): UserAgentAllowedApps {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
allowedApps: json["allowed_apps"],
|
||||
};
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppsToJSON(json: any): UserAgentAllowedApps {
|
||||
return UserAgentAllowedAppsToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppsToJSONTyped(
|
||||
value?: UserAgentAllowedApps | null,
|
||||
ignoreDiscriminator: boolean = false,
|
||||
): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
allowed_apps: value["allowedApps"],
|
||||
};
|
||||
}
|
||||
70
packages/client-ts/src/models/UserAgentAllowedAppsRequest.ts
generated
Normal file
70
packages/client-ts/src/models/UserAgentAllowedAppsRequest.ts
generated
Normal file
@@ -0,0 +1,70 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Payload to replace an agent's allowed applications
|
||||
* @export
|
||||
* @interface UserAgentAllowedAppsRequest
|
||||
*/
|
||||
export interface UserAgentAllowedAppsRequest {
|
||||
/**
|
||||
*
|
||||
* @type {Array<string>}
|
||||
* @memberof UserAgentAllowedAppsRequest
|
||||
*/
|
||||
allowedApps: Array<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the UserAgentAllowedAppsRequest interface.
|
||||
*/
|
||||
export function instanceOfUserAgentAllowedAppsRequest(
|
||||
value: object,
|
||||
): value is UserAgentAllowedAppsRequest {
|
||||
if (!("allowedApps" in value) || value["allowedApps"] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppsRequestFromJSON(json: any): UserAgentAllowedAppsRequest {
|
||||
return UserAgentAllowedAppsRequestFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppsRequestFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): UserAgentAllowedAppsRequest {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
allowedApps: json["allowed_apps"],
|
||||
};
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppsRequestToJSON(json: any): UserAgentAllowedAppsRequest {
|
||||
return UserAgentAllowedAppsRequestToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function UserAgentAllowedAppsRequestToJSONTyped(
|
||||
value?: UserAgentAllowedAppsRequest | null,
|
||||
ignoreDiscriminator: boolean = false,
|
||||
): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
allowed_apps: value["allowedApps"],
|
||||
};
|
||||
}
|
||||
76
packages/client-ts/src/models/UserAgentRequest.ts
generated
Normal file
76
packages/client-ts/src/models/UserAgentRequest.ts
generated
Normal file
@@ -0,0 +1,76 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Payload to create an agent user
|
||||
* @export
|
||||
* @interface UserAgentRequest
|
||||
*/
|
||||
export interface UserAgentRequest {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UserAgentRequest
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof UserAgentRequest
|
||||
*/
|
||||
owner?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the UserAgentRequest interface.
|
||||
*/
|
||||
export function instanceOfUserAgentRequest(value: object): value is UserAgentRequest {
|
||||
if (!("name" in value) || value["name"] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function UserAgentRequestFromJSON(json: any): UserAgentRequest {
|
||||
return UserAgentRequestFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function UserAgentRequestFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): UserAgentRequest {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
name: json["name"],
|
||||
owner: json["owner"] == null ? undefined : json["owner"],
|
||||
};
|
||||
}
|
||||
|
||||
export function UserAgentRequestToJSON(json: any): UserAgentRequest {
|
||||
return UserAgentRequestToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function UserAgentRequestToJSONTyped(
|
||||
value?: UserAgentRequest | null,
|
||||
ignoreDiscriminator: boolean = false,
|
||||
): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
name: value["name"],
|
||||
owner: value["owner"],
|
||||
};
|
||||
}
|
||||
95
packages/client-ts/src/models/UserAgentResponse.ts
generated
Normal file
95
packages/client-ts/src/models/UserAgentResponse.ts
generated
Normal file
@@ -0,0 +1,95 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface UserAgentResponse
|
||||
*/
|
||||
export interface UserAgentResponse {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UserAgentResponse
|
||||
*/
|
||||
username: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UserAgentResponse
|
||||
*/
|
||||
token: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UserAgentResponse
|
||||
*/
|
||||
userUid: string;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof UserAgentResponse
|
||||
*/
|
||||
userPk: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the UserAgentResponse interface.
|
||||
*/
|
||||
export function instanceOfUserAgentResponse(value: object): value is UserAgentResponse {
|
||||
if (!("username" in value) || value["username"] === undefined) return false;
|
||||
if (!("token" in value) || value["token"] === undefined) return false;
|
||||
if (!("userUid" in value) || value["userUid"] === undefined) return false;
|
||||
if (!("userPk" in value) || value["userPk"] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function UserAgentResponseFromJSON(json: any): UserAgentResponse {
|
||||
return UserAgentResponseFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function UserAgentResponseFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): UserAgentResponse {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
username: json["username"],
|
||||
token: json["token"],
|
||||
userUid: json["user_uid"],
|
||||
userPk: json["user_pk"],
|
||||
};
|
||||
}
|
||||
|
||||
export function UserAgentResponseToJSON(json: any): UserAgentResponse {
|
||||
return UserAgentResponseToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function UserAgentResponseToJSONTyped(
|
||||
value?: UserAgentResponse | null,
|
||||
ignoreDiscriminator: boolean = false,
|
||||
): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
username: value["username"],
|
||||
token: value["token"],
|
||||
user_uid: value["userUid"],
|
||||
user_pk: value["userPk"],
|
||||
};
|
||||
}
|
||||
1
packages/client-ts/src/models/UserTypeEnum.ts
generated
1
packages/client-ts/src/models/UserTypeEnum.ts
generated
@@ -21,6 +21,7 @@ export const UserTypeEnum = {
|
||||
External: "external",
|
||||
ServiceAccount: "service_account",
|
||||
InternalServiceAccount: "internal_service_account",
|
||||
Agent: "agent",
|
||||
UnknownDefaultOpenApi: "11184809",
|
||||
} as const;
|
||||
export type UserTypeEnum = (typeof UserTypeEnum)[keyof typeof UserTypeEnum];
|
||||
|
||||
6
packages/client-ts/src/models/index.ts
generated
6
packages/client-ts/src/models/index.ts
generated
@@ -628,6 +628,7 @@ export * from "./PatchedTelegramSourceRequest";
|
||||
export * from "./PatchedTenantRequest";
|
||||
export * from "./PatchedTokenRequest";
|
||||
export * from "./PatchedUniquePasswordPolicyRequest";
|
||||
export * from "./PatchedUserAgentAllowedAppRequest";
|
||||
export * from "./PatchedUserDeleteStageRequest";
|
||||
export * from "./PatchedUserKerberosSourceConnectionRequest";
|
||||
export * from "./PatchedUserLDAPSourceConnectionRequest";
|
||||
@@ -818,6 +819,11 @@ export * from "./UsedByActionEnum";
|
||||
export * from "./User";
|
||||
export * from "./UserAccountRequest";
|
||||
export * from "./UserAccountSerializerForRoleRequest";
|
||||
export * from "./UserAgentAllowedAppActionEnum";
|
||||
export * from "./UserAgentAllowedApps";
|
||||
export * from "./UserAgentAllowedAppsRequest";
|
||||
export * from "./UserAgentRequest";
|
||||
export * from "./UserAgentResponse";
|
||||
export * from "./UserAttributeEnum";
|
||||
export * from "./UserConsent";
|
||||
export * from "./UserCreationModeEnum";
|
||||
|
||||
202
schema.yml
202
schema.yml
@@ -2528,6 +2528,21 @@ paths:
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/core/agent/session/:
|
||||
post:
|
||||
operationId: core_agent_session_create
|
||||
description: Exchange an agent's API token for an authenticated session.
|
||||
tags:
|
||||
- core
|
||||
security:
|
||||
- {}
|
||||
responses:
|
||||
'200':
|
||||
description: No response body
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/core/application_entitlements/:
|
||||
get:
|
||||
operationId: core_application_entitlements_list
|
||||
@@ -3896,6 +3911,33 @@ paths:
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/core/tokens/{identifier}/rotate/:
|
||||
post:
|
||||
operationId: core_tokens_rotate_create
|
||||
description: |-
|
||||
Rotate the token key and reset the expiry to 24 hours. Only callable by the token
|
||||
owner, the owning agent's human owner, or a superuser.
|
||||
parameters:
|
||||
- in: path
|
||||
name: identifier
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
tags:
|
||||
- core
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/TokenView'
|
||||
description: ''
|
||||
'403':
|
||||
description: Not the token owner, agent owner, or superuser
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
/core/tokens/{identifier}/set_key/:
|
||||
post:
|
||||
operationId: core_tokens_set_key_create
|
||||
@@ -4406,6 +4448,75 @@ paths:
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/core/users/{id}/agent_allowed_app/:
|
||||
patch:
|
||||
operationId: core_users_agent_allowed_app_partial_update
|
||||
description: |-
|
||||
Add or remove a single application from an agent's allowed list.
|
||||
Caller must be the agent's owner or a superuser.
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this User.
|
||||
required: true
|
||||
tags:
|
||||
- core
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PatchedUserAgentAllowedAppRequest'
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserAgentAllowedApps'
|
||||
description: ''
|
||||
'204':
|
||||
description: Application removed
|
||||
'400':
|
||||
description: Invalid app UUID or owner lacks access
|
||||
'403':
|
||||
description: Not the agent's owner or superuser
|
||||
/core/users/{id}/agent_allowed_apps/:
|
||||
put:
|
||||
operationId: core_users_agent_allowed_apps_update
|
||||
description: |-
|
||||
Replace the allowed application list for an agent user.
|
||||
Caller must be the agent's owner or a superuser.
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
description: A unique integer value identifying this User.
|
||||
required: true
|
||||
tags:
|
||||
- core
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserAgentAllowedAppsRequest'
|
||||
required: true
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserAgentAllowedApps'
|
||||
description: ''
|
||||
'400':
|
||||
description: Invalid app UUIDs or owner lacks access
|
||||
'403':
|
||||
description: Not the agent's owner or superuser
|
||||
/core/users/{id}/impersonate/:
|
||||
post:
|
||||
operationId: core_users_impersonate_create
|
||||
@@ -4550,6 +4661,32 @@ paths:
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/core/users/agent/:
|
||||
post:
|
||||
operationId: core_users_agent_create
|
||||
description: Create a new agent user. Enterprise only. Caller must be an internal
|
||||
user.
|
||||
tags:
|
||||
- core
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserAgentRequest'
|
||||
required: true
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserAgentResponse'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/core/users/export/:
|
||||
post:
|
||||
operationId: core_users_export_create
|
||||
@@ -50622,6 +50759,15 @@ components:
|
||||
maximum: 2147483647
|
||||
minimum: 0
|
||||
description: Number of passwords to check against.
|
||||
PatchedUserAgentAllowedAppRequest:
|
||||
type: object
|
||||
description: Payload to add or remove a single allowed application
|
||||
properties:
|
||||
app:
|
||||
type: string
|
||||
format: uuid
|
||||
action:
|
||||
$ref: '#/components/schemas/UserAgentAllowedAppActionEnum'
|
||||
PatchedUserDeleteStageRequest:
|
||||
type: object
|
||||
description: UserDeleteStage Serializer
|
||||
@@ -56801,6 +56947,61 @@ components:
|
||||
type: integer
|
||||
required:
|
||||
- pk
|
||||
UserAgentAllowedAppActionEnum:
|
||||
enum:
|
||||
- add
|
||||
- remove
|
||||
type: string
|
||||
UserAgentAllowedApps:
|
||||
type: object
|
||||
description: Payload to replace an agent's allowed applications
|
||||
properties:
|
||||
allowed_apps:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
required:
|
||||
- allowed_apps
|
||||
UserAgentAllowedAppsRequest:
|
||||
type: object
|
||||
description: Payload to replace an agent's allowed applications
|
||||
properties:
|
||||
allowed_apps:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
required:
|
||||
- allowed_apps
|
||||
UserAgentRequest:
|
||||
type: object
|
||||
description: Payload to create an agent user
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 150
|
||||
owner:
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
UserAgentResponse:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
user_uid:
|
||||
type: string
|
||||
user_pk:
|
||||
type: integer
|
||||
required:
|
||||
- token
|
||||
- user_pk
|
||||
- user_uid
|
||||
- username
|
||||
UserAttributeEnum:
|
||||
enum:
|
||||
- username
|
||||
@@ -57706,6 +57907,7 @@ components:
|
||||
- external
|
||||
- service_account
|
||||
- internal_service_account
|
||||
- agent
|
||||
type: string
|
||||
UserVerificationEnum:
|
||||
enum:
|
||||
|
||||
74
web/src/admin/users/AgentAddApplicationForm.ts
Normal file
74
web/src/admin/users/AgentAddApplicationForm.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import "#elements/forms/HorizontalFormElement";
|
||||
import "#elements/forms/SearchSelect/index";
|
||||
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
|
||||
import { Form } from "#elements/forms/Form";
|
||||
|
||||
import { Application, CoreApi, CoreApplicationsListRequest, User } from "@goauthentik/api";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { html, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
const USER_ATTRIBUTE_AGENT_OWNER_PK = "goauthentik.io/agent/owner-pk";
|
||||
|
||||
@customElement("ak-agent-add-application-form")
|
||||
export class AgentAddApplicationForm extends Form<{ app: string }> {
|
||||
public override headline = msg("Add Application");
|
||||
public override submitLabel = msg("Add");
|
||||
|
||||
@property({ attribute: false })
|
||||
public agent: User | null = null;
|
||||
|
||||
public override getSuccessMessage(): string {
|
||||
return msg("Successfully added application.");
|
||||
}
|
||||
|
||||
async send(data: { app: string }): Promise<{ app: string }> {
|
||||
if (!this.agent) throw new Error("Agent not set");
|
||||
await new CoreApi(DEFAULT_CONFIG).coreUsersAgentAllowedAppPartialUpdate({
|
||||
id: this.agent.pk,
|
||||
patchedUserAgentAllowedAppRequest: { app: data.app, action: "add" },
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
protected override renderForm(): TemplateResult {
|
||||
const ownerPk = this.agent?.attributes?.[USER_ATTRIBUTE_AGENT_OWNER_PK];
|
||||
|
||||
return html`<ak-form-element-horizontal label=${msg("Application")} required name="app">
|
||||
<ak-search-select
|
||||
placeholder=${msg("Select an application...")}
|
||||
.fetchObjects=${async (query?: string): Promise<Application[]> => {
|
||||
const args: CoreApplicationsListRequest = {
|
||||
ordering: "name",
|
||||
pageSize: 20,
|
||||
forUser: ownerPk ? Number(ownerPk) : undefined,
|
||||
};
|
||||
if (query) {
|
||||
args.search = query;
|
||||
}
|
||||
const result = await new CoreApi(DEFAULT_CONFIG).coreApplicationsList(args);
|
||||
return result.results;
|
||||
}}
|
||||
.renderElement=${(app: Application): string => {
|
||||
return app.name;
|
||||
}}
|
||||
.value=${(app: Application | undefined): string | undefined => {
|
||||
return app?.pk;
|
||||
}}
|
||||
.renderDescription=${(app: Application): TemplateResult => {
|
||||
return html`${app.group || msg("No group")}`;
|
||||
}}
|
||||
>
|
||||
</ak-search-select>
|
||||
</ak-form-element-horizontal>`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-agent-add-application-form": AgentAddApplicationForm;
|
||||
}
|
||||
}
|
||||
107
web/src/admin/users/AgentForm.ts
Normal file
107
web/src/admin/users/AgentForm.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import "#components/ak-hidden-text-input";
|
||||
import "#elements/forms/HorizontalFormElement";
|
||||
import "#components/ak-text-input";
|
||||
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
|
||||
import { Form } from "#elements/forms/Form";
|
||||
import { ModalForm } from "#elements/forms/ModalForm";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
|
||||
import { CoreApi, UserAgentRequest, UserAgentResponse } from "@goauthentik/api";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { html, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
@customElement("ak-user-agent-form")
|
||||
export class AgentForm extends Form<UserAgentRequest> {
|
||||
public static override verboseName = msg("Agent");
|
||||
public static override verboseNamePlural = msg("Agents");
|
||||
public override cancelButtonLabel = msg("Close");
|
||||
|
||||
@property({ attribute: false })
|
||||
result: UserAgentResponse | null = null;
|
||||
|
||||
getSuccessMessage(): string {
|
||||
return msg("Successfully created agent user.");
|
||||
}
|
||||
|
||||
async send(data: UserAgentRequest): Promise<UserAgentResponse> {
|
||||
const result = await new CoreApi(DEFAULT_CONFIG).coreUsersAgentCreate({
|
||||
userAgentRequest: data,
|
||||
});
|
||||
this.result = result;
|
||||
if (this.parentElement instanceof ModalForm) {
|
||||
this.parentElement.showSubmitButton = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override reset(): void {
|
||||
super.reset();
|
||||
this.result = null;
|
||||
if (this.parentElement instanceof ModalForm) {
|
||||
this.parentElement.showSubmitButton = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override renderForm(): TemplateResult {
|
||||
return html`<ak-text-input
|
||||
name="name"
|
||||
label=${msg("Username")}
|
||||
placeholder=${msg("Type a username for the agent...")}
|
||||
value=""
|
||||
input-hint="code"
|
||||
required
|
||||
maxlength=${150}
|
||||
autofocus
|
||||
help=${msg(
|
||||
"The agent's primary identifier used for authentication. 150 characters or fewer.",
|
||||
)}
|
||||
></ak-text-input>`;
|
||||
}
|
||||
|
||||
protected renderResponseForm(): SlottedTemplateResult {
|
||||
return html`<p>
|
||||
${msg(
|
||||
"Use the username and token below to authenticate. The token expires in 24 hours and must be rotated before expiry.",
|
||||
)}
|
||||
</p>
|
||||
<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-text-input
|
||||
name="name"
|
||||
label=${msg("Username")}
|
||||
autocomplete="off"
|
||||
value=${ifDefined(this.result?.username)}
|
||||
input-hint="code"
|
||||
readonly
|
||||
></ak-text-input>
|
||||
|
||||
<ak-hidden-text-input
|
||||
label=${msg("Token")}
|
||||
value="${this.result?.token ?? ""}"
|
||||
input-hint="code"
|
||||
readonly
|
||||
.help=${msg(
|
||||
"Valid for 24 hours. The agent must rotate the token before it expires. If the rotation window is missed, the owner must issue a new token.",
|
||||
)}
|
||||
>
|
||||
</ak-hidden-text-input>
|
||||
</form>`;
|
||||
}
|
||||
|
||||
protected override renderFormWrapper(): SlottedTemplateResult {
|
||||
if (this.result) {
|
||||
return this.renderResponseForm();
|
||||
}
|
||||
return super.renderFormWrapper();
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-user-agent-form": AgentForm;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
import "#admin/users/AgentAddApplicationForm";
|
||||
import "#elements/AppIcon";
|
||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
|
||||
import { renderModal } from "#elements/dialogs";
|
||||
import { PaginatedResponse, Table, TableColumn } from "#elements/table/Table";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
import { ifPresent } from "#elements/utils/attributes";
|
||||
|
||||
import { applicationListStyle } from "#admin/applications/ApplicationListPage";
|
||||
|
||||
import { Application, CoreApi, User } from "@goauthentik/api";
|
||||
import { Application, CoreApi, User, UserTypeEnum } from "@goauthentik/api";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, html, nothing } from "lit";
|
||||
@@ -22,6 +24,10 @@ export class UserApplicationTable extends Table<Application> {
|
||||
|
||||
static styles: CSSResult[] = [...super.styles, applicationListStyle];
|
||||
|
||||
private get isAgent(): boolean {
|
||||
return this.user?.type === UserTypeEnum.Agent;
|
||||
}
|
||||
|
||||
async apiEndpoint(): Promise<PaginatedResponse<Application>> {
|
||||
return new CoreApi(DEFAULT_CONFIG).coreApplicationsList({
|
||||
...(await this.defaultEndpointConfig()),
|
||||
@@ -38,6 +44,35 @@ export class UserApplicationTable extends Table<Application> {
|
||||
[msg("Actions"), null, msg("Row Actions")],
|
||||
];
|
||||
|
||||
private async removeApplication(app: Application): Promise<void> {
|
||||
if (!this.user) return;
|
||||
await new CoreApi(DEFAULT_CONFIG).coreUsersAgentAllowedAppPartialUpdate({
|
||||
id: this.user.pk,
|
||||
patchedUserAgentAllowedAppRequest: { app: String(app.pk), action: "remove" },
|
||||
});
|
||||
this.fetch();
|
||||
}
|
||||
|
||||
protected openAddApplicationModal = () => {
|
||||
renderModal(
|
||||
html`<ak-agent-add-application-form
|
||||
.agent=${this.user}
|
||||
></ak-agent-add-application-form>`,
|
||||
).then(() => {
|
||||
this.fetch();
|
||||
});
|
||||
};
|
||||
|
||||
protected override renderToolbar(): SlottedTemplateResult {
|
||||
if (!this.isAgent) {
|
||||
return super.renderToolbar();
|
||||
}
|
||||
return html`<button class="pf-c-button pf-m-primary" @click=${this.openAddApplicationModal}>
|
||||
${msg("Add Application")}
|
||||
</button>
|
||||
${super.renderToolbar()}`;
|
||||
}
|
||||
|
||||
row(item: Application): SlottedTemplateResult[] {
|
||||
return [
|
||||
html`<ak-app-icon name=${item.name} icon=${ifPresent(item.metaIconUrl)}></ak-app-icon>`,
|
||||
@@ -71,6 +106,16 @@ export class UserApplicationTable extends Table<Application> {
|
||||
</pf-tooltip>
|
||||
</a>`
|
||||
: nothing}
|
||||
${this.isAgent
|
||||
? html`<button
|
||||
class="pf-c-button pf-m-plain"
|
||||
@click=${() => this.removeApplication(item)}
|
||||
>
|
||||
<pf-tooltip position="top" content=${msg("Remove")}>
|
||||
<i class="fas fa-trash" aria-hidden="true"></i>
|
||||
</pf-tooltip>
|
||||
</button>`
|
||||
: nothing}
|
||||
</div>`,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -102,6 +102,10 @@ export class UserForm extends ModelForm<User, number> {
|
||||
verboseName: msg("Service Account"),
|
||||
verboseNamePlural: msg("Service Accounts"),
|
||||
}))
|
||||
.with(UserTypeEnum.Agent, () => ({
|
||||
verboseName: msg("Agent User"),
|
||||
verboseNamePlural: msg("Agent Users"),
|
||||
}))
|
||||
.otherwise(() => ({
|
||||
verboseName: msg("User"),
|
||||
verboseNamePlural: msg("Users"),
|
||||
@@ -203,27 +207,44 @@ export class UserForm extends ModelForm<User, number> {
|
||||
|
||||
${this.userType
|
||||
? null
|
||||
: html`<ak-radio-input
|
||||
label=${msg("User type")}
|
||||
required
|
||||
name="type"
|
||||
.value=${this.instance?.type}
|
||||
.options=${[
|
||||
...UserTypeOptions,
|
||||
...(this.instance
|
||||
? [
|
||||
{
|
||||
label: msg("Internal Service account"),
|
||||
value: UserTypeEnum.InternalServiceAccount,
|
||||
disabled: true,
|
||||
description: html`${msg(
|
||||
"Managed by authentik and cannot be assigned manually.",
|
||||
)}`,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
] satisfies RadioOption<UserTypeEnum>[]}
|
||||
></ak-radio-input>`}
|
||||
: this.instance?.type === UserTypeEnum.Agent
|
||||
? html`<ak-radio-input
|
||||
label=${msg("User type")}
|
||||
required
|
||||
name="type"
|
||||
.value=${UserTypeEnum.Agent}
|
||||
.options=${[
|
||||
{
|
||||
label: msg("Agent"),
|
||||
value: UserTypeEnum.Agent,
|
||||
disabled: true,
|
||||
description: html`${msg(
|
||||
"Agent users are managed by their owner and cannot change type.",
|
||||
)}`,
|
||||
},
|
||||
] satisfies RadioOption<UserTypeEnum>[]}
|
||||
></ak-radio-input>`
|
||||
: html`<ak-radio-input
|
||||
label=${msg("User type")}
|
||||
required
|
||||
name="type"
|
||||
.value=${this.instance?.type}
|
||||
.options=${[
|
||||
...UserTypeOptions,
|
||||
...(this.instance
|
||||
? [
|
||||
{
|
||||
label: msg("Internal Service account"),
|
||||
value: UserTypeEnum.InternalServiceAccount,
|
||||
disabled: true,
|
||||
description: html`${msg(
|
||||
"Managed by authentik and cannot be assigned manually.",
|
||||
)}`,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
] satisfies RadioOption<UserTypeEnum>[]}
|
||||
></ak-radio-input>`}
|
||||
<ak-text-input
|
||||
name="email"
|
||||
label=${msg("Email Address")}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import "#admin/users/AgentForm";
|
||||
import "#admin/users/ServiceAccountForm";
|
||||
import "#admin/users/UserForm";
|
||||
import "#components/ak-hidden-text-input";
|
||||
@@ -13,7 +14,12 @@ import { WizardPage } from "#elements/wizard/WizardPage";
|
||||
|
||||
import { UserForm } from "#admin/users/UserForm";
|
||||
|
||||
import { TypeCreate, UserServiceAccountResponse, UserTypeEnum } from "@goauthentik/api";
|
||||
import {
|
||||
TypeCreate,
|
||||
UserAgentResponse,
|
||||
UserServiceAccountResponse,
|
||||
UserTypeEnum,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, html } from "lit";
|
||||
@@ -22,6 +28,9 @@ import { customElement, property, state } from "lit/decorators.js";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
|
||||
const AGENT_FORM_SLOT = `type-ak-user-agent-form-${UserTypeEnum.Agent}` as const;
|
||||
const AGENT_RESULT_SLOT = `${AGENT_FORM_SLOT}-result` as const;
|
||||
|
||||
const SERVICE_ACCOUNT_FORM_SLOT =
|
||||
`type-ak-user-service-account-form-${UserTypeEnum.ServiceAccount}` as const;
|
||||
const SERVICE_ACCOUNT_RESULT_SLOT = `${SERVICE_ACCOUNT_FORM_SLOT}-result` as const;
|
||||
@@ -41,6 +50,13 @@ const DEFAULT_USER_TYPES: TypeCreate[] = [
|
||||
"External consultants or B2C customers without access to enterprise features.",
|
||||
),
|
||||
},
|
||||
{
|
||||
component: "ak-user-agent-form",
|
||||
modelName: UserTypeEnum.Agent,
|
||||
name: msg("Agent"),
|
||||
description: msg("Machine user owned by an internal user, with scoped application access."),
|
||||
requiresEnterprise: true,
|
||||
},
|
||||
{
|
||||
component: "ak-user-service-account-form",
|
||||
modelName: UserTypeEnum.ServiceAccount,
|
||||
@@ -50,6 +66,7 @@ const DEFAULT_USER_TYPES: TypeCreate[] = [
|
||||
];
|
||||
|
||||
export interface UserWizardState {
|
||||
[AGENT_FORM_SLOT]?: UserAgentResponse;
|
||||
[SERVICE_ACCOUNT_FORM_SLOT]?: UserServiceAccountResponse;
|
||||
}
|
||||
|
||||
@@ -110,6 +127,63 @@ export class ServiceAccountResultPage extends WizardPage<UserWizardState> {
|
||||
}
|
||||
}
|
||||
|
||||
@customElement("ak-user-agent-result-page")
|
||||
export class AgentResultPage extends WizardPage<UserWizardState> {
|
||||
public static styles: CSSResult[] = [PFForm, PFFormControl];
|
||||
|
||||
public override headline = msg("Review Credentials");
|
||||
|
||||
@state()
|
||||
protected result: UserAgentResponse | null = null;
|
||||
|
||||
public override activeCallback = async (): Promise<void> => {
|
||||
const result = this.host.state[AGENT_FORM_SLOT];
|
||||
|
||||
if (!result) {
|
||||
throw new TypeError("Expected agent creation result in wizard state.");
|
||||
}
|
||||
|
||||
this.result = result;
|
||||
|
||||
this.host.valid = true;
|
||||
this.host.cancelable = false;
|
||||
};
|
||||
|
||||
public override nextCallback = async (): Promise<boolean> => true;
|
||||
|
||||
protected override render(): SlottedTemplateResult {
|
||||
if (!this.result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { username, token } = this.result;
|
||||
|
||||
return html`<h3 class="pf-c-wizard__main-title">${msg("Review Credentials")}</h3>
|
||||
<h4 class="pf-c-title pf-m-md">
|
||||
${msg(
|
||||
"Use the username and token below to authenticate. The token expires in 24 hours and must be rotated before expiry.",
|
||||
)}
|
||||
</h4>
|
||||
<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-text-input
|
||||
label=${msg("Username")}
|
||||
value=${username}
|
||||
input-hint="code"
|
||||
readonly
|
||||
></ak-text-input>
|
||||
<ak-hidden-text-input
|
||||
label=${msg("Token")}
|
||||
value="${token}"
|
||||
input-hint="code"
|
||||
readonly
|
||||
.help=${msg(
|
||||
"Valid for 24 hours. The agent must rotate the token before it expires.",
|
||||
)}
|
||||
></ak-hidden-text-input>
|
||||
</form>`;
|
||||
}
|
||||
}
|
||||
|
||||
@customElement("ak-user-wizard")
|
||||
export class AKUserWizard extends CreateWizard {
|
||||
/**
|
||||
@@ -128,20 +202,28 @@ export class AKUserWizard extends CreateWizard {
|
||||
|
||||
protected override selectSteps(type: TypeCreate, currentSteps: string[]): string[] {
|
||||
const { modelName } = type;
|
||||
const serviceAccount = modelName === UserTypeEnum.ServiceAccount;
|
||||
|
||||
if (!serviceAccount) {
|
||||
return super.selectSteps(type, currentSteps);
|
||||
if (modelName === UserTypeEnum.Agent) {
|
||||
return [AGENT_FORM_SLOT, AGENT_RESULT_SLOT];
|
||||
}
|
||||
|
||||
return [
|
||||
// ---
|
||||
SERVICE_ACCOUNT_FORM_SLOT,
|
||||
SERVICE_ACCOUNT_RESULT_SLOT,
|
||||
];
|
||||
if (modelName === UserTypeEnum.ServiceAccount) {
|
||||
return [SERVICE_ACCOUNT_FORM_SLOT, SERVICE_ACCOUNT_RESULT_SLOT];
|
||||
}
|
||||
|
||||
return super.selectSteps(type, currentSteps);
|
||||
}
|
||||
|
||||
protected override renderWizardStep(type: TypeCreate): SlottedTemplateResult {
|
||||
if (type.modelName === UserTypeEnum.Agent) {
|
||||
return [
|
||||
super.renderWizardStep(type),
|
||||
html`<ak-user-agent-result-page
|
||||
slot=${AGENT_RESULT_SLOT}
|
||||
></ak-user-agent-result-page>`,
|
||||
];
|
||||
}
|
||||
|
||||
if (type.modelName === UserTypeEnum.ServiceAccount) {
|
||||
return [
|
||||
super.renderWizardStep(type),
|
||||
@@ -155,7 +237,10 @@ export class AKUserWizard extends CreateWizard {
|
||||
}
|
||||
|
||||
protected override assembleFormProps(type: TypeCreate): LitPropertyRecord<UserForm | object> {
|
||||
if (type.modelName === UserTypeEnum.ServiceAccount) {
|
||||
if (
|
||||
type.modelName === UserTypeEnum.Agent ||
|
||||
type.modelName === UserTypeEnum.ServiceAccount
|
||||
) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -171,6 +256,7 @@ export class AKUserWizard extends CreateWizard {
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-user-wizard": AKUserWizard;
|
||||
"ak-user-agent-result-page": AgentResultPage;
|
||||
"ak-user-service-account-result-page": ServiceAccountResultPage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ const _userTypeToLabel = new Map<UserTypeEnum | undefined, string>([
|
||||
[UserTypeEnum.External, msg("External")],
|
||||
[UserTypeEnum.ServiceAccount, msg("Service account")],
|
||||
[UserTypeEnum.InternalServiceAccount, msg("Service account (internal)")],
|
||||
[UserTypeEnum.Agent, msg("Agent")],
|
||||
]);
|
||||
|
||||
export const userTypeToLabel = (type?: UserTypeEnum): string =>
|
||||
|
||||
Reference in New Issue
Block a user