Compare commits

..

13 Commits

Author SHA1 Message Date
c1c55a6005 lifecycle: fix permission error with local docker
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-22 20:47:05 +02:00
2d5c45543b release: 2021.5.4 2021-05-22 20:15:23 +02:00
9d476a42d1 web: don't set X-Forwarded-Proto when no request TLS Options are set
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-22 19:46:40 +02:00
2c816e6162 providers/proxy: don't use https to communicate with outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-22 18:56:38 +02:00
dbcb4d46ba web: fix missing flow and policy cache UI
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-22 13:04:13 +02:00
6600da7d98 providers/oauth2: add missing kid header to JWT Tokens
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-21 23:40:00 +02:00
a265dd54cc stages/authenticator_*: fix Permission Error when disabling Authenticator as non-superuser
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-21 21:25:03 +02:00
a603f42cc0 api: add OwnerFilter
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-21 20:46:59 +02:00
d9a788aac8 api: rename auth to authentication, add authorization for rest_framework permission class
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-21 20:14:03 +02:00
7c6185b581 api: fix URL names for admin Authenticator Views
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-21 19:53:40 +02:00
41a1305555 policies: improve debug logging
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-21 19:10:47 +02:00
75f252b530 flows: rename oob to oobe
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-21 19:10:42 +02:00
a9519a4a68 g: set x-forwarded-proto based on upstream TLS Status
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-05-21 09:41:39 +02:00
48 changed files with 528 additions and 390 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2021.5.3
current_version = 2021.5.4
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)

View File

@ -36,9 +36,9 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik:2021.5.3,
beryju/authentik:2021.5.4,
beryju/authentik:latest,
ghcr.io/goauthentik/server:2021.5.3,
ghcr.io/goauthentik/server:2021.5.4,
ghcr.io/goauthentik/server:latest
platforms: linux/amd64,linux/arm64
context: .
@ -75,9 +75,9 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-proxy:2021.5.3,
beryju/authentik-proxy:2021.5.4,
beryju/authentik-proxy:latest,
ghcr.io/goauthentik/proxy:2021.5.3,
ghcr.io/goauthentik/proxy:2021.5.4,
ghcr.io/goauthentik/proxy:latest
context: outpost/
file: outpost/proxy.Dockerfile
@ -115,9 +115,9 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-ldap:2021.5.3,
beryju/authentik-ldap:2021.5.4,
beryju/authentik-ldap:latest,
ghcr.io/goauthentik/ldap:2021.5.3,
ghcr.io/goauthentik/ldap:2021.5.4,
ghcr.io/goauthentik/ldap:latest
context: outpost/
file: outpost/ldap.Dockerfile
@ -155,5 +155,5 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
version: authentik@2021.5.3
version: authentik@2021.5.4
environment: beryjuorg-prod

View File

@ -1,3 +1,3 @@
"""authentik"""
__version__ = "2021.5.3"
__version__ = "2021.5.4"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -42,7 +42,7 @@ def token_from_header(raw_header: bytes) -> Optional[Token]:
return tokens.first()
class AuthentikTokenAuthentication(BaseAuthentication):
class TokenAuthentication(BaseAuthentication):
"""Token-based authentication using HTTP Bearer authentication"""
def authenticate(self, request: Request) -> Union[tuple[User, Any], None]:

View File

@ -0,0 +1,35 @@
"""API Authorization"""
from django.db.models import Model
from django.db.models.query import QuerySet
from rest_framework.filters import BaseFilterBackend
from rest_framework.permissions import BasePermission
from rest_framework.request import Request
class OwnerFilter(BaseFilterBackend):
"""Filter objects by their owner"""
owner_key = "user"
def filter_queryset(self, request: Request, queryset: QuerySet, view) -> QuerySet:
return queryset.filter(**{self.owner_key: request.user})
class OwnerPermissions(BasePermission):
"""Authorize requests by an object's owner matching the requesting user"""
owner_key = "user"
def has_permission(self, request: Request, view) -> bool:
"""If the user is authenticated, we allow all requests here. For listing, the
object-level permissions are done by the filter backend"""
return request.user.is_authenticated
def has_object_permission(self, request: Request, view, obj: Model) -> bool:
"""Check if the object's owner matches the currently logged in user"""
if not hasattr(obj, self.owner_key):
return False
owner = getattr(obj, self.owner_key)
if owner != request.user:
return False
return True

View File

@ -5,7 +5,7 @@ from django.test import TestCase
from guardian.shortcuts import get_anonymous_user
from rest_framework.exceptions import AuthenticationFailed
from authentik.api.auth import token_from_header
from authentik.api.authentication import token_from_header
from authentik.core.models import Token, TokenIntents

View File

@ -169,9 +169,19 @@ router.register("propertymappings/scope", ScopeMappingViewSet)
router.register("authenticators/static", StaticDeviceViewSet)
router.register("authenticators/totp", TOTPDeviceViewSet)
router.register("authenticators/webauthn", WebAuthnDeviceViewSet)
router.register("authenticators/admin/static", StaticAdminDeviceViewSet)
router.register("authenticators/admin/totp", TOTPAdminDeviceViewSet)
router.register("authenticators/admin/webauthn", WebAuthnAdminDeviceViewSet)
router.register(
"authenticators/admin/static",
StaticAdminDeviceViewSet,
basename="admin-staticdevice",
)
router.register(
"authenticators/admin/totp", TOTPAdminDeviceViewSet, basename="admin-totpdevice"
)
router.register(
"authenticators/admin/webauthn",
WebAuthnAdminDeviceViewSet,
basename="admin-webauthndevice",
)
router.register("stages/all", StageViewSet)
router.register("stages/authenticator/static", AuthenticatorStaticStageViewSet)

View File

