enterprise/providers/rac: connection token management (#8467)
This commit is contained in:
53
authentik/enterprise/providers/rac/api/connection_tokens.py
Normal file
53
authentik/enterprise/providers/rac/api/connection_tokens.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
"""RAC Provider API Views"""
|
||||||
|
|
||||||
|
from django_filters.rest_framework.backends import DjangoFilterBackend
|
||||||
|
from rest_framework import mixins
|
||||||
|
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||||
|
from rest_framework.serializers import ModelSerializer
|
||||||
|
from rest_framework.viewsets import GenericViewSet
|
||||||
|
|
||||||
|
from authentik.api.authorization import OwnerFilter, OwnerPermissions
|
||||||
|
from authentik.core.api.groups import GroupMemberSerializer
|
||||||
|
from authentik.core.api.used_by import UsedByMixin
|
||||||
|
from authentik.enterprise.api import EnterpriseRequiredMixin
|
||||||
|
from authentik.enterprise.providers.rac.api.endpoints import EndpointSerializer
|
||||||
|
from authentik.enterprise.providers.rac.api.providers import RACProviderSerializer
|
||||||
|
from authentik.enterprise.providers.rac.models import ConnectionToken, Endpoint
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionTokenSerializer(EnterpriseRequiredMixin, ModelSerializer):
|
||||||
|
"""ConnectionToken Serializer"""
|
||||||
|
|
||||||
|
provider_obj = RACProviderSerializer(source="provider", read_only=True)
|
||||||
|
endpoint_obj = EndpointSerializer(source="endpoint", read_only=True)
|
||||||
|
user = GroupMemberSerializer(source="session.user", read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Endpoint
|
||||||
|
fields = [
|
||||||
|
"pk",
|
||||||
|
"provider",
|
||||||
|
"provider_obj",
|
||||||
|
"endpoint",
|
||||||
|
"endpoint_obj",
|
||||||
|
"user",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionTokenViewSet(
|
||||||
|
mixins.RetrieveModelMixin,
|
||||||
|
mixins.UpdateModelMixin,
|
||||||
|
mixins.DestroyModelMixin,
|
||||||
|
UsedByMixin,
|
||||||
|
mixins.ListModelMixin,
|
||||||
|
GenericViewSet,
|
||||||
|
):
|
||||||
|
"""ConnectionToken Viewset"""
|
||||||
|
|
||||||
|
queryset = ConnectionToken.objects.all().select_related("session", "endpoint")
|
||||||
|
serializer_class = ConnectionTokenSerializer
|
||||||
|
filterset_fields = ["endpoint", "session__user", "provider"]
|
||||||
|
search_fields = ["endpoint__name", "provider__name"]
|
||||||
|
ordering = ["endpoint__name", "provider__name"]
|
||||||
|
permission_classes = [OwnerPermissions]
|
||||||
|
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
|
@ -16,7 +16,12 @@ class RACProviderSerializer(EnterpriseRequiredMixin, ProviderSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RACProvider
|
model = RACProvider
|
||||||
fields = ProviderSerializer.Meta.fields + ["settings", "outpost_set", "connection_expiry"]
|
fields = ProviderSerializer.Meta.fields + [
|
||||||
|
"settings",
|
||||||
|
"outpost_set",
|
||||||
|
"connection_expiry",
|
||||||
|
"delete_token_on_disconnect",
|
||||||
|
]
|
||||||
extra_kwargs = ProviderSerializer.Meta.extra_kwargs
|
extra_kwargs = ProviderSerializer.Meta.extra_kwargs
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ class RACClientConsumer(AsyncWebsocketConsumer):
|
|||||||
logger: BoundLogger
|
logger: BoundLogger
|
||||||
|
|
||||||
async def connect(self):
|
async def connect(self):
|
||||||
|
self.logger = get_logger()
|
||||||
await self.accept("guacamole")
|
await self.accept("guacamole")
|
||||||
await self.channel_layer.group_add(RAC_CLIENT_GROUP, self.channel_name)
|
await self.channel_layer.group_add(RAC_CLIENT_GROUP, self.channel_name)
|
||||||
await self.channel_layer.group_add(
|
await self.channel_layer.group_add(
|
||||||
@ -64,9 +65,11 @@ class RACClientConsumer(AsyncWebsocketConsumer):
|
|||||||
@database_sync_to_async
|
@database_sync_to_async
|
||||||
def init_outpost_connection(self):
|
def init_outpost_connection(self):
|
||||||
"""Initialize guac connection settings"""
|
"""Initialize guac connection settings"""
|
||||||
self.token = ConnectionToken.filter_not_expired(
|
self.token = (
|
||||||
token=self.scope["url_route"]["kwargs"]["token"]
|
ConnectionToken.filter_not_expired(token=self.scope["url_route"]["kwargs"]["token"])
|
||||||
).first()
|
.select_related("endpoint", "provider", "session", "session__user")
|
||||||
|
.first()
|
||||||
|
)
|
||||||
if not self.token:
|
if not self.token:
|
||||||
raise DenyConnection()
|
raise DenyConnection()
|
||||||
self.provider = self.token.provider
|
self.provider = self.token.provider
|
||||||
@ -107,6 +110,9 @@ class RACClientConsumer(AsyncWebsocketConsumer):
|
|||||||
OUTPOST_GROUP_INSTANCE % {"outpost_pk": str(outpost.pk), "instance": states[0].uid},
|
OUTPOST_GROUP_INSTANCE % {"outpost_pk": str(outpost.pk), "instance": states[0].uid},
|
||||||
msg,
|
msg,
|
||||||
)
|
)
|
||||||
|
if self.provider and self.provider.delete_token_on_disconnect:
|
||||||
|
self.logger.info("Deleting connection token to prevent reconnect", token=self.token)
|
||||||
|
self.token.delete()
|
||||||
|
|
||||||
async def receive(self, text_data=None, bytes_data=None):
|
async def receive(self, text_data=None, bytes_data=None):
|
||||||
"""Mirror data received from client to the dest_channel_id
|
"""Mirror data received from client to the dest_channel_id
|
||||||
|
@ -0,0 +1,181 @@
|
|||||||
|
# Generated by Django 5.0.1 on 2024-02-11 19:04
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import authentik.core.models
|
||||||
|
import authentik.lib.utils.time
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
replaces = [
|
||||||
|
("authentik_providers_rac", "0001_initial"),
|
||||||
|
("authentik_providers_rac", "0002_endpoint_maximum_connections"),
|
||||||
|
("authentik_providers_rac", "0003_alter_connectiontoken_options_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_core", "0032_group_roles"),
|
||||||
|
("authentik_policies", "0011_policybinding_failure_result_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="RACPropertyMapping",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"propertymapping_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="authentik_core.propertymapping",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("static_settings", models.JSONField(default=dict)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "RAC Property Mapping",
|
||||||
|
"verbose_name_plural": "RAC Property Mappings",
|
||||||
|
},
|
||||||
|
bases=("authentik_core.propertymapping",),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="RACProvider",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"provider_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="authentik_core.provider",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("settings", models.JSONField(default=dict)),
|
||||||
|
(
|
||||||
|
"auth_mode",
|
||||||
|
models.TextField(
|
||||||
|
choices=[("static", "Static"), ("prompt", "Prompt")], default="prompt"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"connection_expiry",
|
||||||
|
models.TextField(
|
||||||
|
default="hours=8",
|
||||||
|
help_text="Determines how long a session lasts. Default of 0 means that the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)",
|
||||||
|
validators=[authentik.lib.utils.time.timedelta_string_validator],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"delete_token_on_disconnect",
|
||||||
|
models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text="When set to true, connection tokens will be deleted upon disconnect.",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "RAC Provider",
|
||||||
|
"verbose_name_plural": "RAC Providers",
|
||||||
|
},
|
||||||
|
bases=("authentik_core.provider",),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Endpoint",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"policybindingmodel_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="authentik_policies.policybindingmodel",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("name", models.TextField()),
|
||||||
|
("host", models.TextField()),
|
||||||
|
(
|
||||||
|
"protocol",
|
||||||
|
models.TextField(choices=[("rdp", "Rdp"), ("vnc", "Vnc"), ("ssh", "Ssh")]),
|
||||||
|
),
|
||||||
|
("settings", models.JSONField(default=dict)),
|
||||||
|
(
|
||||||
|
"auth_mode",
|
||||||
|
models.TextField(choices=[("static", "Static"), ("prompt", "Prompt")]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"property_mappings",
|
||||||
|
models.ManyToManyField(
|
||||||
|
blank=True, default=None, to="authentik_core.propertymapping"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"provider",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="authentik_providers_rac.racprovider",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("maximum_connections", models.IntegerField(default=1)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "RAC Endpoint",
|
||||||
|
"verbose_name_plural": "RAC Endpoints",
|
||||||
|
},
|
||||||
|
bases=("authentik_policies.policybindingmodel", models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="ConnectionToken",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"expires",
|
||||||
|
models.DateTimeField(default=authentik.core.models.default_token_duration),
|
||||||
|
),
|
||||||
|
("expiring", models.BooleanField(default=True)),
|
||||||
|
(
|
||||||
|
"connection_token_uuid",
|
||||||
|
models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False),
|
||||||
|
),
|
||||||
|
("token", models.TextField(default=authentik.core.models.default_token_key)),
|
||||||
|
("settings", models.JSONField(default=dict)),
|
||||||
|
(
|
||||||
|
"endpoint",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="authentik_providers_rac.endpoint",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"provider",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="authentik_providers_rac.racprovider",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"session",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="authentik_core.authenticatedsession",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
"verbose_name": "RAC Connection token",
|
||||||
|
"verbose_name_plural": "RAC Connection tokens",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 5.0.1 on 2024-02-11 19:04
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_providers_rac", "0002_endpoint_maximum_connections"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="connectiontoken",
|
||||||
|
options={
|
||||||
|
"verbose_name": "RAC Connection token",
|
||||||
|
"verbose_name_plural": "RAC Connection tokens",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="racprovider",
|
||||||
|
name="delete_token_on_disconnect",
|
||||||
|
field=models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text="When set to true, connection tokens will be deleted upon disconnect.",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -52,6 +52,10 @@ class RACProvider(Provider):
|
|||||||
"(Format: hours=-1;minutes=-2;seconds=-3)"
|
"(Format: hours=-1;minutes=-2;seconds=-3)"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
delete_token_on_disconnect = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text=_("When set to true, connection tokens will be deleted upon disconnect."),
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def launch_url(self) -> Optional[str]:
|
def launch_url(self) -> Optional[str]:
|
||||||
@ -195,3 +199,13 @@ class ConnectionToken(ExpiringModel):
|
|||||||
continue
|
continue
|
||||||
settings[key] = str(value)
|
settings[key] = str(value)
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
f"RAC Connection token {self.session.user} to "
|
||||||
|
f"{self.endpoint.provider.name}/{self.endpoint.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("RAC Connection token")
|
||||||
|
verbose_name_plural = _("RAC Connection tokens")
|
||||||
|
@ -45,8 +45,8 @@ def pre_delete_connection_token_disconnect(sender, instance: ConnectionToken, **
|
|||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Endpoint)
|
@receiver(post_save, sender=Endpoint)
|
||||||
def post_save_application(sender: type[Model], instance, created: bool, **_):
|
def post_save_endpoint(sender: type[Model], instance, created: bool, **_):
|
||||||
"""Clear user's application cache upon application creation"""
|
"""Clear user's endpoint cache upon endpoint creation"""
|
||||||
if not created: # pragma: no cover
|
if not created: # pragma: no cover
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ class TestEndpointsAPI(APITestCase):
|
|||||||
"authorization_flow": None,
|
"authorization_flow": None,
|
||||||
"property_mappings": [],
|
"property_mappings": [],
|
||||||
"connection_expiry": "hours=8",
|
"connection_expiry": "hours=8",
|
||||||
|
"delete_token_on_disconnect": False,
|
||||||
"component": "ak-provider-rac-form",
|
"component": "ak-provider-rac-form",
|
||||||
"assigned_application_slug": self.app.slug,
|
"assigned_application_slug": self.app.slug,
|
||||||
"assigned_application_name": self.app.name,
|
"assigned_application_name": self.app.name,
|
||||||
@ -124,6 +125,7 @@ class TestEndpointsAPI(APITestCase):
|
|||||||
"assigned_application_slug": self.app.slug,
|
"assigned_application_slug": self.app.slug,
|
||||||
"assigned_application_name": self.app.name,
|
"assigned_application_name": self.app.name,
|
||||||
"connection_expiry": "hours=8",
|
"connection_expiry": "hours=8",
|
||||||
|
"delete_token_on_disconnect": False,
|
||||||
"verbose_name": "RAC Provider",
|
"verbose_name": "RAC Provider",
|
||||||
"verbose_name_plural": "RAC Providers",
|
"verbose_name_plural": "RAC Providers",
|
||||||
"meta_model_name": "authentik_providers_rac.racprovider",
|
"meta_model_name": "authentik_providers_rac.racprovider",
|
||||||
@ -152,6 +154,7 @@ class TestEndpointsAPI(APITestCase):
|
|||||||
"assigned_application_slug": self.app.slug,
|
"assigned_application_slug": self.app.slug,
|
||||||
"assigned_application_name": self.app.name,
|
"assigned_application_name": self.app.name,
|
||||||
"connection_expiry": "hours=8",
|
"connection_expiry": "hours=8",
|
||||||
|
"delete_token_on_disconnect": False,
|
||||||
"verbose_name": "RAC Provider",
|
"verbose_name": "RAC Provider",
|
||||||
"verbose_name_plural": "RAC Providers",
|
"verbose_name_plural": "RAC Providers",
|
||||||
"meta_model_name": "authentik_providers_rac.racprovider",
|
"meta_model_name": "authentik_providers_rac.racprovider",
|
||||||
|
@ -6,6 +6,7 @@ from django.urls import path
|
|||||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||||
|
|
||||||
from authentik.core.channels import TokenOutpostMiddleware
|
from authentik.core.channels import TokenOutpostMiddleware
|
||||||
|
from authentik.enterprise.providers.rac.api.connection_tokens import ConnectionTokenViewSet
|
||||||
from authentik.enterprise.providers.rac.api.endpoints import EndpointViewSet
|
from authentik.enterprise.providers.rac.api.endpoints import EndpointViewSet
|
||||||
from authentik.enterprise.providers.rac.api.property_mappings import RACPropertyMappingViewSet
|
from authentik.enterprise.providers.rac.api.property_mappings import RACPropertyMappingViewSet
|
||||||
from authentik.enterprise.providers.rac.api.providers import RACProviderViewSet
|
from authentik.enterprise.providers.rac.api.providers import RACProviderViewSet
|
||||||
@ -45,4 +46,5 @@ api_urlpatterns = [
|
|||||||
("providers/rac", RACProviderViewSet),
|
("providers/rac", RACProviderViewSet),
|
||||||
("propertymappings/rac", RACPropertyMappingViewSet),
|
("propertymappings/rac", RACPropertyMappingViewSet),
|
||||||
("rac/endpoints", EndpointViewSet),
|
("rac/endpoints", EndpointViewSet),
|
||||||
|
("rac/connection_tokens", ConnectionTokenViewSet),
|
||||||
]
|
]
|
||||||
|
@ -23,18 +23,15 @@ class Migration(migrations.Migration):
|
|||||||
model_name="systemtask",
|
model_name="systemtask",
|
||||||
name="duration",
|
name="duration",
|
||||||
field=models.FloatField(default=0),
|
field=models.FloatField(default=0),
|
||||||
preserve_default=False,
|
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="systemtask",
|
model_name="systemtask",
|
||||||
name="finish_timestamp",
|
name="finish_timestamp",
|
||||||
field=models.DateTimeField(default=django.utils.timezone.now),
|
field=models.DateTimeField(default=django.utils.timezone.now),
|
||||||
preserve_default=False,
|
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="systemtask",
|
model_name="systemtask",
|
||||||
name="start_timestamp",
|
name="start_timestamp",
|
||||||
field=models.DateTimeField(default=django.utils.timezone.now),
|
field=models.DateTimeField(default=django.utils.timezone.now),
|
||||||
preserve_default=False,
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -620,9 +620,9 @@ class SystemTask(SerializerModel, ExpiringModel):
|
|||||||
name = models.TextField()
|
name = models.TextField()
|
||||||
uid = models.TextField(null=True)
|
uid = models.TextField(null=True)
|
||||||
|
|
||||||
start_timestamp = models.DateTimeField()
|
start_timestamp = models.DateTimeField(default=now)
|
||||||
finish_timestamp = models.DateTimeField()
|
finish_timestamp = models.DateTimeField(default=now)
|
||||||
duration = models.FloatField()
|
duration = models.FloatField(default=0)
|
||||||
|
|
||||||
status = models.TextField(choices=TaskStatus.choices)
|
status = models.TextField(choices=TaskStatus.choices)
|
||||||
|
|
||||||
|
@ -7924,6 +7924,11 @@
|
|||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"title": "Connection expiry",
|
"title": "Connection expiry",
|
||||||
"description": "Determines how long a session lasts. Default of 0 means that the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
"description": "Determines how long a session lasts. Default of 0 means that the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
||||||
|
},
|
||||||
|
"delete_token_on_disconnect": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Delete token on disconnect",
|
||||||
|
"description": "When set to true, connection tokens will be deleted upon disconnect."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
@ -23,6 +23,8 @@ entries:
|
|||||||
enable-full-window-drag: "true"
|
enable-full-window-drag: "true"
|
||||||
enable-desktop-composition: "true"
|
enable-desktop-composition: "true"
|
||||||
enable-menu-animations: "true"
|
enable-menu-animations: "true"
|
||||||
|
enable-wallpaper: "true"
|
||||||
|
enable-font-smoothing: "true"
|
||||||
- identifiers:
|
- identifiers:
|
||||||
managed: goauthentik.io/providers/rac/ssh-default
|
managed: goauthentik.io/providers/rac/ssh-default
|
||||||
model: authentik_providers_rac.racpropertymapping
|
model: authentik_providers_rac.racpropertymapping
|
||||||
|
315
schema.yml
315
schema.yml
@ -17818,6 +17818,252 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/GenericError'
|
$ref: '#/components/schemas/GenericError'
|
||||||
description: ''
|
description: ''
|
||||||
|
/rac/connection_tokens/:
|
||||||
|
get:
|
||||||
|
operationId: rac_connection_tokens_list
|
||||||
|
description: ConnectionToken Viewset
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: endpoint
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
- name: ordering
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
description: Which field to use when ordering the results.
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: page
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
description: A page number within the paginated result set.
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
- name: page_size
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
description: Number of results to return per page.
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
- in: query
|
||||||
|
name: provider
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
- name: search
|
||||||
|
required: false
|
||||||
|
in: query
|
||||||
|
description: A search term.
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: session__user
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
tags:
|
||||||
|
- rac
|
||||||
|
security:
|
||||||
|
- authentik: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/PaginatedConnectionTokenList'
|
||||||
|
description: ''
|
||||||
|
'400':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ValidationError'
|
||||||
|
description: ''
|
||||||
|
'403':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GenericError'
|
||||||
|
description: ''
|
||||||
|
/rac/connection_tokens/{connection_token_uuid}/:
|
||||||
|
get:
|
||||||
|
operationId: rac_connection_tokens_retrieve
|
||||||
|
description: ConnectionToken Viewset
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: connection_token_uuid
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: A UUID string identifying this connection token.
|
||||||
|
required: true
|
||||||
|
tags:
|
||||||
|
- rac
|
||||||
|
security:
|
||||||
|
- authentik: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ConnectionToken'
|
||||||
|
description: ''
|
||||||
|
'400':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ValidationError'
|
||||||
|
description: ''
|
||||||
|
'403':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GenericError'
|
||||||
|
description: ''
|
||||||
|
put:
|
||||||
|
operationId: rac_connection_tokens_update
|
||||||
|
description: ConnectionToken Viewset
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: connection_token_uuid
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: A UUID string identifying this connection token.
|
||||||
|
required: true
|
||||||
|
tags:
|
||||||
|
- rac
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ConnectionTokenRequest'
|
||||||
|
required: true
|
||||||
|
security:
|
||||||
|
- authentik: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ConnectionToken'
|
||||||
|
description: ''
|
||||||
|
'400':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ValidationError'
|
||||||
|
description: ''
|
||||||
|
'403':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GenericError'
|
||||||
|
description: ''
|
||||||
|
patch:
|
||||||
|
operationId: rac_connection_tokens_partial_update
|
||||||
|
description: ConnectionToken Viewset
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: connection_token_uuid
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: A UUID string identifying this connection token.
|
||||||
|
required: true
|
||||||
|
tags:
|
||||||
|
- rac
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/PatchedConnectionTokenRequest'
|
||||||
|
security:
|
||||||
|
- authentik: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ConnectionToken'
|
||||||
|
description: ''
|
||||||
|
'400':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ValidationError'
|
||||||
|
description: ''
|
||||||
|
'403':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GenericError'
|
||||||
|
description: ''
|
||||||
|
delete:
|
||||||
|
operationId: rac_connection_tokens_destroy
|
||||||
|
description: ConnectionToken Viewset
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: connection_token_uuid
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: A UUID string identifying this connection token.
|
||||||
|
required: true
|
||||||
|
tags:
|
||||||
|
- rac
|
||||||
|
security:
|
||||||
|
- authentik: []
|
||||||
|
responses:
|
||||||
|
'204':
|
||||||
|
description: No response body
|
||||||
|
'400':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ValidationError'
|
||||||
|
description: ''
|
||||||
|
'403':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GenericError'
|
||||||
|
description: ''
|
||||||
|
/rac/connection_tokens/{connection_token_uuid}/used_by/:
|
||||||
|
get:
|
||||||
|
operationId: rac_connection_tokens_used_by_list
|
||||||
|
description: Get a list of all objects that use this object
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: connection_token_uuid
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: A UUID string identifying this connection token.
|
||||||
|
required: true
|
||||||
|
tags:
|
||||||
|
- rac
|
||||||
|
security:
|
||||||
|
- authentik: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/UsedBy'
|
||||||
|
description: ''
|
||||||
|
'400':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ValidationError'
|
||||||
|
description: ''
|
||||||
|
'403':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GenericError'
|
||||||
|
description: ''
|
||||||
/rac/endpoints/:
|
/rac/endpoints/:
|
||||||
get:
|
get:
|
||||||
operationId: rac_endpoints_list
|
operationId: rac_endpoints_list
|
||||||
@ -31248,6 +31494,48 @@ components:
|
|||||||
- cache_timeout_reputation
|
- cache_timeout_reputation
|
||||||
- capabilities
|
- capabilities
|
||||||
- error_reporting
|
- error_reporting
|
||||||
|
ConnectionToken:
|
||||||
|
type: object
|
||||||
|
description: ConnectionToken Serializer
|
||||||
|
properties:
|
||||||
|
pk:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
readOnly: true
|
||||||
|
title: Pbm uuid
|
||||||
|
provider:
|
||||||
|
type: integer
|
||||||
|
provider_obj:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/RACProvider'
|
||||||
|
readOnly: true
|
||||||
|
endpoint:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
readOnly: true
|
||||||
|
endpoint_obj:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/Endpoint'
|
||||||
|
readOnly: true
|
||||||
|
user:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/GroupMember'
|
||||||
|
readOnly: true
|
||||||
|
required:
|
||||||
|
- endpoint
|
||||||
|
- endpoint_obj
|
||||||
|
- pk
|
||||||
|
- provider
|
||||||
|
- provider_obj
|
||||||
|
- user
|
||||||
|
ConnectionTokenRequest:
|
||||||
|
type: object
|
||||||
|
description: ConnectionToken Serializer
|
||||||
|
properties:
|
||||||
|
provider:
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- provider
|
||||||
ConsentChallenge:
|
ConsentChallenge:
|
||||||
type: object
|
type: object
|
||||||
description: Challenge info for consent screens
|
description: Challenge info for consent screens
|
||||||
@ -36268,6 +36556,18 @@ components:
|
|||||||
required:
|
required:
|
||||||
- pagination
|
- pagination
|
||||||
- results
|
- results
|
||||||
|
PaginatedConnectionTokenList:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
pagination:
|
||||||
|
$ref: '#/components/schemas/Pagination'
|
||||||
|
results:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/ConnectionToken'
|
||||||
|
required:
|
||||||
|
- pagination
|
||||||
|
- results
|
||||||
PaginatedConsentStageList:
|
PaginatedConsentStageList:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -37980,6 +38280,12 @@ components:
|
|||||||
writeOnly: true
|
writeOnly: true
|
||||||
description: Optional Private Key. If this is set, you can use this keypair
|
description: Optional Private Key. If this is set, you can use this keypair
|
||||||
for encryption.
|
for encryption.
|
||||||
|
PatchedConnectionTokenRequest:
|
||||||
|
type: object
|
||||||
|
description: ConnectionToken Serializer
|
||||||
|
properties:
|
||||||
|
provider:
|
||||||
|
type: integer
|
||||||
PatchedConsentStageRequest:
|
PatchedConsentStageRequest:
|
||||||
type: object
|
type: object
|
||||||
description: ConsentStage Serializer
|
description: ConsentStage Serializer
|
||||||
@ -39542,6 +39848,9 @@ components:
|
|||||||
minLength: 1
|
minLength: 1
|
||||||
description: 'Determines how long a session lasts. Default of 0 means that
|
description: 'Determines how long a session lasts. Default of 0 means that
|
||||||
the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)'
|
the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)'
|
||||||
|
delete_token_on_disconnect:
|
||||||
|
type: boolean
|
||||||
|
description: When set to true, connection tokens will be deleted upon disconnect.
|
||||||
PatchedRadiusProviderRequest:
|
PatchedRadiusProviderRequest:
|
||||||
type: object
|
type: object
|
||||||
description: RadiusProvider Serializer
|
description: RadiusProvider Serializer
|
||||||
@ -41615,6 +41924,9 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
description: 'Determines how long a session lasts. Default of 0 means that
|
description: 'Determines how long a session lasts. Default of 0 means that
|
||||||
the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)'
|
the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)'
|
||||||
|
delete_token_on_disconnect:
|
||||||
|
type: boolean
|
||||||
|
description: When set to true, connection tokens will be deleted upon disconnect.
|
||||||
required:
|
required:
|
||||||
- assigned_application_name
|
- assigned_application_name
|
||||||
- assigned_application_slug
|
- assigned_application_slug
|
||||||
@ -41656,6 +41968,9 @@ components:
|
|||||||
minLength: 1
|
minLength: 1
|
||||||
description: 'Determines how long a session lasts. Default of 0 means that
|
description: 'Determines how long a session lasts. Default of 0 means that
|
||||||
the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)'
|
the sessions lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)'
|
||||||
|
delete_token_on_disconnect:
|
||||||
|
type: boolean
|
||||||
|
description: When set to true, connection tokens will be deleted upon disconnect.
|
||||||
required:
|
required:
|
||||||
- authorization_flow
|
- authorization_flow
|
||||||
- name
|
- name
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { EVENT_REFRESH_ENTERPRISE } from "@goauthentik/app/common/constants";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import "@goauthentik/elements/CodeMirror";
|
import "@goauthentik/elements/CodeMirror";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
@ -34,14 +35,19 @@ export class EnterpriseLicenseForm extends ModelForm<License, string> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async send(data: License): Promise<License> {
|
async send(data: License): Promise<License> {
|
||||||
return this.instance
|
return (
|
||||||
? new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicensePartialUpdate({
|
this.instance
|
||||||
licenseUuid: this.instance.licenseUuid || "",
|
? new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicensePartialUpdate({
|
||||||
patchedLicenseRequest: data,
|
licenseUuid: this.instance.licenseUuid || "",
|
||||||
})
|
patchedLicenseRequest: data,
|
||||||
: new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseCreate({
|
})
|
||||||
licenseRequest: data,
|
: new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseCreate({
|
||||||
});
|
licenseRequest: data,
|
||||||
|
})
|
||||||
|
).then((data) => {
|
||||||
|
window.dispatchEvent(new CustomEvent(EVENT_REFRESH_ENTERPRISE));
|
||||||
|
return data;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderForm(): TemplateResult {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { first } from "@goauthentik/app/common/utils";
|
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { docLink } from "@goauthentik/common/global";
|
import { docLink } from "@goauthentik/common/global";
|
||||||
import "@goauthentik/elements/CodeMirror";
|
import "@goauthentik/elements/CodeMirror";
|
||||||
@ -6,6 +5,8 @@ import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
|
|||||||
import "@goauthentik/elements/forms/FormGroup";
|
import "@goauthentik/elements/forms/FormGroup";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
||||||
|
import "@goauthentik/elements/forms/Radio";
|
||||||
|
import type { RadioOption } from "@goauthentik/elements/forms/Radio";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { TemplateResult, html } from "lit";
|
import { TemplateResult, html } from "lit";
|
||||||
@ -14,6 +15,23 @@ import { ifDefined } from "lit/directives/if-defined.js";
|
|||||||
|
|
||||||
import { PropertymappingsApi, RACPropertyMapping } from "@goauthentik/api";
|
import { PropertymappingsApi, RACPropertyMapping } from "@goauthentik/api";
|
||||||
|
|
||||||
|
export const staticSettingOptions: RadioOption<string | undefined>[] = [
|
||||||
|
{
|
||||||
|
label: msg("Unconfigured"),
|
||||||
|
value: undefined,
|
||||||
|
default: true,
|
||||||
|
description: html`${msg("This option will not be changed by this mapping.")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: msg("Enabled"),
|
||||||
|
value: "true",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: msg("Disabled"),
|
||||||
|
value: "false",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
@customElement("ak-property-mapping-rac-form")
|
@customElement("ak-property-mapping-rac-form")
|
||||||
export class PropertyMappingLDAPForm extends ModelForm<RACPropertyMapping, string> {
|
export class PropertyMappingLDAPForm extends ModelForm<RACPropertyMapping, string> {
|
||||||
loadInstance(pk: string): Promise<RACPropertyMapping> {
|
loadInstance(pk: string): Promise<RACPropertyMapping> {
|
||||||
@ -58,7 +76,6 @@ export class PropertyMappingLDAPForm extends ModelForm<RACPropertyMapping, strin
|
|||||||
<div slot="body" class="pf-c-form">
|
<div slot="body" class="pf-c-form">
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
label=${msg("Username")}
|
label=${msg("Username")}
|
||||||
?required=${true}
|
|
||||||
name="staticSettings.username"
|
name="staticSettings.username"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@ -70,7 +87,6 @@ export class PropertyMappingLDAPForm extends ModelForm<RACPropertyMapping, strin
|
|||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
label=${msg("Password")}
|
label=${msg("Password")}
|
||||||
?required=${true}
|
|
||||||
name="staticSettings.password"
|
name="staticSettings.password"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@ -85,81 +101,45 @@ export class PropertyMappingLDAPForm extends ModelForm<RACPropertyMapping, strin
|
|||||||
<ak-form-group>
|
<ak-form-group>
|
||||||
<span slot="header"> ${msg("RDP settings")} </span>
|
<span slot="header"> ${msg("RDP settings")} </span>
|
||||||
<div slot="body" class="pf-c-form">
|
<div slot="body" class="pf-c-form">
|
||||||
<ak-form-element-horizontal name="staticSettings.ignore-cert">
|
<ak-form-element-horizontal
|
||||||
<label class="pf-c-switch">
|
label=${msg("Ignore server certificate")}
|
||||||
<input
|
name="staticSettings.ignore-cert"
|
||||||
class="pf-c-switch__input"
|
>
|
||||||
type="checkbox"
|
<ak-radio
|
||||||
?checked=${first(
|
.options=${staticSettingOptions}
|
||||||
this.instance?.staticSettings["ignore-cert"],
|
.value=${this.instance?.staticSettings["ignore-cert"]}
|
||||||
false,
|
>
|
||||||
)}
|
</ak-radio>
|
||||||
/>
|
|
||||||
<span class="pf-c-switch__toggle">
|
|
||||||
<span class="pf-c-switch__toggle-icon">
|
|
||||||
<i class="fas fa-check" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span class="pf-c-switch__label"
|
|
||||||
>${msg("Ignore server certificate")}</span
|
|
||||||
>
|
|
||||||
</label>
|
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal name="staticSettings.enable-wallpaper">
|
<ak-form-element-horizontal
|
||||||
<label class="pf-c-switch">
|
label=${msg("Enable wallpaper")}
|
||||||
<input
|
name="staticSettings.enable-wallpaper"
|
||||||
class="pf-c-switch__input"
|
>
|
||||||
type="checkbox"
|
<ak-radio
|
||||||
?checked=${first(
|
.options=${staticSettingOptions}
|
||||||
this.instance?.staticSettings["enable-wallpaper"],
|
.value=${this.instance?.staticSettings["enable-wallpaper"]}
|
||||||
false,
|
>
|
||||||
)}
|
</ak-radio>
|
||||||
/>
|
|
||||||
<span class="pf-c-switch__toggle">
|
|
||||||
<span class="pf-c-switch__toggle-icon">
|
|
||||||
<i class="fas fa-check" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span class="pf-c-switch__label">${msg("Enable wallpaper")}</span>
|
|
||||||
</label>
|
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal name="staticSettings.enable-font-smoothing">
|
<ak-form-element-horizontal
|
||||||
<label class="pf-c-switch">
|
label=${msg("Enable font-smoothing")}
|
||||||
<input
|
name="staticSettings.enable-font-smoothing"
|
||||||
class="pf-c-switch__input"
|
>
|
||||||
type="checkbox"
|
<ak-radio
|
||||||
?checked=${first(
|
.options=${staticSettingOptions}
|
||||||
this.instance?.staticSettings["enable-font-smoothing"],
|
.value=${this.instance?.staticSettings["enable-font-smoothing"]}
|
||||||
false,
|
>
|
||||||
)}
|
</ak-radio>
|
||||||
/>
|
|
||||||
<span class="pf-c-switch__toggle">
|
|
||||||
<span class="pf-c-switch__toggle-icon">
|
|
||||||
<i class="fas fa-check" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span class="pf-c-switch__label">${msg("Enable font-smoothing")}</span>
|
|
||||||
</label>
|
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal name="staticSettings.enable-full-window-drag">
|
<ak-form-element-horizontal
|
||||||
<label class="pf-c-switch">
|
label=${msg("Enable full window dragging")}
|
||||||
<input
|
name="staticSettings.enable-full-window-drag"
|
||||||
class="pf-c-switch__input"
|
>
|
||||||
type="checkbox"
|
<ak-radio
|
||||||
?checked=${first(
|
.options=${staticSettingOptions}
|
||||||
this.instance?.staticSettings["enable-full-window-drag"],
|
.value=${this.instance?.staticSettings["enable-full-window-drag"]}
|
||||||
false,
|
>
|
||||||
)}
|
</ak-radio>
|
||||||
/>
|
|
||||||
<span class="pf-c-switch__toggle">
|
|
||||||
<span class="pf-c-switch__toggle-icon">
|
|
||||||
<i class="fas fa-check" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span class="pf-c-switch__label"
|
|
||||||
>${msg("Enable full window dragging")}</span
|
|
||||||
>
|
|
||||||
</label>
|
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
</div>
|
</div>
|
||||||
</ak-form-group>
|
</ak-form-group>
|
||||||
|
98
web/src/admin/providers/rac/ConnectionTokenList.ts
Normal file
98
web/src/admin/providers/rac/ConnectionTokenList.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
|
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||||
|
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||||
|
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||||
|
import "@goauthentik/elements/forms/ModalForm";
|
||||||
|
import { PaginatedResponse, Table } from "@goauthentik/elements/table/Table";
|
||||||
|
import { TableColumn } from "@goauthentik/elements/table/Table";
|
||||||
|
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||||
|
|
||||||
|
import { msg } from "@lit/localize";
|
||||||
|
import { CSSResult, TemplateResult, html } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators.js";
|
||||||
|
|
||||||
|
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
|
||||||
|
|
||||||
|
import { ConnectionToken, Endpoint, RACProvider, RacApi } from "@goauthentik/api";
|
||||||
|
|
||||||
|
@customElement("ak-rac-connection-token-list")
|
||||||
|
export class ConnectionTokenListPage extends Table<ConnectionToken> {
|
||||||
|
checkbox = true;
|
||||||
|
clearOnRefresh = true;
|
||||||
|
|
||||||
|
searchEnabled(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property()
|
||||||
|
order = "name";
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
provider?: RACProvider;
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
userId?: number;
|
||||||
|
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return super.styles.concat(PFDescriptionList);
|
||||||
|
}
|
||||||
|
|
||||||
|
async apiEndpoint(page: number): Promise<PaginatedResponse<ConnectionToken>> {
|
||||||
|
return new RacApi(DEFAULT_CONFIG).racConnectionTokensList({
|
||||||
|
ordering: this.order,
|
||||||
|
page: page,
|
||||||
|
pageSize: (await uiConfig()).pagination.perPage,
|
||||||
|
search: this.search || "",
|
||||||
|
provider: this.provider?.pk,
|
||||||
|
sessionUser: this.userId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderToolbarSelected(): TemplateResult {
|
||||||
|
const disabled = this.selectedElements.length < 1;
|
||||||
|
return html`<ak-forms-delete-bulk
|
||||||
|
objectLabel=${msg("Connection Token(s)")}
|
||||||
|
.objects=${this.selectedElements}
|
||||||
|
.metadata=${(item: Endpoint) => {
|
||||||
|
return [
|
||||||
|
{ key: msg("Name"), value: item.name },
|
||||||
|
{ key: msg("Host"), value: item.host },
|
||||||
|
];
|
||||||
|
}}
|
||||||
|
.usedBy=${(item: Endpoint) => {
|
||||||
|
return new RacApi(DEFAULT_CONFIG).racConnectionTokensUsedByList({
|
||||||
|
connectionTokenUuid: item.pk,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
.delete=${(item: Endpoint) => {
|
||||||
|
return new RacApi(DEFAULT_CONFIG).racConnectionTokensDestroy({
|
||||||
|
connectionTokenUuid: item.pk,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
|
||||||
|
${msg("Delete")}
|
||||||
|
</button>
|
||||||
|
</ak-forms-delete-bulk>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
columns(): TableColumn[] {
|
||||||
|
if (this.provider) {
|
||||||
|
return [
|
||||||
|
new TableColumn(msg("Endpoint"), "endpoint__name"),
|
||||||
|
new TableColumn(msg("User"), "session__user"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
new TableColumn(msg("Provider"), "provider__name"),
|
||||||
|
new TableColumn(msg("Endpoint"), "endpoint__name"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
row(item: ConnectionToken): TemplateResult[] {
|
||||||
|
if (this.provider) {
|
||||||
|
return [html`${item.endpointObj.name}`, html`${item.user.username}`];
|
||||||
|
}
|
||||||
|
return [html`${item.providerObj.name}`, html`${item.endpointObj.name}`];
|
||||||
|
}
|
||||||
|
}
|
@ -107,6 +107,28 @@ export class RACProviderFormPage extends ModelForm<RACProvider, number> {
|
|||||||
</p>
|
</p>
|
||||||
<ak-utils-time-delta-help></ak-utils-time-delta-help>
|
<ak-utils-time-delta-help></ak-utils-time-delta-help>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
|
<ak-form-element-horizontal name="deleteTokenOnDisconnect">
|
||||||
|
<label class="pf-c-switch">
|
||||||
|
<input
|
||||||
|
class="pf-c-switch__input"
|
||||||
|
type="checkbox"
|
||||||
|
?checked=${first(this.instance?.deleteTokenOnDisconnect, false)}
|
||||||
|
/>
|
||||||
|
<span class="pf-c-switch__toggle">
|
||||||
|
<span class="pf-c-switch__toggle-icon">
|
||||||
|
<i class="fas fa-check" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span class="pf-c-switch__label"
|
||||||
|
>${msg("Delete authorization on disconnect")}</span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<p class="pf-c-form__helper-text">
|
||||||
|
${msg(
|
||||||
|
"When enabled, connection authorizations will be deleted when a client disconnects. This will force clients with flaky internet connections to re-authorize the endpoint.",
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
|
|
||||||
<ak-form-group .expanded=${true}>
|
<ak-form-group .expanded=${true}>
|
||||||
<span slot="header"> ${msg("Protocol settings")} </span>
|
<span slot="header"> ${msg("Protocol settings")} </span>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import "@goauthentik/admin/providers/RelatedApplicationButton";
|
import "@goauthentik/admin/providers/RelatedApplicationButton";
|
||||||
|
import "@goauthentik/admin/providers/rac/ConnectionTokenList";
|
||||||
import "@goauthentik/admin/providers/rac/EndpointForm";
|
import "@goauthentik/admin/providers/rac/EndpointForm";
|
||||||
import "@goauthentik/admin/providers/rac/EndpointList";
|
import "@goauthentik/admin/providers/rac/EndpointList";
|
||||||
import "@goauthentik/admin/providers/rac/RACProviderForm";
|
import "@goauthentik/admin/providers/rac/RACProviderForm";
|
||||||
@ -86,6 +87,15 @@ export class RACProviderViewPage extends AKElement {
|
|||||||
<section slot="page-overview" data-tab-title="${msg("Overview")}">
|
<section slot="page-overview" data-tab-title="${msg("Overview")}">
|
||||||
${this.renderTabOverview()}
|
${this.renderTabOverview()}
|
||||||
</section>
|
</section>
|
||||||
|
<section slot="page-connections" data-tab-title="${msg("Connections")}">
|
||||||
|
<div class="pf-c-card">
|
||||||
|
<div class="pf-c-card__body">
|
||||||
|
<ak-rac-connection-token-list
|
||||||
|
.provider=${this.provider}
|
||||||
|
></ak-rac-connection-token-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
<section
|
<section
|
||||||
slot="page-changelog"
|
slot="page-changelog"
|
||||||
data-tab-title="${msg("Changelog")}"
|
data-tab-title="${msg("Changelog")}"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import "@goauthentik/admin/groups/RelatedGroupList";
|
import "@goauthentik/admin/groups/RelatedGroupList";
|
||||||
|
import "@goauthentik/admin/providers/rac/ConnectionTokenList";
|
||||||
import "@goauthentik/admin/users/UserActiveForm";
|
import "@goauthentik/admin/users/UserActiveForm";
|
||||||
import "@goauthentik/admin/users/UserApplicationTable";
|
import "@goauthentik/admin/users/UserApplicationTable";
|
||||||
import "@goauthentik/admin/users/UserChart";
|
import "@goauthentik/admin/users/UserChart";
|
||||||
@ -329,6 +330,16 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) {
|
|||||||
</ak-user-settings-source>
|
</ak-user-settings-source>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<section
|
||||||
|
slot="page-rac-connection-tokens"
|
||||||
|
data-tab-title="${msg("RAC Connections")}"
|
||||||
|
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||||
|
>
|
||||||
|
<div class="pf-c-card">
|
||||||
|
<ak-rac-connection-token-list userId=${user.pk}>
|
||||||
|
</ak-rac-connection-token-list>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</ak-tabs>
|
</ak-tabs>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ export const EVENT_LOCALE_REQUEST = "ak-locale-request";
|
|||||||
export const EVENT_REQUEST_POST = "ak-request-post";
|
export const EVENT_REQUEST_POST = "ak-request-post";
|
||||||
export const EVENT_MESSAGE = "ak-message";
|
export const EVENT_MESSAGE = "ak-message";
|
||||||
export const EVENT_THEME_CHANGE = "ak-theme-change";
|
export const EVENT_THEME_CHANGE = "ak-theme-change";
|
||||||
|
export const EVENT_REFRESH_ENTERPRISE = "ak-refresh-enterprise";
|
||||||
|
|
||||||
export const WS_MSG_TYPE_MESSAGE = "message";
|
export const WS_MSG_TYPE_MESSAGE = "message";
|
||||||
export const WS_MSG_TYPE_REFRESH = "refresh";
|
export const WS_MSG_TYPE_REFRESH = "refresh";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { EVENT_REFRESH_ENTERPRISE } from "@goauthentik/app/common/constants";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { brand, config } from "@goauthentik/common/api/config";
|
import { brand, config } from "@goauthentik/common/api/config";
|
||||||
import { UIConfig, uiConfig } from "@goauthentik/common/ui/config";
|
import { UIConfig, uiConfig } from "@goauthentik/common/ui/config";
|
||||||
@ -109,8 +110,16 @@ export class EnterpriseAwareInterface extends Interface {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseSummaryRetrieve().then((enterprise) => {
|
const refreshStatus = () => {
|
||||||
this.licenseSummary = enterprise;
|
new EnterpriseApi(DEFAULT_CONFIG)
|
||||||
|
.enterpriseLicenseSummaryRetrieve()
|
||||||
|
.then((enterprise) => {
|
||||||
|
this.licenseSummary = enterprise;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
refreshStatus();
|
||||||
|
window.addEventListener(EVENT_REFRESH_ENTERPRISE, () => {
|
||||||
|
refreshStatus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import { randomId } from "../utils/randomId";
|
|||||||
export interface RadioOption<T> {
|
export interface RadioOption<T> {
|
||||||
label: string;
|
label: string;
|
||||||
description?: TemplateResult;
|
description?: TemplateResult;
|
||||||
default: boolean;
|
default?: boolean;
|
||||||
value: T;
|
value: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user