@ -78,7 +78,7 @@ class PropertyMappingViewSet(
filterset_fields = {"managed": ["isnull"]}
ordering = ["name"]
def get_queryset(self):
def get_queryset(self): # pragma: no cover
return PropertyMapping.objects.select_subclasses()
@swagger_auto_schema(responses={200: TypeCreateSerializer(many=True)})

View File

@ -63,7 +63,7 @@ class ProviderViewSet(
"application__name",
]
def get_queryset(self):
def get_queryset(self): # pragma: no cover
return Provider.objects.select_subclasses()
@swagger_auto_schema(responses={200: TypeCreateSerializer(many=True)})

View File

@ -61,7 +61,7 @@ class SourceViewSet(
serializer_class = SourceSerializer
lookup_field = "slug"
def get_queryset(self):
def get_queryset(self): # pragma: no cover
return Source.objects.select_subclasses()
@swagger_auto_schema(responses={200: TypeCreateSerializer(many=True)})

View File

@ -139,7 +139,7 @@ class UserViewSet(ModelViewSet):
search_fields = ["username", "name", "is_active"]
filterset_class = UsersFilter
def get_queryset(self):
def get_queryset(self): # pragma: no cover
return User.objects.all().exclude(pk=get_anonymous_user().pk)
@swagger_auto_schema(responses={200: SessionUserSerializer(many=False)})

View File

@ -4,7 +4,7 @@ from channels.generic.websocket import JsonWebsocketConsumer
from rest_framework.exceptions import AuthenticationFailed
from structlog.stdlib import get_logger
from authentik.api.auth import token_from_header
from authentik.api.authentication import token_from_header
from authentik.core.models import User
LOGGER = get_logger()

View File

@ -1,12 +1,12 @@
"""Notification API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from guardian.utils import get_anonymous_user
from rest_framework import mixins
from rest_framework.fields import ReadOnlyField
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.events.api.event import EventSerializer
from authentik.events.models import Notification
@ -49,12 +49,5 @@ class NotificationViewSet(
"event",
"seen",
]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()
return Notification.objects.filter(user=user.pk)
permission_classes = [OwnerPermissions]
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]

View File

@ -65,7 +65,7 @@ class StageViewSet(
search_fields = ["name"]
filterset_fields = ["name"]
def get_queryset(self):
def get_queryset(self): # pragma: no cover
return Stage.objects.select_subclasses()
@swagger_auto_schema(responses={200: TypeCreateSerializer(many=True)})

View File

@ -21,7 +21,7 @@ context["user_backend"] = "django.contrib.auth.backends.ModelBackend"
return True"""
def create_default_oob_flow(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
def create_default_oobe_flow(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
from authentik.stages.prompt.models import FieldTypes
User = apps.get_model("authentik_core", "User")
@ -52,20 +52,20 @@ def create_default_oob_flow(apps: Apps, schema_editor: BaseDatabaseSchemaEditor)
# Create a policy that sets the flow's user
prefill_policy, _ = ExpressionPolicy.objects.using(db_alias).update_or_create(
name="default-oob-prefill-user",
name="default-oobe-prefill-user",
defaults={"expression": PREFILL_POLICY_EXPRESSION},
)
password_usable_policy, _ = ExpressionPolicy.objects.using(
db_alias
).update_or_create(
name="default-oob-password-usable",
name="default-oobe-password-usable",
defaults={"expression": PW_USABLE_POLICY_EXPRESSION},
)
prompt_header, _ = Prompt.objects.using(db_alias).update_or_create(
field_key="oob-header-text",
field_key="oobe-header-text",
defaults={
"label": "oob-header-text",
"label": "oobe-header-text",
"type": FieldTypes.STATIC,
"placeholder": "Welcome to authentik! Please set a password for the default admin user, akadmin.",
"order": 100,
@ -84,7 +84,7 @@ def create_default_oob_flow(apps: Apps, schema_editor: BaseDatabaseSchemaEditor)
password_second = Prompt.objects.using(db_alias).get(field_key="password_repeat")
prompt_stage, _ = PromptStage.objects.using(db_alias).update_or_create(
name="default-oob-password",
name="default-oobe-password",
)
prompt_stage.fields.set(
[prompt_header, prompt_email, password_first, password_second]
@ -102,7 +102,7 @@ def create_default_oob_flow(apps: Apps, schema_editor: BaseDatabaseSchemaEditor)
slug="initial-setup",
designation=FlowDesignation.STAGE_CONFIGURATION,
defaults={
"name": "default-oob-setup",
"name": "default-oobe-setup",
"title": "Welcome to authentik!",
},
)
@ -146,5 +146,5 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RunPython(create_default_oob_flow),
migrations.RunPython(create_default_oobe_flow),
]

View File

@ -2,28 +2,6 @@
from django.http import HttpRequest
from django.template.response import TemplateResponse
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView
from guardian.shortcuts import assign_perm
class CreateAssignPermView(CreateView):
"""Assign permissions to object after creation"""
permissions = [
"%s.view_%s",
"%s.change_%s",
"%s.delete_%s",
]
def form_valid(self, form):
response = super().form_valid(form)
for permission in self.permissions:
full_permission = permission % (
self.object._meta.app_label,
self.object._meta.model_name,
)
assign_perm(full_permission, self.request.user, self.object)
return response
def bad_request_message(

View File

@ -91,7 +91,7 @@ class PolicyViewSet(
}
search_fields = ["name"]
def get_queryset(self):
def get_queryset(self): # pragma: no cover
return Policy.objects.select_subclasses().prefetch_related(
"bindings", "promptstage_set"
)

View File

@ -105,16 +105,21 @@ class PolicyEngine:
if cached_policy and self.use_cache:
self.logger.debug(
"P_ENG: Taking result from cache",
policy=binding.policy,
binding=binding,
cache_key=key,
request=self.request,
)
self.__cached_policies.append(cached_policy)
continue
self.logger.debug("P_ENG: Evaluating policy", policy=binding.policy)
self.logger.debug(
"P_ENG: Evaluating policy", binding=binding, request=self.request
)
our_end, task_end = Pipe(False)
task = PolicyProcess(binding, self.request, task_end)
task.daemon = False
self.logger.debug("P_ENG: Starting Process", policy=binding.policy)
self.logger.debug(
"P_ENG: Starting Process", binding=binding, request=self.request
)
if not CURRENT_PROCESS._config.get("daemon"):
task.run()
else:

View File

@ -51,7 +51,12 @@ class PolicyRequest:
LOGGER.warning("failed to get geoip data", exc=exc)
def __str__(self):
return f"<PolicyRequest user={self.user}>"
text = f"<PolicyRequest user={self.user}"
if self.obj:
text += f" obj={self.obj}"
if self.http_request:
text += f" http_request={self.http_request}"
return text + ">"
@dataclass

View File

@ -6,11 +6,10 @@ import time
from dataclasses import asdict, dataclass, field
from datetime import datetime
from hashlib import sha256
from typing import Any, Optional, Type, Union
from typing import Any, Optional, Type
from urllib.parse import urlparse
from uuid import uuid4
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from dacite import from_dict
from django.db import models
from django.http import HttpRequest
@ -238,7 +237,7 @@ class OAuth2Provider(Provider):
token.access_token = token.create_access_token(user, request)
return token
def get_jwt_keys(self) -> Union[RSAPrivateKey, str]:
def get_jwt_key(self) -> str:
"""
Takes a provider and returns the set of keys associated with it.
Returns a list of keys.
@ -255,7 +254,7 @@ class OAuth2Provider(Provider):
self.jwt_alg = JWTAlgorithms.HS256
self.save()
else:
return self.rsa_key.private_key
return self.rsa_key.key_data
if self.jwt_alg == JWTAlgorithms.HS256:
return self.client_secret
@ -299,11 +298,14 @@ class OAuth2Provider(Provider):
def encode(self, payload: dict[str, Any]) -> str:
"""Represent the ID Token as a JSON Web Token (JWT)."""
key = self.get_jwt_keys()
headers = {}
if self.rsa_key:
headers["kid"] = self.rsa_key.kid
key = self.get_jwt_key()
# If the provider does not have an RSA Key assigned, it was switched to Symmetric
self.refresh_from_db()
# pyright: reportGeneralTypeIssues=false
return encode(payload, key, algorithm=self.jwt_alg)
return encode(payload, key, algorithm=self.jwt_alg, headers=headers)
class Meta:

View File

@ -4,6 +4,7 @@ from django.urls import reverse
from django.utils.encoding import force_str
from authentik.core.models import Application, User
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.challenge import ChallengeTypes
from authentik.flows.models import Flow
from authentik.providers.oauth2.errors import (
@ -207,6 +208,7 @@ class TestAuthorize(OAuthTestCase):
client_secret=generate_client_secret(),
authorization_flow=flow,
redirect_uris="http://localhost",
rsa_key=CertificateKeyPair.objects.first(),
)
Application.objects.create(name="app", slug="app", provider=provider)
state = generate_client_id()

View File

@ -2,7 +2,11 @@
from django.test import TestCase
from jwt import decode
from authentik.providers.oauth2.models import OAuth2Provider, RefreshToken
from authentik.providers.oauth2.models import (
JWTAlgorithms,
OAuth2Provider,
RefreshToken,
)
class OAuthTestCase(TestCase):
@ -19,9 +23,12 @@ class OAuthTestCase(TestCase):
def validate_jwt(self, token: RefreshToken, provider: OAuth2Provider):
"""Validate that all required fields are set"""
key = provider.client_secret
if provider.jwt_alg == JWTAlgorithms.RS256:
key = provider.rsa_key.public_key
jwt = decode(
token.access_token,
provider.client_secret,
key,
algorithms=[provider.jwt_alg],
audience=provider.client_id,
)

View File

@ -84,7 +84,6 @@ class IngressReconciler(KubernetesObjectReconciler[NetworkingV1beta1Ingress]):
"traefik.ingress.kubernetes.io/affinity": "true",
"nginx.ingress.kubernetes.io/proxy-buffers-number": "4",
"nginx.ingress.kubernetes.io/proxy-buffer-size": "16k",
"nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
}
annotations.update(
self.controller.outpost.config.kubernetes_ingress_annotations
@ -114,7 +113,7 @@ class IngressReconciler(KubernetesObjectReconciler[NetworkingV1beta1Ingress]):
NetworkingV1beta1HTTPIngressPath(
backend=NetworkingV1beta1IngressBackend(
service_name=self.name,
service_port="https",
service_port="http",
),
path="/akprox",
)
@ -129,7 +128,7 @@ class IngressReconciler(KubernetesObjectReconciler[NetworkingV1beta1Ingress]):
NetworkingV1beta1HTTPIngressPath(
backend=NetworkingV1beta1IngressBackend(
service_name=self.name,
service_port="https",
service_port="http",
),
path="/",
)

View File

@ -161,7 +161,7 @@ REST_FRAMEWORK = {
"rest_framework.permissions.DjangoObjectPermissions",
),
"DEFAULT_AUTHENTICATION_CLASSES": (
"authentik.api.auth.AuthentikTokenAuthentication",
"authentik.api.authentication.TokenAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
"DEFAULT_RENDERER_CLASSES": [

View File

@ -1,9 +1,10 @@
"""OAuth Source Serializer"""
from django_filters.rest_framework import DjangoFilterBackend
from guardian.utils import get_anonymous_user
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.viewsets import ModelViewSet
from rest_framework.viewsets import GenericViewSet
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.sources import SourceSerializer
from authentik.sources.oauth.models import UserOAuthSourceConnection
@ -21,20 +22,17 @@ class UserOAuthSourceConnectionSerializer(SourceSerializer):
]
class UserOAuthSourceConnectionViewSet(ModelViewSet):
class UserOAuthSourceConnectionViewSet(
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet,
):
"""Source Viewset"""
queryset = UserOAuthSourceConnection.objects.all()
serializer_class = UserOAuthSourceConnectionSerializer
filterset_fields = ["source__slug"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()
if user.is_superuser:
return super().get_queryset()
return super().get_queryset().filter(user=user.pk)
permission_classes = [OwnerPermissions]
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]

View File

@ -1,12 +1,13 @@
"""AuthenticatorStaticStage API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from django_otp.plugins.otp_static.models import StaticDevice
from guardian.utils import get_anonymous_user
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_static.models import AuthenticatorStaticStage
@ -37,23 +38,22 @@ class StaticDeviceSerializer(ModelSerializer):
depth = 2
class StaticDeviceViewSet(ModelViewSet):
class StaticDeviceViewSet(
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet,
):
"""Viewset for static authenticator devices"""
queryset = StaticDevice.objects.none()
queryset = StaticDevice.objects.all()
serializer_class = StaticDeviceSerializer
permission_classes = [OwnerPermissions]
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()
return StaticDevice.objects.filter(user=user.pk)
class StaticAdminDeviceViewSet(ReadOnlyModelViewSet):

View File

@ -0,0 +1,20 @@
"""Test Static API"""
from django.urls import reverse
from django_otp.plugins.otp_static.models import StaticDevice
from rest_framework.test import APITestCase
from authentik.core.models import User
class AuthenticatorStaticStage(APITestCase):
"""Test Static API"""
def test_api_delete(self):
"""Test api delete"""
user = User.objects.create(username="foo")
self.client.force_login(user)
dev = StaticDevice.objects.create(user=user)
response = self.client.delete(
reverse("authentik_api:staticdevice-detail", kwargs={"pk": dev.pk})
)
self.assertEqual(response.status_code, 204)

View File

@ -1,12 +1,13 @@
"""AuthenticatorTOTPStage API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from django_filters.rest_framework.backends import DjangoFilterBackend
from django_otp.plugins.otp_totp.models import TOTPDevice
from guardian.utils import get_anonymous_user
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_totp.models import AuthenticatorTOTPStage
@ -40,23 +41,22 @@ class TOTPDeviceSerializer(ModelSerializer):
depth = 2
class TOTPDeviceViewSet(ModelViewSet):
class TOTPDeviceViewSet(
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet,
):
"""Viewset for totp authenticator devices"""
queryset = TOTPDevice.objects.none()
queryset = TOTPDevice.objects.all()
serializer_class = TOTPDeviceSerializer
permission_classes = [OwnerPermissions]
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()
return TOTPDevice.objects.filter(user=user.pk)
class TOTPAdminDeviceViewSet(ReadOnlyModelViewSet):

View File

@ -0,0 +1,20 @@
"""Test TOTP API"""
from django.urls import reverse
from django_otp.plugins.otp_totp.models import TOTPDevice
from rest_framework.test import APITestCase
from authentik.core.models import User
class AuthenticatorTOTPStage(APITestCase):
"""Test TOTP API"""
def test_api_delete(self):
"""Test api delete"""
user = User.objects.create(username="foo")
self.client.force_login(user)
dev = TOTPDevice.objects.create(user=user)
response = self.client.delete(
reverse("authentik_api:totpdevice-detail", kwargs={"pk": dev.pk})
)
self.assertEqual(response.status_code, 204)

View File

@ -1,11 +1,12 @@
"""AuthenticateWebAuthnStage API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from guardian.utils import get_anonymous_user
from django_filters.rest_framework.backends import DjangoFilterBackend
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_webauthn.models import (
AuthenticateWebAuthnStage,
@ -39,23 +40,22 @@ class WebAuthnDeviceSerializer(ModelSerializer):
depth = 2
class WebAuthnDeviceViewSet(ModelViewSet):
class WebAuthnDeviceViewSet(
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet,
):
"""Viewset for WebAuthn authenticator devices"""
queryset = WebAuthnDevice.objects.none()
queryset = WebAuthnDevice.objects.all()
serializer_class = WebAuthnDeviceSerializer
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()
return WebAuthnDevice.objects.filter(user=user.pk)
permission_classes = [OwnerPermissions]
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
class WebAuthnAdminDeviceViewSet(ReadOnlyModelViewSet):

View File

@ -0,0 +1,20 @@
"""Test WebAuthn API"""
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.stages.authenticator_webauthn.models import WebAuthnDevice
class AuthenticatorWebAuthnStage(APITestCase):
"""Test WebAuthn API"""
def test_api_delete(self):
"""Test api delete"""
user = User.objects.create(username="foo")
self.client.force_login(user)
dev = WebAuthnDevice.objects.create(user=user)
response = self.client.delete(
reverse("authentik_api:webauthndevice-detail", kwargs={"pk": dev.pk})
)
self.assertEqual(response.status_code, 204)

View File

@ -1,5 +1,5 @@
"""dummy tests"""
from django.test import Client, TestCase
from django.test import TestCase
from django.urls import reverse
from django.utils.encoding import force_str
@ -14,7 +14,6 @@ class TestDummyStage(TestCase):
def setUp(self):
super().setUp()
self.user = User.objects.create(username="unittest", email="test@beryju.org")
self.client = Client()
self.flow = Flow.objects.create(
name="test-dummy",

View File

@ -21,7 +21,7 @@ services:
networks:
- internal
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.5.3}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.5.4}
restart: unless-stopped
command: server
environment:
@ -52,7 +52,7 @@ services:
- "0.0.0.0:9000:9000"
- "0.0.0.0:9443:9443"
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.5.3}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.5.4}
restart: unless-stopped
command: worker
networks:

View File

@ -1,3 +1,3 @@
package constants
const VERSION = "2021.5.3"
const VERSION = "2021.5.4"

View File

@ -9,7 +9,18 @@ import (
func (ws *WebServer) configureProxy() {
// Reverse proxy to the application server
u, _ := url.Parse("http://localhost:8000")
rp := httputil.NewSingleHostReverseProxy(u)
director := func(req *http.Request) {
req.URL.Scheme = u.Scheme
req.URL.Host = u.Host
if _, ok := req.Header["User-Agent"]; !ok {
// explicitly disable User-Agent so it's not set to default value
req.Header.Set("User-Agent", "")
}
if req.TLS != nil {
req.Header.Set("X-Forwarded-Proto", "https")
}
}
rp := &httputil.ReverseProxy{Director: director}
rp.ErrorHandler = ws.proxyErrorHandler
rp.ModifyResponse = ws.proxyModifyResponse
ws.m.PathPrefix("/").Handler(rp)

View File

@ -18,7 +18,7 @@ function check_if_root {
fi
# Fix permissions of backups and media
chown -R authentik:authentik /media /backups
chpst -u authentik env HOME=/authentik $1
chpst -u authentik:authentik:docker env HOME=/authentik $1
}
if [[ "$1" == "server" ]]; then

View File

@ -5,7 +5,7 @@ import (
"os"
)
const VERSION = "2021.5.3"
const VERSION = "2021.5.4"
func BUILD() string {
return os.Getenv("GIT_BUILD_HASH")

View File

@ -595,30 +595,6 @@ paths:
$ref: '#/definitions/GenericError'
tags:
- authenticators
post:
operationId: authenticators_static_create
description: Viewset for static authenticator devices
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/StaticDevice'
responses:
'201':
description: ''
schema:
$ref: '#/definitions/StaticDevice'
'400':
description: Invalid input.
schema:
$ref: '#/definitions/ValidationError'
'403':
description: Authentication credentials were invalid, absent or insufficient.
schema:
$ref: '#/definitions/GenericError'
tags:
- authenticators
parameters: []
/authenticators/static/{id}/:
get:
@ -797,30 +773,6 @@ paths:
$ref: '#/definitions/GenericError'
tags:
- authenticators
post:
operationId: authenticators_totp_create
description: Viewset for totp authenticator devices
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/TOTPDevice'
responses:
'201':
description: ''
schema:
$ref: '#/definitions/TOTPDevice'
'400':
description: Invalid input.
schema:
$ref: '#/definitions/ValidationError'
'403':
description: Authentication credentials were invalid, absent or insufficient.
schema:
$ref: '#/definitions/GenericError'
tags:
- authenticators
parameters: []
/authenticators/totp/{id}/:
get:
@ -999,30 +951,6 @@ paths:
$ref: '#/definitions/GenericError'
tags:
- authenticators
post:
operationId: authenticators_webauthn_create
description: Viewset for WebAuthn authenticator devices
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/WebAuthnDevice'
responses:
'201':
description: ''
schema:
$ref: '#/definitions/WebAuthnDevice'
'400':
description: Invalid input.
schema:
$ref: '#/definitions/ValidationError'
'403':
description: Authentication credentials were invalid, absent or insufficient.
schema:
$ref: '#/definitions/GenericError'
tags:
- authenticators
parameters: []
/authenticators/webauthn/{id}/:
get:
@ -10425,30 +10353,6 @@ paths:
$ref: '#/definitions/GenericError'
tags:
- sources
post:
operationId: sources_oauth_user_connections_create
description: Source Viewset
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/UserOAuthSourceConnection'
responses:
'201':
description: ''
schema:
$ref: '#/definitions/UserOAuthSourceConnection'
'400':
description: Invalid input.
schema:
$ref: '#/definitions/ValidationError'
'403':
description: Authentication credentials were invalid, absent or insufficient.
schema:
$ref: '#/definitions/GenericError'
tags:
- sources
parameters: []
/sources/oauth_user_connections/{id}/:
get:
@ -18045,6 +17949,7 @@ definitions:
required:
- name
- slug
- plex_token
type: object
properties:
pk:

View File

@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current";
export const VERSION = "2021.5.3";
export const VERSION = "2021.5.4";
export const PAGE_SIZE = 20;
export const EVENT_REFRESH = "ak-refresh";
export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle";

View File

@ -144,7 +144,7 @@ msgstr "Algorithm used to sign the JWT Tokens."
msgid "Allow IDP-initiated logins"
msgstr "Allow IDP-initiated logins"
#: src/pages/sources/plex/PlexSourceForm.ts:150
#: src/pages/sources/plex/PlexSourceForm.ts:103
msgid "Allow friends to authenticate via Plex, even if you don't share any servers"
msgstr "Allow friends to authenticate via Plex, even if you don't share any servers"
@ -152,7 +152,7 @@ msgstr "Allow friends to authenticate via Plex, even if you don't share any serv
msgid "Allow up to N occurrences in the HIBP database."
msgstr "Allow up to N occurrences in the HIBP database."
#: src/pages/policies/PolicyListPage.ts:41
#: src/pages/policies/PolicyListPage.ts:42
msgid "Allow users to use Applications based on properties, enforce Password Criteria and selectively apply Stages."
msgstr "Allow users to use Applications based on properties, enforce Password Criteria and selectively apply Stages."
@ -164,7 +164,7 @@ msgstr "Allowed Redirect URIs"
msgid "Allowed count"
msgstr "Allowed count"
#: src/pages/sources/plex/PlexSourceForm.ts:155
#: src/pages/sources/plex/PlexSourceForm.ts:108
msgid "Allowed servers"
msgstr "Allowed servers"
@ -218,6 +218,22 @@ msgstr "Applications"
msgid "Apps with most usage"
msgstr "Apps with most usage"
#: src/pages/flows/FlowListPage.ts:146
msgid ""
"Are you sure you want to clear the flow cache?\n"
"This will cause all flows to be re-evaluated on their next usage."
msgstr ""
"Are you sure you want to clear the flow cache?\n"
"This will cause all flows to be re-evaluated on their next usage."
#: src/pages/policies/PolicyListPage.ts:165
msgid ""
"Are you sure you want to clear the policy cache?\n"
"This will cause all policies to be re-evaluated on their next usage."
msgstr ""
"Are you sure you want to clear the policy cache?\n"
"This will cause all policies to be re-evaluated on their next usage."
#: src/elements/forms/DeleteForm.ts:69
msgid "Are you sure you want to delete {0} {objName} ?"
msgstr "Are you sure you want to delete {0} {objName} ?"
@ -250,7 +266,7 @@ msgstr "Assertions is empty"
msgid "Assigned to application"
msgstr "Assigned to application"
#: src/pages/policies/PolicyListPage.ts:68
#: src/pages/policies/PolicyListPage.ts:69
msgid "Assigned to {0} objects."
msgstr "Assigned to {0} objects."
@ -282,7 +298,7 @@ msgid "Authentication"
msgstr "Authentication"
#: src/pages/sources/oauth/OAuthSourceForm.ts:231
#: src/pages/sources/plex/PlexSourceForm.ts:185
#: src/pages/sources/plex/PlexSourceForm.ts:190
#: src/pages/sources/saml/SAMLSourceForm.ts:243
msgid "Authentication flow"
msgstr "Authentication flow"
@ -530,6 +546,21 @@ msgstr "Checks if the request's user's password has been changed in the last x d
msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength."
msgstr "Checks the value from the policy request against several rules, mostly used to ensure password strength."
#: src/pages/flows/FlowListPage.ts:143
msgid "Clear Flow cache"
msgstr "Clear Flow cache"
#: src/pages/policies/PolicyListPage.ts:162
msgid "Clear Policy cache"
msgstr "Clear Policy cache"
#: src/pages/flows/FlowListPage.ts:138
#: src/pages/flows/FlowListPage.ts:150
#: src/pages/policies/PolicyListPage.ts:157
#: src/pages/policies/PolicyListPage.ts:169
msgid "Clear cache"
msgstr "Clear cache"
#: src/elements/forms/HorizontalFormElement.ts:82
msgid "Click to change value"
msgstr "Click to change value"
@ -540,7 +571,7 @@ msgstr "Click to copy token"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:107
#: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts:99
#: src/pages/sources/plex/PlexSourceForm.ts:141
#: src/pages/sources/plex/PlexSourceForm.ts:176
msgid "Client ID"
msgstr "Client ID"
@ -726,8 +757,8 @@ msgstr "Copy download URL"
#: src/pages/flows/BoundStagesList.ts:119
#: src/pages/flows/BoundStagesList.ts:146
#: src/pages/flows/BoundStagesList.ts:167
#: src/pages/flows/FlowListPage.ts:109
#: src/pages/flows/FlowListPage.ts:117
#: src/pages/flows/FlowListPage.ts:110
#: src/pages/flows/FlowListPage.ts:118
#: src/pages/groups/GroupListPage.ts:90
#: src/pages/groups/GroupListPage.ts:98
#: src/pages/outposts/OutpostListPage.ts:101
@ -737,8 +768,8 @@ msgstr "Copy download URL"
#: src/pages/policies/BoundPoliciesList.ts:162
#: src/pages/policies/BoundPoliciesList.ts:189
#: src/pages/policies/BoundPoliciesList.ts:210
#: src/pages/policies/PolicyListPage.ts:124
#: src/pages/policies/PolicyListPage.ts:133
#: src/pages/policies/PolicyListPage.ts:125
#: src/pages/policies/PolicyListPage.ts:134
#: src/pages/property-mappings/PropertyMappingListPage.ts:113
#: src/pages/property-mappings/PropertyMappingListPage.ts:122
#: src/pages/providers/ProviderListPage.ts:108
@ -778,7 +809,7 @@ msgstr "Create Binding"
msgid "Create Certificate-Key Pair"
msgstr "Create Certificate-Key Pair"
#: src/pages/flows/FlowListPage.ts:112
#: src/pages/flows/FlowListPage.ts:113
msgid "Create Flow"
msgstr "Create Flow"
@ -840,7 +871,7 @@ msgstr "Create provider"
#: src/pages/flows/BoundStagesList.ts:149
#: src/pages/outposts/ServiceConnectionListPage.ts:122
#: src/pages/policies/BoundPoliciesList.ts:192
#: src/pages/policies/PolicyListPage.ts:136
#: src/pages/policies/PolicyListPage.ts:137
#: src/pages/property-mappings/PropertyMappingListPage.ts:125
#: src/pages/providers/ProviderListPage.ts:120
#: src/pages/sources/SourcesListPage.ts:126
@ -892,11 +923,11 @@ msgstr "Define how notifications are sent to users, like Email or Webhook."
#: src/pages/crypto/CertificateKeyPairListPage.ts:86
#: src/pages/events/RuleListPage.ts:82
#: src/pages/events/TransportListPage.ts:86
#: src/pages/flows/FlowListPage.ts:86
#: src/pages/flows/FlowListPage.ts:87
#: src/pages/groups/GroupListPage.ts:81
#: src/pages/outposts/OutpostListPage.ts:87
#: src/pages/outposts/ServiceConnectionListPage.ts:101
#: src/pages/policies/PolicyListPage.ts:115
#: src/pages/policies/PolicyListPage.ts:116
#: src/pages/property-mappings/PropertyMappingListPage.ts:104
#: src/pages/providers/ProviderListPage.ts:99
#: src/pages/sources/SourcesListPage.ts:95
@ -967,7 +998,7 @@ msgid "Designates whether this user should be treated as active. Unselect this i
msgstr "Designates whether this user should be treated as active. Unselect this instead of deleting accounts."
#: src/pages/flows/FlowForm.ts:119
#: src/pages/flows/FlowListPage.ts:48
#: src/pages/flows/FlowListPage.ts:49
msgid "Designation"
msgstr "Designation"
@ -1049,11 +1080,11 @@ msgstr "Each provider has a different issuer, based on the application slug."
#: src/pages/crypto/CertificateKeyPairListPage.ts:74
#: src/pages/events/RuleListPage.ts:70
#: src/pages/events/TransportListPage.ts:74
#: src/pages/flows/FlowListPage.ts:74
#: src/pages/flows/FlowListPage.ts:75
#: src/pages/groups/GroupListPage.ts:69
#: src/pages/outposts/OutpostListPage.ts:75
#: src/pages/outposts/ServiceConnectionListPage.ts:89
#: src/pages/policies/PolicyListPage.ts:90
#: src/pages/policies/PolicyListPage.ts:91
#: src/pages/property-mappings/PropertyMappingListPage.ts:79
#: src/pages/providers/ProviderListPage.ts:87
#: src/pages/providers/ldap/LDAPProviderViewPage.ts:103
@ -1148,7 +1179,7 @@ msgstr "Enable this if you don't want to use this provider as a proxy, and want
#: src/pages/policies/PolicyBindingForm.ts:199
#: src/pages/sources/ldap/LDAPSourceForm.ts:67
#: src/pages/sources/oauth/OAuthSourceForm.ts:134
#: src/pages/sources/plex/PlexSourceForm.ts:108
#: src/pages/sources/plex/PlexSourceForm.ts:143
#: src/pages/sources/saml/SAMLSourceForm.ts:67
msgid "Enabled"
msgstr "Enabled"
@ -1158,7 +1189,7 @@ msgid "Enrollment"
msgstr "Enrollment"
#: src/pages/sources/oauth/OAuthSourceForm.ts:252
#: src/pages/sources/plex/PlexSourceForm.ts:206
#: src/pages/sources/plex/PlexSourceForm.ts:211
#: src/pages/sources/saml/SAMLSourceForm.ts:264
#: src/pages/stages/identification/IdentificationStageForm.ts:104
msgid "Enrollment flow"
@ -1225,12 +1256,12 @@ msgstr "Events"
msgid "Exception"
msgstr "Exception"
#: src/pages/flows/FlowListPage.ts:98
#: src/pages/flows/FlowViewPage.ts:83
#: src/pages/flows/FlowListPage.ts:99
#: src/pages/flows/FlowViewPage.ts:75
msgid "Execute"
msgstr "Execute"
#: src/pages/flows/FlowViewPage.ts:69
#: src/pages/flows/FlowViewPage.ts:61
msgid "Execute flow"
msgstr "Execute flow"
@ -1277,7 +1308,7 @@ msgstr "Expiry date"
msgid "Explicit Consent"
msgstr "Explicit Consent"
#: src/pages/flows/FlowListPage.ts:101
#: src/pages/flows/FlowListPage.ts:102
msgid "Export"
msgstr "Export"
@ -1316,6 +1347,14 @@ msgstr "Failed attempts before cancel"
msgid "Failed sources"
msgstr "Failed sources"
#: src/pages/flows/FlowListPage.ts:137
msgid "Failed to delete flow cache"
msgstr "Failed to delete flow cache"
#: src/pages/policies/PolicyListPage.ts:156
msgid "Failed to delete policy cache"
msgstr "Failed to delete policy cache"
#: src/elements/forms/DeleteForm.ts:46
msgid "Failed to delete {0}: {1}"
msgstr "Failed to delete {0}: {1}"
@ -1358,7 +1397,7 @@ msgid "Fields a user can identify themselves with. If no fields are selected, th
msgstr "Fields a user can identify themselves with. If no fields are selected, the user will only be able to use sources."
#: src/pages/flows/FlowImportForm.ts:34
#: src/pages/flows/FlowListPage.ts:79
#: src/pages/flows/FlowListPage.ts:80
msgid "Flow"
msgstr "Flow"
@ -1367,19 +1406,19 @@ msgid "Flow Overview"
msgstr "Flow Overview"
#: src/pages/sources/oauth/OAuthSourceForm.ts:227
#: src/pages/sources/plex/PlexSourceForm.ts:181
#: src/pages/sources/plex/PlexSourceForm.ts:186
#: src/pages/sources/saml/SAMLSourceForm.ts:218
msgid "Flow settings"
msgstr "Flow settings"
#: src/pages/sources/oauth/OAuthSourceForm.ts:249
#: src/pages/sources/plex/PlexSourceForm.ts:203
#: src/pages/sources/plex/PlexSourceForm.ts:208
#: src/pages/sources/saml/SAMLSourceForm.ts:261
msgid "Flow to use when authenticating existing users."
msgstr "Flow to use when authenticating existing users."
#: src/pages/sources/oauth/OAuthSourceForm.ts:270
#: src/pages/sources/plex/PlexSourceForm.ts:224
#: src/pages/sources/plex/PlexSourceForm.ts:229
#: src/pages/sources/saml/SAMLSourceForm.ts:282
msgid "Flow to use when enrolling new users."
msgstr "Flow to use when enrolling new users."
@ -1411,12 +1450,12 @@ msgstr "Flow used when authorizing this provider."
#: src/interfaces/AdminInterface.ts:82
#: src/interfaces/AdminInterface.ts:84
#: src/pages/admin-overview/AdminOverviewPage.ts:61
#: src/pages/flows/FlowListPage.ts:28
#: src/pages/flows/FlowListPage.ts:29
#: src/pages/stages/StageListPage.ts:66
msgid "Flows"
msgstr "Flows"
#: src/pages/flows/FlowListPage.ts:31
#: src/pages/flows/FlowListPage.ts:32
msgid "Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them."
msgstr "Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them."
@ -1546,7 +1585,7 @@ msgstr "Hide service-accounts"
#: src/pages/providers/saml/SAMLProviderForm.ts:176
#: src/pages/sources/ldap/LDAPSourceForm.ts:165
#: src/pages/sources/ldap/LDAPSourceForm.ts:191
#: src/pages/sources/plex/PlexSourceForm.ts:168
#: src/pages/sources/plex/PlexSourceForm.ts:121
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts:114
#: src/pages/stages/identification/IdentificationStageForm.ts:83
#: src/pages/stages/password/PasswordStageForm.ts:84
@ -1567,7 +1606,7 @@ msgstr "ID"
msgid "Icon"
msgstr "Icon"
#: src/pages/flows/FlowListPage.ts:46
#: src/pages/flows/FlowListPage.ts:47
#: src/pages/system-tasks/SystemTaskListPage.ts:54
#: src/pages/tokens/TokenListPage.ts:44
#: src/pages/user-settings/tokens/UserTokenForm.ts:49
@ -1600,12 +1639,12 @@ msgstr "If your authentik Instance is using a self-signed certificate, set this
msgid "Impersonate"
msgstr "Impersonate"
#: src/pages/flows/FlowListPage.ts:122
#: src/pages/flows/FlowListPage.ts:130
#: src/pages/flows/FlowListPage.ts:123
#: src/pages/flows/FlowListPage.ts:131
msgid "Import"
msgstr "Import"
#: src/pages/flows/FlowListPage.ts:125
#: src/pages/flows/FlowListPage.ts:126
msgid "Import Flow"
msgstr "Import Flow"
@ -1716,7 +1755,7 @@ msgstr "Last login"
msgid "Last run"
msgstr "Last run"
#: src/pages/outposts/OutpostHealth.ts:54
#: src/pages/outposts/OutpostHealth.ts:53
msgid "Last seen: {0}"
msgstr "Last seen: {0}"
@ -1742,21 +1781,21 @@ msgid "Library"
msgstr "Library"
#: src/pages/sources/oauth/OAuthSourceForm.ts:147
#: src/pages/sources/plex/PlexSourceForm.ts:121
#: src/pages/sources/plex/PlexSourceForm.ts:156
msgid "Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses"
msgstr "Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses"
#: src/pages/sources/oauth/OAuthSourceForm.ts:153
#: src/pages/sources/plex/PlexSourceForm.ts:127
#: src/pages/sources/plex/PlexSourceForm.ts:162
msgid "Link to a user with identical username address. Can have security implications when a username is used with another source."
msgstr "Link to a user with identical username address. Can have security implications when a username is used with another source."
#: src/pages/sources/oauth/OAuthSourceForm.ts:144
#: src/pages/sources/plex/PlexSourceForm.ts:118
#: src/pages/sources/plex/PlexSourceForm.ts:153
msgid "Link users on unique identifier"
msgstr "Link users on unique identifier"
#: src/pages/sources/plex/PlexSourceForm.ts:173
#: src/pages/sources/plex/PlexSourceForm.ts:96
msgid "Load servers"
msgstr "Load servers"
@ -1821,8 +1860,8 @@ msgstr "Loading"
#: src/pages/sources/oauth/OAuthSourceForm.ts:219
#: src/pages/sources/oauth/OAuthSourceForm.ts:247
#: src/pages/sources/oauth/OAuthSourceForm.ts:268
#: src/pages/sources/plex/PlexSourceForm.ts:201
#: src/pages/sources/plex/PlexSourceForm.ts:222
#: src/pages/sources/plex/PlexSourceForm.ts:206
#: src/pages/sources/plex/PlexSourceForm.ts:227
#: src/pages/sources/saml/SAMLSourceForm.ts:124
#: src/pages/sources/saml/SAMLSourceForm.ts:238
#: src/pages/sources/saml/SAMLSourceForm.ts:259
@ -1961,7 +2000,7 @@ msgstr "My Applications"
#: src/pages/events/TransportListPage.ts:46
#: src/pages/flows/BoundStagesList.ts:39
#: src/pages/flows/FlowForm.ts:86
#: src/pages/flows/FlowListPage.ts:47
#: src/pages/flows/FlowListPage.ts:48
#: src/pages/groups/GroupForm.ts:58
#: src/pages/groups/GroupListPage.ts:45
#: src/pages/groups/MemberSelectModal.ts:45
@ -1970,7 +2009,7 @@ msgstr "My Applications"
#: src/pages/outposts/ServiceConnectionDockerForm.ts:51
#: src/pages/outposts/ServiceConnectionKubernetesForm.ts:52
#: src/pages/outposts/ServiceConnectionListPage.ts:53
#: src/pages/policies/PolicyListPage.ts:56
#: src/pages/policies/PolicyListPage.ts:57
#: src/pages/policies/dummy/DummyPolicyForm.ts:54
#: src/pages/policies/event_matcher/EventMatcherPolicyForm.ts:55
#: src/pages/policies/expiry/ExpiryPolicyForm.ts:54
@ -1997,7 +2036,7 @@ msgstr "My Applications"
#: src/pages/sources/ldap/LDAPSourceViewPage.ts:64
#: src/pages/sources/oauth/OAuthSourceForm.ts:108
#: src/pages/sources/oauth/OAuthSourceViewPage.ts:64
#: src/pages/sources/plex/PlexSourceForm.ts:93
#: src/pages/sources/plex/PlexSourceForm.ts:128
#: src/pages/sources/plex/PlexSourceViewPage.ts:63
#: src/pages/sources/saml/SAMLSourceForm.ts:52
#: src/pages/sources/saml/SAMLSourceViewPage.ts:66
@ -2359,15 +2398,15 @@ msgstr "Please enter your password"
#: src/interfaces/AdminInterface.ts:74
#: src/pages/admin-overview/AdminOverviewPage.ts:56
#: src/pages/flows/FlowListPage.ts:50
#: src/pages/policies/PolicyListPage.ts:38
#: src/pages/flows/FlowListPage.ts:51
#: src/pages/policies/PolicyListPage.ts:39
msgid "Policies"
msgstr "Policies"
#: src/pages/policies/PolicyBindingForm.ts:108
#: src/pages/policies/PolicyBindingForm.ts:117
#: src/pages/policies/PolicyBindingForm.ts:148
#: src/pages/policies/PolicyListPage.ts:108
#: src/pages/policies/PolicyListPage.ts:109
msgid "Policy"
msgstr "Policy"
@ -2492,7 +2531,7 @@ msgstr "Protocol Settings"
#: src/pages/providers/proxy/ProxyProviderForm.ts:123
#: src/pages/providers/saml/SAMLProviderForm.ts:77
#: src/pages/sources/oauth/OAuthSourceForm.ts:163
#: src/pages/sources/plex/PlexSourceForm.ts:137
#: src/pages/sources/plex/PlexSourceForm.ts:172
#: src/pages/sources/saml/SAMLSourceForm.ts:74
msgid "Protocol settings"
msgstr "Protocol settings"
@ -2623,7 +2662,7 @@ msgid "Regular expressions for which authentication is not required. Each new li
msgstr "Regular expressions for which authentication is not required. Each new line is interpreted as a new Regular Expression."
#: src/pages/applications/ApplicationViewPage.ts:62
#: src/pages/flows/FlowViewPage.ts:64
#: src/pages/flows/FlowViewPage.ts:56
msgid "Related"
msgstr "Related"
@ -2800,7 +2839,7 @@ msgstr "Select users to add"
msgid "Select which scopes can be used by the client. The client stil has to specify the scope to access the data."
msgstr "Select which scopes can be used by the client. The client stil has to specify the scope to access the data."
#: src/pages/sources/plex/PlexSourceForm.ts:167
#: src/pages/sources/plex/PlexSourceForm.ts:120
msgid "Select which server a user has to be a member of to be allowed to authenticate."
msgstr "Select which server a user has to be a member of to be allowed to authenticate."
@ -2940,7 +2979,7 @@ msgstr "Skip path regex"
#: src/pages/flows/FlowForm.ts:99
#: src/pages/sources/ldap/LDAPSourceForm.ts:58
#: src/pages/sources/oauth/OAuthSourceForm.ts:114
#: src/pages/sources/plex/PlexSourceForm.ts:99
#: src/pages/sources/plex/PlexSourceForm.ts:134
#: src/pages/sources/saml/SAMLSourceForm.ts:58
msgid "Slug"
msgstr "Slug"
@ -3017,7 +3056,7 @@ msgid "Stage-specific settings"
msgstr "Stage-specific settings"
#: src/interfaces/AdminInterface.ts:87
#: src/pages/flows/FlowListPage.ts:49
#: src/pages/flows/FlowListPage.ts:50
#: src/pages/stages/StageListPage.ts:44
#: src/pages/stages/prompt/PromptListPage.ts:50
msgid "Stages"
@ -3081,6 +3120,14 @@ msgstr "Subject-alt name"
msgid "Successful"
msgstr "Successful"
#: src/pages/flows/FlowListPage.ts:136
msgid "Successfully cleared flow cache"
msgstr "Successfully cleared flow cache"
#: src/pages/policies/PolicyListPage.ts:155
msgid "Successfully cleared policy cache"
msgstr "Successfully cleared policy cache"
#: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts:63
msgid "Successfully copied TOTP Config."
msgstr "Successfully copied TOTP Config."
@ -3405,14 +3452,14 @@ msgid "Template"
msgstr "Template"
#: src/pages/events/TransportListPage.ts:62
#: src/pages/policies/PolicyListPage.ts:95
#: src/pages/policies/PolicyListPage.ts:103
#: src/pages/policies/PolicyListPage.ts:96
#: src/pages/policies/PolicyListPage.ts:104
#: src/pages/property-mappings/PropertyMappingListPage.ts:84
#: src/pages/property-mappings/PropertyMappingListPage.ts:92
msgid "Test"
msgstr "Test"
#: src/pages/policies/PolicyListPage.ts:98
#: src/pages/policies/PolicyListPage.ts:99
msgid "Test Policy"
msgstr "Test Policy"
@ -3429,8 +3476,8 @@ msgid "The URL \"{0}\" was not found."
msgstr "The URL \"{0}\" was not found."
#: src/pages/providers/proxy/ProxyProviderForm.ts:131
msgid "The external URL you'll access the application at"
msgstr "The external URL you'll access the application at"
msgid "The external URL you'll access the application at. Include any non-standard port."
msgstr "The external URL you'll access the application at. Include any non-standard port."
#: src/pages/policies/dummy/DummyPolicyForm.ts:88
msgid "The policy takes a random time to execute. This controls the minimum time it will take."
@ -3564,7 +3611,7 @@ msgstr "Transports"
#: src/pages/flows/BoundStagesList.ts:40
#: src/pages/outposts/OutpostForm.ts:58
#: src/pages/outposts/ServiceConnectionListPage.ts:54
#: src/pages/policies/PolicyListPage.ts:57
#: src/pages/policies/PolicyListPage.ts:58
#: src/pages/property-mappings/PropertyMappingListPage.ts:55
#: src/pages/providers/ProviderListPage.ts:55
#: src/pages/sources/SourcesListPage.ts:53
@ -3640,7 +3687,7 @@ msgstr "Up-to-date!"
#: src/pages/events/TransportListPage.ts:66
#: src/pages/flows/BoundStagesList.ts:53
#: src/pages/flows/BoundStagesList.ts:71
#: src/pages/flows/FlowListPage.ts:66
#: src/pages/flows/FlowListPage.ts:67
#: src/pages/groups/GroupListPage.ts:61
#: src/pages/outposts/OutpostListPage.ts:67
#: src/pages/outposts/ServiceConnectionListPage.ts:76
@ -3648,7 +3695,7 @@ msgstr "Up-to-date!"
#: src/pages/policies/BoundPoliciesList.ts:88
#: src/pages/policies/BoundPoliciesList.ts:103
#: src/pages/policies/BoundPoliciesList.ts:129
#: src/pages/policies/PolicyListPage.ts:77
#: src/pages/policies/PolicyListPage.ts:78
#: src/pages/property-mappings/PropertyMappingListPage.ts:66
#: src/pages/providers/ProviderListPage.ts:74
#: src/pages/providers/ldap/LDAPProviderViewPage.ts:93
@ -3686,7 +3733,7 @@ msgstr "Update Binding"
msgid "Update Certificate-Key Pair"
msgstr "Update Certificate-Key Pair"
#: src/pages/flows/FlowListPage.ts:69
#: src/pages/flows/FlowListPage.ts:70
msgid "Update Flow"
msgstr "Update Flow"
@ -3764,7 +3811,7 @@ msgstr "Update details"
#: src/pages/flows/BoundStagesList.ts:56
#: src/pages/outposts/ServiceConnectionListPage.ts:79
#: src/pages/policies/BoundPoliciesList.ts:71
#: src/pages/policies/PolicyListPage.ts:80
#: src/pages/policies/PolicyListPage.ts:81
#: src/pages/property-mappings/PropertyMappingListPage.ts:69
#: src/pages/providers/ProviderListPage.ts:77
#: src/pages/sources/SourcesListPage.ts:73
@ -3798,12 +3845,12 @@ msgid "Use global settings"
msgstr "Use global settings"
#: src/pages/sources/oauth/OAuthSourceForm.ts:150
#: src/pages/sources/plex/PlexSourceForm.ts:124
#: src/pages/sources/plex/PlexSourceForm.ts:159
msgid "Use the user's email address, but deny enrollment when the email address already exists."
msgstr "Use the user's email address, but deny enrollment when the email address already exists."
#: src/pages/sources/oauth/OAuthSourceForm.ts:156
#: src/pages/sources/plex/PlexSourceForm.ts:130
#: src/pages/sources/plex/PlexSourceForm.ts:165
msgid "Use the user's username, but deny enrollment when the username already exists."
msgstr "Use the user's username, but deny enrollment when the username already exists."
@ -3852,7 +3899,7 @@ msgid "User fields"
msgstr "User fields"
#: src/pages/sources/oauth/OAuthSourceForm.ts:139
#: src/pages/sources/plex/PlexSourceForm.ts:113
#: src/pages/sources/plex/PlexSourceForm.ts:148
msgid "User matching mode"
msgstr "User matching mode"
@ -3913,8 +3960,8 @@ msgid "Users added to this group will be superusers."
msgstr "Users added to this group will be superusers."
#: src/pages/providers/ldap/LDAPProviderForm.ts:86
msgid "Users in the selected group can do search queries."
msgstr "Users in the selected group can do search queries."
msgid "Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed."
msgstr "Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed."
#: src/pages/events/EventInfo.ts:108
msgid "Using flow"
@ -3956,7 +4003,7 @@ msgstr "Verify the user's email address by sending them a one-time-link. Can als
msgid "Version"
msgstr "Version"
#: src/pages/outposts/OutpostHealth.ts:60
#: src/pages/outposts/OutpostHealth.ts:59
msgid "Version: {0}"
msgstr "Version: {0}"
@ -3985,7 +4032,7 @@ msgstr "Wait (min)"
msgid "Warning"
msgstr "Warning"
#: src/pages/policies/PolicyListPage.ts:71
#: src/pages/policies/PolicyListPage.ts:72
msgid "Warning: Policy is not assigned."
msgstr "Warning: Policy is not assigned."
@ -4122,7 +4169,7 @@ msgstr "{0} is available!"
msgid "{0} unread"
msgstr "{0} unread"
#: src/pages/outposts/OutpostHealth.ts:59
#: src/pages/outposts/OutpostHealth.ts:58
msgid "{0}, should be {1}"
msgstr "{0}, should be {1}"

View File

@ -144,7 +144,7 @@ msgstr ""
msgid "Allow IDP-initiated logins"
msgstr ""
#: src/pages/sources/plex/PlexSourceForm.ts:150
#: src/pages/sources/plex/PlexSourceForm.ts:103
msgid "Allow friends to authenticate via Plex, even if you don't share any servers"
msgstr ""
@ -152,7 +152,7 @@ msgstr ""
msgid "Allow up to N occurrences in the HIBP database."
msgstr ""
#: src/pages/policies/PolicyListPage.ts:41
#: src/pages/policies/PolicyListPage.ts:42
msgid "Allow users to use Applications based on properties, enforce Password Criteria and selectively apply Stages."
msgstr ""
@ -164,7 +164,7 @@ msgstr ""
msgid "Allowed count"
msgstr ""
#: src/pages/sources/plex/PlexSourceForm.ts:155
#: src/pages/sources/plex/PlexSourceForm.ts:108
msgid "Allowed servers"
msgstr ""
@ -218,6 +218,18 @@ msgstr ""
msgid "Apps with most usage"
msgstr ""
#: src/pages/flows/FlowListPage.ts:146
msgid ""
"Are you sure you want to clear the flow cache?\n"
"This will cause all flows to be re-evaluated on their next usage."
msgstr ""
#: src/pages/policies/PolicyListPage.ts:165
msgid ""
"Are you sure you want to clear the policy cache?\n"
"This will cause all policies to be re-evaluated on their next usage."
msgstr ""
#: src/elements/forms/DeleteForm.ts:69
msgid "Are you sure you want to delete {0} {objName} ?"
msgstr ""
@ -250,7 +262,7 @@ msgstr ""
msgid "Assigned to application"
msgstr ""
#: src/pages/policies/PolicyListPage.ts:68
#: src/pages/policies/PolicyListPage.ts:69
msgid "Assigned to {0} objects."
msgstr ""
@ -282,7 +294,7 @@ msgid "Authentication"
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:231
#: src/pages/sources/plex/PlexSourceForm.ts:185
#: src/pages/sources/plex/PlexSourceForm.ts:190
#: src/pages/sources/saml/SAMLSourceForm.ts:243
msgid "Authentication flow"
msgstr ""
@ -528,6 +540,21 @@ msgstr ""
msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength."
msgstr ""
#: src/pages/flows/FlowListPage.ts:143
msgid "Clear Flow cache"
msgstr ""
#: src/pages/policies/PolicyListPage.ts:162
msgid "Clear Policy cache"
msgstr ""
#: src/pages/flows/FlowListPage.ts:138
#: src/pages/flows/FlowListPage.ts:150
#: src/pages/policies/PolicyListPage.ts:157
#: src/pages/policies/PolicyListPage.ts:169
msgid "Clear cache"
msgstr ""
#: src/elements/forms/HorizontalFormElement.ts:82
msgid "Click to change value"
msgstr ""
@ -538,7 +565,7 @@ msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts:107
#: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts:99
#: src/pages/sources/plex/PlexSourceForm.ts:141
#: src/pages/sources/plex/PlexSourceForm.ts:176
msgid "Client ID"
msgstr ""
@ -724,8 +751,8 @@ msgstr ""
#: src/pages/flows/BoundStagesList.ts:119
#: src/pages/flows/BoundStagesList.ts:146
#: src/pages/flows/BoundStagesList.ts:167
#: src/pages/flows/FlowListPage.ts:109
#: src/pages/flows/FlowListPage.ts:117
#: src/pages/flows/FlowListPage.ts:110
#: src/pages/flows/FlowListPage.ts:118
#: src/pages/groups/GroupListPage.ts:90
#: src/pages/groups/GroupListPage.ts:98
#: src/pages/outposts/OutpostListPage.ts:101
@ -735,8 +762,8 @@ msgstr ""
#: src/pages/policies/BoundPoliciesList.ts:162
#: src/pages/policies/BoundPoliciesList.ts:189
#: src/pages/policies/BoundPoliciesList.ts:210
#: src/pages/policies/PolicyListPage.ts:124
#: src/pages/policies/PolicyListPage.ts:133
#: src/pages/policies/PolicyListPage.ts:125
#: src/pages/policies/PolicyListPage.ts:134
#: src/pages/property-mappings/PropertyMappingListPage.ts:113
#: src/pages/property-mappings/PropertyMappingListPage.ts:122
#: src/pages/providers/ProviderListPage.ts:108
@ -776,7 +803,7 @@ msgstr ""
msgid "Create Certificate-Key Pair"
msgstr ""
#: src/pages/flows/FlowListPage.ts:112
#: src/pages/flows/FlowListPage.ts:113
msgid "Create Flow"
msgstr ""
@ -838,7 +865,7 @@ msgstr ""
#: src/pages/flows/BoundStagesList.ts:149
#: src/pages/outposts/ServiceConnectionListPage.ts:122
#: src/pages/policies/BoundPoliciesList.ts:192
#: src/pages/policies/PolicyListPage.ts:136
#: src/pages/policies/PolicyListPage.ts:137
#: src/pages/property-mappings/PropertyMappingListPage.ts:125
#: src/pages/providers/ProviderListPage.ts:120
#: src/pages/sources/SourcesListPage.ts:126
@ -890,11 +917,11 @@ msgstr ""
#: src/pages/crypto/CertificateKeyPairListPage.ts:86
#: src/pages/events/RuleListPage.ts:82
#: src/pages/events/TransportListPage.ts:86
#: src/pages/flows/FlowListPage.ts:86
#: src/pages/flows/FlowListPage.ts:87
#: src/pages/groups/GroupListPage.ts:81
#: src/pages/outposts/OutpostListPage.ts:87
#: src/pages/outposts/ServiceConnectionListPage.ts:101
#: src/pages/policies/PolicyListPage.ts:115
#: src/pages/policies/PolicyListPage.ts:116
#: src/pages/property-mappings/PropertyMappingListPage.ts:104
#: src/pages/providers/ProviderListPage.ts:99
#: src/pages/sources/SourcesListPage.ts:95
@ -963,7 +990,7 @@ msgid "Designates whether this user should be treated as active. Unselect this i
msgstr ""
#: src/pages/flows/FlowForm.ts:119
#: src/pages/flows/FlowListPage.ts:48
#: src/pages/flows/FlowListPage.ts:49
msgid "Designation"
msgstr ""
@ -1045,11 +1072,11 @@ msgstr ""
#: src/pages/crypto/CertificateKeyPairListPage.ts:74
#: src/pages/events/RuleListPage.ts:70
#: src/pages/events/TransportListPage.ts:74
#: src/pages/flows/FlowListPage.ts:74
#: src/pages/flows/FlowListPage.ts:75
#: src/pages/groups/GroupListPage.ts:69
#: src/pages/outposts/OutpostListPage.ts:75
#: src/pages/outposts/ServiceConnectionListPage.ts:89
#: src/pages/policies/PolicyListPage.ts:90
#: src/pages/policies/PolicyListPage.ts:91
#: src/pages/property-mappings/PropertyMappingListPage.ts:79
#: src/pages/providers/ProviderListPage.ts:87
#: src/pages/providers/ldap/LDAPProviderViewPage.ts:103
@ -1144,7 +1171,7 @@ msgstr ""
#: src/pages/policies/PolicyBindingForm.ts:199
#: src/pages/sources/ldap/LDAPSourceForm.ts:67
#: src/pages/sources/oauth/OAuthSourceForm.ts:134
#: src/pages/sources/plex/PlexSourceForm.ts:108
#: src/pages/sources/plex/PlexSourceForm.ts:143
#: src/pages/sources/saml/SAMLSourceForm.ts:67
msgid "Enabled"
msgstr ""
@ -1154,7 +1181,7 @@ msgid "Enrollment"
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:252
#: src/pages/sources/plex/PlexSourceForm.ts:206
#: src/pages/sources/plex/PlexSourceForm.ts:211
#: src/pages/sources/saml/SAMLSourceForm.ts:264
#: src/pages/stages/identification/IdentificationStageForm.ts:104
msgid "Enrollment flow"
@ -1221,12 +1248,12 @@ msgstr ""
msgid "Exception"
msgstr ""
#: src/pages/flows/FlowListPage.ts:98
#: src/pages/flows/FlowViewPage.ts:83
#: src/pages/flows/FlowListPage.ts:99
#: src/pages/flows/FlowViewPage.ts:75
msgid "Execute"
msgstr ""
#: src/pages/flows/FlowViewPage.ts:69
#: src/pages/flows/FlowViewPage.ts:61
msgid "Execute flow"
msgstr ""
@ -1273,7 +1300,7 @@ msgstr ""
msgid "Explicit Consent"
msgstr ""
#: src/pages/flows/FlowListPage.ts:101
#: src/pages/flows/FlowListPage.ts:102
msgid "Export"
msgstr ""
@ -1312,6 +1339,14 @@ msgstr ""
msgid "Failed sources"
msgstr ""
#: src/pages/flows/FlowListPage.ts:137
msgid "Failed to delete flow cache"
msgstr ""
#: src/pages/policies/PolicyListPage.ts:156
msgid "Failed to delete policy cache"
msgstr ""
#: src/elements/forms/DeleteForm.ts:46
msgid "Failed to delete {0}: {1}"
msgstr ""
@ -1354,7 +1389,7 @@ msgid "Fields a user can identify themselves with. If no fields are selected, th
msgstr ""
#: src/pages/flows/FlowImportForm.ts:34
#: src/pages/flows/FlowListPage.ts:79
#: src/pages/flows/FlowListPage.ts:80
msgid "Flow"
msgstr ""
@ -1363,19 +1398,19 @@ msgid "Flow Overview"
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:227
#: src/pages/sources/plex/PlexSourceForm.ts:181
#: src/pages/sources/plex/PlexSourceForm.ts:186
#: src/pages/sources/saml/SAMLSourceForm.ts:218
msgid "Flow settings"
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:249
#: src/pages/sources/plex/PlexSourceForm.ts:203
#: src/pages/sources/plex/PlexSourceForm.ts:208
#: src/pages/sources/saml/SAMLSourceForm.ts:261
msgid "Flow to use when authenticating existing users."
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:270
#: src/pages/sources/plex/PlexSourceForm.ts:224
#: src/pages/sources/plex/PlexSourceForm.ts:229
#: src/pages/sources/saml/SAMLSourceForm.ts:282
msgid "Flow to use when enrolling new users."
msgstr ""
@ -1407,12 +1442,12 @@ msgstr ""
#: src/interfaces/AdminInterface.ts:82
#: src/interfaces/AdminInterface.ts:84
#: src/pages/admin-overview/AdminOverviewPage.ts:61
#: src/pages/flows/FlowListPage.ts:28
#: src/pages/flows/FlowListPage.ts:29
#: src/pages/stages/StageListPage.ts:66
msgid "Flows"
msgstr ""
#: src/pages/flows/FlowListPage.ts:31
#: src/pages/flows/FlowListPage.ts:32
msgid "Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them."
msgstr ""
@ -1542,7 +1577,7 @@ msgstr ""
#: src/pages/providers/saml/SAMLProviderForm.ts:176
#: src/pages/sources/ldap/LDAPSourceForm.ts:165
#: src/pages/sources/ldap/LDAPSourceForm.ts:191
#: src/pages/sources/plex/PlexSourceForm.ts:168
#: src/pages/sources/plex/PlexSourceForm.ts:121
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts:114
#: src/pages/stages/identification/IdentificationStageForm.ts:83
#: src/pages/stages/password/PasswordStageForm.ts:84
@ -1563,7 +1598,7 @@ msgstr ""
msgid "Icon"
msgstr ""
#: src/pages/flows/FlowListPage.ts:46
#: src/pages/flows/FlowListPage.ts:47
#: src/pages/system-tasks/SystemTaskListPage.ts:54
#: src/pages/tokens/TokenListPage.ts:44
#: src/pages/user-settings/tokens/UserTokenForm.ts:49
@ -1596,12 +1631,12 @@ msgstr ""
msgid "Impersonate"
msgstr ""
#: src/pages/flows/FlowListPage.ts:122
#: src/pages/flows/FlowListPage.ts:130
#: src/pages/flows/FlowListPage.ts:123
#: src/pages/flows/FlowListPage.ts:131
msgid "Import"
msgstr ""
#: src/pages/flows/FlowListPage.ts:125
#: src/pages/flows/FlowListPage.ts:126
msgid "Import Flow"
msgstr ""
@ -1712,7 +1747,7 @@ msgstr ""
msgid "Last run"
msgstr ""
#: src/pages/outposts/OutpostHealth.ts:54
#: src/pages/outposts/OutpostHealth.ts:53
msgid "Last seen: {0}"
msgstr ""
@ -1738,21 +1773,21 @@ msgid "Library"
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:147
#: src/pages/sources/plex/PlexSourceForm.ts:121
#: src/pages/sources/plex/PlexSourceForm.ts:156
msgid "Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses"
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:153
#: src/pages/sources/plex/PlexSourceForm.ts:127
#: src/pages/sources/plex/PlexSourceForm.ts:162
msgid "Link to a user with identical username address. Can have security implications when a username is used with another source."
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:144
#: src/pages/sources/plex/PlexSourceForm.ts:118
#: src/pages/sources/plex/PlexSourceForm.ts:153
msgid "Link users on unique identifier"
msgstr ""
#: src/pages/sources/plex/PlexSourceForm.ts:173
#: src/pages/sources/plex/PlexSourceForm.ts:96
msgid "Load servers"
msgstr ""
@ -1817,8 +1852,8 @@ msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:219
#: src/pages/sources/oauth/OAuthSourceForm.ts:247
#: src/pages/sources/oauth/OAuthSourceForm.ts:268
#: src/pages/sources/plex/PlexSourceForm.ts:201
#: src/pages/sources/plex/PlexSourceForm.ts:222
#: src/pages/sources/plex/PlexSourceForm.ts:206
#: src/pages/sources/plex/PlexSourceForm.ts:227
#: src/pages/sources/saml/SAMLSourceForm.ts:124
#: src/pages/sources/saml/SAMLSourceForm.ts:238
#: src/pages/sources/saml/SAMLSourceForm.ts:259
@ -1957,7 +1992,7 @@ msgstr ""
#: src/pages/events/TransportListPage.ts:46
#: src/pages/flows/BoundStagesList.ts:39
#: src/pages/flows/FlowForm.ts:86
#: src/pages/flows/FlowListPage.ts:47
#: src/pages/flows/FlowListPage.ts:48
#: src/pages/groups/GroupForm.ts:58
#: src/pages/groups/GroupListPage.ts:45
#: src/pages/groups/MemberSelectModal.ts:45
@ -1966,7 +2001,7 @@ msgstr ""
#: src/pages/outposts/ServiceConnectionDockerForm.ts:51
#: src/pages/outposts/ServiceConnectionKubernetesForm.ts:52
#: src/pages/outposts/ServiceConnectionListPage.ts:53
#: src/pages/policies/PolicyListPage.ts:56
#: src/pages/policies/PolicyListPage.ts:57
#: src/pages/policies/dummy/DummyPolicyForm.ts:54
#: src/pages/policies/event_matcher/EventMatcherPolicyForm.ts:55
#: src/pages/policies/expiry/ExpiryPolicyForm.ts:54
@ -1993,7 +2028,7 @@ msgstr ""
#: src/pages/sources/ldap/LDAPSourceViewPage.ts:64
#: src/pages/sources/oauth/OAuthSourceForm.ts:108
#: src/pages/sources/oauth/OAuthSourceViewPage.ts:64
#: src/pages/sources/plex/PlexSourceForm.ts:93
#: src/pages/sources/plex/PlexSourceForm.ts:128
#: src/pages/sources/plex/PlexSourceViewPage.ts:63
#: src/pages/sources/saml/SAMLSourceForm.ts:52
#: src/pages/sources/saml/SAMLSourceViewPage.ts:66
@ -2355,15 +2390,15 @@ msgstr ""
#: src/interfaces/AdminInterface.ts:74
#: src/pages/admin-overview/AdminOverviewPage.ts:56
#: src/pages/flows/FlowListPage.ts:50
#: src/pages/policies/PolicyListPage.ts:38
#: src/pages/flows/FlowListPage.ts:51
#: src/pages/policies/PolicyListPage.ts:39
msgid "Policies"
msgstr ""
#: src/pages/policies/PolicyBindingForm.ts:108
#: src/pages/policies/PolicyBindingForm.ts:117
#: src/pages/policies/PolicyBindingForm.ts:148
#: src/pages/policies/PolicyListPage.ts:108
#: src/pages/policies/PolicyListPage.ts:109
msgid "Policy"
msgstr ""
@ -2488,7 +2523,7 @@ msgstr ""
#: src/pages/providers/proxy/ProxyProviderForm.ts:123
#: src/pages/providers/saml/SAMLProviderForm.ts:77
#: src/pages/sources/oauth/OAuthSourceForm.ts:163
#: src/pages/sources/plex/PlexSourceForm.ts:137
#: src/pages/sources/plex/PlexSourceForm.ts:172
#: src/pages/sources/saml/SAMLSourceForm.ts:74
msgid "Protocol settings"
msgstr ""
@ -2619,7 +2654,7 @@ msgid "Regular expressions for which authentication is not required. Each new li
msgstr ""
#: src/pages/applications/ApplicationViewPage.ts:62
#: src/pages/flows/FlowViewPage.ts:64
#: src/pages/flows/FlowViewPage.ts:56
msgid "Related"
msgstr ""
@ -2796,7 +2831,7 @@ msgstr ""
msgid "Select which scopes can be used by the client. The client stil has to specify the scope to access the data."
msgstr ""
#: src/pages/sources/plex/PlexSourceForm.ts:167
#: src/pages/sources/plex/PlexSourceForm.ts:120
msgid "Select which server a user has to be a member of to be allowed to authenticate."
msgstr ""
@ -2936,7 +2971,7 @@ msgstr ""
#: src/pages/flows/FlowForm.ts:99
#: src/pages/sources/ldap/LDAPSourceForm.ts:58
#: src/pages/sources/oauth/OAuthSourceForm.ts:114
#: src/pages/sources/plex/PlexSourceForm.ts:99
#: src/pages/sources/plex/PlexSourceForm.ts:134
#: src/pages/sources/saml/SAMLSourceForm.ts:58
msgid "Slug"
msgstr ""
@ -3013,7 +3048,7 @@ msgid "Stage-specific settings"
msgstr ""
#: src/interfaces/AdminInterface.ts:87
#: src/pages/flows/FlowListPage.ts:49
#: src/pages/flows/FlowListPage.ts:50
#: src/pages/stages/StageListPage.ts:44
#: src/pages/stages/prompt/PromptListPage.ts:50
msgid "Stages"
@ -3077,6 +3112,14 @@ msgstr ""
msgid "Successful"
msgstr ""
#: src/pages/flows/FlowListPage.ts:136
msgid "Successfully cleared flow cache"
msgstr ""
#: src/pages/policies/PolicyListPage.ts:155
msgid "Successfully cleared policy cache"
msgstr ""
#: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts:63
msgid "Successfully copied TOTP Config."
msgstr ""
@ -3401,14 +3444,14 @@ msgid "Template"
msgstr ""
#: src/pages/events/TransportListPage.ts:62
#: src/pages/policies/PolicyListPage.ts:95
#: src/pages/policies/PolicyListPage.ts:103
#: src/pages/policies/PolicyListPage.ts:96
#: src/pages/policies/PolicyListPage.ts:104
#: src/pages/property-mappings/PropertyMappingListPage.ts:84
#: src/pages/property-mappings/PropertyMappingListPage.ts:92
msgid "Test"
msgstr ""
#: src/pages/policies/PolicyListPage.ts:98
#: src/pages/policies/PolicyListPage.ts:99
msgid "Test Policy"
msgstr ""
@ -3425,7 +3468,7 @@ msgid "The URL \"{0}\" was not found."
msgstr ""
#: src/pages/providers/proxy/ProxyProviderForm.ts:131
msgid "The external URL you'll access the application at"
msgid "The external URL you'll access the application at. Include any non-standard port."
msgstr ""
#: src/pages/policies/dummy/DummyPolicyForm.ts:88
@ -3556,7 +3599,7 @@ msgstr ""
#: src/pages/flows/BoundStagesList.ts:40
#: src/pages/outposts/OutpostForm.ts:58
#: src/pages/outposts/ServiceConnectionListPage.ts:54
#: src/pages/policies/PolicyListPage.ts:57
#: src/pages/policies/PolicyListPage.ts:58
#: src/pages/property-mappings/PropertyMappingListPage.ts:55
#: src/pages/providers/ProviderListPage.ts:55
#: src/pages/sources/SourcesListPage.ts:53
@ -3632,7 +3675,7 @@ msgstr ""
#: src/pages/events/TransportListPage.ts:66
#: src/pages/flows/BoundStagesList.ts:53
#: src/pages/flows/BoundStagesList.ts:71
#: src/pages/flows/FlowListPage.ts:66
#: src/pages/flows/FlowListPage.ts:67
#: src/pages/groups/GroupListPage.ts:61
#: src/pages/outposts/OutpostListPage.ts:67
#: src/pages/outposts/ServiceConnectionListPage.ts:76
@ -3640,7 +3683,7 @@ msgstr ""
#: src/pages/policies/BoundPoliciesList.ts:88
#: src/pages/policies/BoundPoliciesList.ts:103
#: src/pages/policies/BoundPoliciesList.ts:129
#: src/pages/policies/PolicyListPage.ts:77
#: src/pages/policies/PolicyListPage.ts:78
#: src/pages/property-mappings/PropertyMappingListPage.ts:66
#: src/pages/providers/ProviderListPage.ts:74
#: src/pages/providers/ldap/LDAPProviderViewPage.ts:93
@ -3678,7 +3721,7 @@ msgstr ""
msgid "Update Certificate-Key Pair"
msgstr ""
#: src/pages/flows/FlowListPage.ts:69
#: src/pages/flows/FlowListPage.ts:70
msgid "Update Flow"
msgstr ""
@ -3756,7 +3799,7 @@ msgstr ""
#: src/pages/flows/BoundStagesList.ts:56
#: src/pages/outposts/ServiceConnectionListPage.ts:79
#: src/pages/policies/BoundPoliciesList.ts:71
#: src/pages/policies/PolicyListPage.ts:80
#: src/pages/policies/PolicyListPage.ts:81
#: src/pages/property-mappings/PropertyMappingListPage.ts:69
#: src/pages/providers/ProviderListPage.ts:77
#: src/pages/sources/SourcesListPage.ts:73
@ -3790,12 +3833,12 @@ msgid "Use global settings"
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:150
#: src/pages/sources/plex/PlexSourceForm.ts:124
#: src/pages/sources/plex/PlexSourceForm.ts:159
msgid "Use the user's email address, but deny enrollment when the email address already exists."
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:156
#: src/pages/sources/plex/PlexSourceForm.ts:130
#: src/pages/sources/plex/PlexSourceForm.ts:165
msgid "Use the user's username, but deny enrollment when the username already exists."
msgstr ""
@ -3844,7 +3887,7 @@ msgid "User fields"
msgstr ""
#: src/pages/sources/oauth/OAuthSourceForm.ts:139
#: src/pages/sources/plex/PlexSourceForm.ts:113
#: src/pages/sources/plex/PlexSourceForm.ts:148
msgid "User matching mode"
msgstr ""
@ -3905,7 +3948,7 @@ msgid "Users added to this group will be superusers."
msgstr ""
#: src/pages/providers/ldap/LDAPProviderForm.ts:86
msgid "Users in the selected group can do search queries."
msgid "Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed."
msgstr ""
#: src/pages/events/EventInfo.ts:108
@ -3948,7 +3991,7 @@ msgstr ""
msgid "Version"
msgstr ""
#: src/pages/outposts/OutpostHealth.ts:60
#: src/pages/outposts/OutpostHealth.ts:59
msgid "Version: {0}"
msgstr ""
@ -3977,7 +4020,7 @@ msgstr ""
msgid "Warning"
msgstr ""
#: src/pages/policies/PolicyListPage.ts:71
#: src/pages/policies/PolicyListPage.ts:72
msgid "Warning: Policy is not assigned."
msgstr ""
@ -4112,7 +4155,7 @@ msgstr ""
msgid "{0} unread"
msgstr ""
#: src/pages/outposts/OutpostHealth.ts:59
#: src/pages/outposts/OutpostHealth.ts:58
msgid "{0}, should be {1}"
msgstr ""

View File

@ -6,6 +6,7 @@ import { TablePage } from "../../elements/table/TablePage";
import "../../elements/buttons/SpinnerButton";
import "../../elements/forms/DeleteForm";
import "../../elements/forms/ModalForm";
import "../../elements/forms/ConfirmationForm";
import "./FlowForm";
import "./FlowImportForm";
import { TableColumn } from "../../elements/table/Table";
@ -132,6 +133,24 @@ export class FlowListPage extends TablePage<Flow> {
</button>
</ak-forms-modal>
${super.renderToolbar()}
`;
<ak-forms-confirm
successMessage=${t`Successfully cleared flow cache`}
errorMessage=${t`Failed to delete flow cache`}
action=${t`Clear cache`}
.onConfirm=${() => {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesCacheClear();
}}>
<span slot="header">
${t`Clear Flow cache`}
</span>
<p slot="body">
${t`Are you sure you want to clear the flow cache?
This will cause all flows to be re-evaluated on their next usage.`}
</p>
<button slot="trigger" class="pf-c-button pf-m-secondary" type="button">
${t`Clear cache`}
</button>
<div slot="modal"></div>
</ak-forms-confirm>`;
}
}

View File

@ -8,6 +8,7 @@ import "../../elements/buttons/SpinnerButton";
import "../../elements/forms/DeleteForm";
import "../../elements/forms/ModalForm";
import "../../elements/forms/ProxyForm";
import "../../elements/forms/ConfirmationForm";
import "./PolicyTestForm";
import { TableColumn } from "../../elements/table/Table";
import { until } from "lit-html/directives/until";
@ -150,7 +151,26 @@ export class PolicyListPage extends TablePage<Policy> {
}), html`<ak-spinner></ak-spinner>`)}
</ul>
</ak-dropdown>
${super.renderToolbar()}`;
${super.renderToolbar()}
<ak-forms-confirm
successMessage=${t`Successfully cleared policy cache`}
errorMessage=${t`Failed to delete policy cache`}
action=${t`Clear cache`}
.onConfirm=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesAllCacheClear();
}}>
<span slot="header">
${t`Clear Policy cache`}
</span>
<p slot="body">
${t`Are you sure you want to clear the policy cache?
This will cause all policies to be re-evaluated on their next usage.`}
</p>
<button slot="trigger" class="pf-c-button pf-m-secondary" type="button">
${t`Clear cache`}
</button>
<div slot="modal"></div>
</ak-forms-confirm>`;
}
}

View File

@ -125,7 +125,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
?required=${true}
name="externalHost">
<input type="text" value="${ifDefined(this.instance?.externalHost)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`The external URL you'll access the application at`}</p>
<p class="pf-c-form__helper-text">${t`The external URL you'll access the application at. Include any non-standard port.`}</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="forwardAuthMode">
<div class="pf-c-check">

View File

@ -46,7 +46,7 @@ export class PlexSourceForm extends ModelForm<PlexSource, string> {
}
send = (data: PlexSource): Promise<PlexSource> => {
data.plexToken = this.plexToken;
data.plexToken = this.plexToken || "";
if (this.instance?.slug) {
return new SourcesApi(DEFAULT_CONFIG).sourcesPlexUpdate({
slug: this.instance.slug,

View File

@ -12,11 +12,11 @@ This installation method is for test-setups and small-scale productive setups.
## Preparation
Download the latest `docker-compose.yml` from [here](https://raw.githubusercontent.com/goauthentik/authentik/version/2021.5.3/docker-compose.yml). Place it in a directory of your choice.
Download the latest `docker-compose.yml` from [here](https://raw.githubusercontent.com/goauthentik/authentik/version/2021.5.4/docker-compose.yml). Place it in a directory of your choice.
To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env`
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.5.3 >> .env`
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.5.4 >> .env`
If this is a fresh authentik install run the following commands to generate a password:

View File

@ -11,7 +11,7 @@ version: "3.5"
services:
authentik_proxy:
image: ghcr.io/goauthentik/proxy:2021.5.3
image: ghcr.io/goauthentik/proxy:2021.5.4
ports:
- 4180:4180
- 4443:4443
@ -21,7 +21,7 @@ services:
AUTHENTIK_TOKEN: token-generated-by-authentik
# Or, for the LDAP Outpost
authentik_proxy:
image: ghcr.io/goauthentik/ldap:2021.5.3
image: ghcr.io/goauthentik/ldap:2021.5.4
ports:
- 389:3389
environment:

View File

@ -14,7 +14,7 @@ metadata:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.5.3
app.kubernetes.io/version: 2021.5.4
name: authentik-outpost-api
stringData:
authentik_host: "__AUTHENTIK_URL__"
@ -29,7 +29,7 @@ metadata:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.5.3
app.kubernetes.io/version: 2021.5.4
name: authentik-outpost
spec:
ports:
@ -54,7 +54,7 @@ metadata:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.5.3
app.kubernetes.io/version: 2021.5.4
name: authentik-outpost
spec:
selector:
@ -62,14 +62,14 @@ spec:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.5.3
app.kubernetes.io/version: 2021.5.4
template:
metadata:
labels:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.5.3
app.kubernetes.io/version: 2021.5.4
spec:
containers:
- env:
@ -88,7 +88,7 @@ spec:
secretKeyRef:
key: authentik_host_insecure
name: authentik-outpost-api
image: ghcr.io/goauthentik/proxy:2021.5.3
image: ghcr.io/goauthentik/proxy:2021.5.4
name: proxy
ports:
- containerPort: 4180
@ -110,7 +110,7 @@ metadata:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.5.3
app.kubernetes.io/version: 2021.5.4
name: authentik-outpost
spec:
rules: