Compare commits
148 Commits
beta-upgra
...
smusali/qr
Author | SHA1 | Date | |
---|---|---|---|
8daa8e1ca1 | |||
0f78db65a9 | |||
4e741416d8 | |||
87f3484be4 | |||
0b25c612c0 | |||
38356ac1dc | |||
f0619814f9 | |||
d09bee7bf9 | |||
81c22fa22a | |||
47a916ad5e | |||
4a41811465 | |||
8dbfafe612 | |||
b6160cf759 | |||
4118a34ed9 | |||
9f78d34719 | |||
21d5059876 | |||
4093b2b71f | |||
0d974dd0e1 | |||
0138aef70a | |||
d063fcb117 | |||
3e64409fdb | |||
ce96600adb | |||
e8c2aabad0 | |||
5e5a74eebf | |||
fa87519536 | |||
60e911baf8 | |||
a8067c1f0d | |||
f8ca498c77 | |||
489a680ff4 | |||
6c3a1795dd | |||
5b0cc3672b | |||
1ce482911b | |||
c869f3a3e2 | |||
2236eaccbc | |||
09fea420dd | |||
5c3295f4fd | |||
41de8f1191 | |||
0deaf25b1f | |||
47d5fc26cc | |||
9a996e7176 | |||
554a26442d | |||
573517bf0a | |||
2cd68dfa87 | |||
8029a13be1 | |||
22ee587e9f | |||
7c9659dd24 | |||
1ba734cc7b | |||
7c43c1a05b | |||
4230d8ee20 | |||
d590c1cdc4 | |||
ac843bb8ce | |||
71ba5be55f | |||
7358553333 | |||
d53d212377 | |||
9a39696367 | |||
6766b12bd1 | |||
c1404285bb | |||
8bba8422d7 | |||
ffcf8b110b | |||
894b4e3ca7 | |||
7c7957f160 | |||
36340d0960 | |||
9f9a71f3d6 | |||
0d0bb1a559 | |||
e3e1fbad3f | |||
91f0d31175 | |||
8af9eca24c | |||
1ee78ff1f2 | |||
618a61af04 | |||
44341f0224 | |||
444deae637 | |||
ba0e64d304 | |||
05fd539db5 | |||
3dd200dbe5 | |||
411ef239f6 | |||
25840ce04e | |||
bb64fb1130 | |||
5d5938c412 | |||
d8de60b053 | |||
b4a3b266b3 | |||
65c02c9ad5 | |||
e4d8612088 | |||
c2b26718f6 | |||
300901e93f | |||
33386b126c | |||
1bdc0b5e65 | |||
a308cfedf3 | |||
3236f57f7b | |||
0a4792cf95 | |||
6af85b002f | |||
30d2c4fcc6 | |||
6900ffffd8 | |||
873aaf85f9 | |||
9c69f67778 | |||
6cf7a72831 | |||
7e3b325929 | |||
b916b612c7 | |||
b7c5fc3f1e | |||
a3ac5ec183 | |||
d30379ba93 | |||
12815526c1 | |||
ed2f0a2d5e | |||
536d776d02 | |||
f70d6432e7 | |||
cc08bfb18b | |||
79dcc30778 | |||
68a1bcf233 | |||
cd7de4c0b9 | |||
3195a75b9a | |||
886d7832df | |||
a3595a36d2 | |||
28ac00798c | |||
f4b0d6e85c | |||
daa3c91afc | |||
5eba598584 | |||
a6b16ecc68 | |||
a41924939b | |||
0afd3b121e | |||
a58374f065 | |||
8faec99bd6 | |||
6c27a2f783 | |||
78e4c313b5 | |||
f8140e1543 | |||
4405a04b0b | |||
7eb5fa6a24 | |||
216e8aff64 | |||
c91bbecb7b | |||
084b3eb039 | |||
557aadecc0 | |||
33b8c45f5c | |||
52132112f6 | |||
ff1510dedc | |||
c3398004ff | |||
47f09ac285 | |||
259c87fa37 | |||
80bb6c6274 | |||
f8c2fc2ead | |||
ea84ee0222 | |||
a695ffc224 | |||
9e22f007a8 | |||
6299fc7f81 | |||
a032fd529b | |||
ec78e56fbd | |||
ad7dedb61f | |||
8356ceaead | |||
228197ea5e | |||
27d3d4a534 | |||
f2dcbf9b1d |
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 2023.4.1
|
||||
current_version = 2023.5.2
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
|
||||
|
2
.github/workflows/ci-main.yml
vendored
2
.github/workflows/ci-main.yml
vendored
@ -112,7 +112,7 @@ jobs:
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- name: Create k8s Kind Cluster
|
||||
uses: helm/kind-action@v1.5.0
|
||||
uses: helm/kind-action@v1.7.0
|
||||
- name: run integration
|
||||
run: |
|
||||
poetry run coverage run manage.py test tests/integration
|
||||
|
5
.vscode/extensions.json
vendored
5
.vscode/extensions.json
vendored
@ -1,10 +1,11 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"EditorConfig.EditorConfig",
|
||||
"bashmish.es6-string-css",
|
||||
"bpruitt-goddard.mermaid-markdown-syntax-highlighting",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"EditorConfig.EditorConfig",
|
||||
"esbenp.prettier-vscode",
|
||||
"github.vscode-github-actions",
|
||||
"golang.go",
|
||||
"Gruntfuggly.todo-tree",
|
||||
"mechatroner.rainbow-csv",
|
||||
@ -15,6 +16,6 @@
|
||||
"ms-python.vscode-pylance",
|
||||
"redhat.vscode-yaml",
|
||||
"Tobermory.es6-string-html",
|
||||
"unifiedjs.vscode-mdx"
|
||||
"unifiedjs.vscode-mdx",
|
||||
]
|
||||
}
|
||||
|
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@ -48,5 +48,10 @@
|
||||
"ignoreCase": false
|
||||
}
|
||||
],
|
||||
"go.testFlags": ["-count=1"]
|
||||
"go.testFlags": [
|
||||
"-count=1"
|
||||
],
|
||||
"github-actions.workflows.pinned.workflows": [
|
||||
".github/workflows/ci-main.yml"
|
||||
]
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ COPY ./SECURITY.md /work/
|
||||
|
||||
ENV NODE_ENV=production
|
||||
WORKDIR /work/website
|
||||
RUN npm ci && npm run build-docs-only
|
||||
RUN npm ci --include=dev && npm run build-docs-only
|
||||
|
||||
# Stage 2: Build webui
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/node:20 as web-builder
|
||||
@ -17,7 +17,7 @@ COPY ./website /work/website/
|
||||
|
||||
ENV NODE_ENV=production
|
||||
WORKDIR /work/web
|
||||
RUN npm ci && npm run build
|
||||
RUN npm ci --include=dev && npm run build
|
||||
|
||||
# Stage 3: Poetry to requirements.txt export
|
||||
FROM docker.io/python:3.11.3-slim-bullseye AS poetry-locker
|
||||
|
@ -6,8 +6,8 @@ Authentik takes security very seriously. We follow the rules of [responsible dis
|
||||
|
||||
| Version | Supported |
|
||||
| --------- | ------------------ |
|
||||
| 2023.2.x | :white_check_mark: |
|
||||
| 2023.3.x | :white_check_mark: |
|
||||
| 2023.4.x | :white_check_mark: |
|
||||
| 2023.5.x | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
from os import environ
|
||||
from typing import Optional
|
||||
|
||||
__version__ = "2023.4.1"
|
||||
__version__ = "2023.5.2"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""core Configs API"""
|
||||
from os import path
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
@ -63,7 +63,7 @@ class ConfigView(APIView):
|
||||
"""Get all capabilities this server instance supports"""
|
||||
caps = []
|
||||
deb_test = settings.DEBUG or settings.TEST
|
||||
if path.ismount(settings.MEDIA_ROOT) or deb_test:
|
||||
if Path(settings.MEDIA_ROOT).is_mount() or deb_test:
|
||||
caps.append(Capabilities.CAN_SAVE_MEDIA)
|
||||
if GEOIP_READER.enabled:
|
||||
caps.append(Capabilities.CAN_GEO_IP)
|
||||
|
@ -11,7 +11,7 @@ from rest_framework.serializers import ListSerializer, ModelSerializer
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik.api.decorators import permission_required
|
||||
from authentik.blueprints.models import BlueprintInstance, BlueprintRetrievalFailed
|
||||
from authentik.blueprints.models import BlueprintInstance
|
||||
from authentik.blueprints.v1.importer import Importer
|
||||
from authentik.blueprints.v1.tasks import apply_blueprint, blueprints_find_dict
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
@ -35,11 +35,12 @@ class BlueprintInstanceSerializer(ModelSerializer):
|
||||
"""Info about a single blueprint instance file"""
|
||||
|
||||
def validate_path(self, path: str) -> str:
|
||||
"""Ensure the path specified is retrievable"""
|
||||
try:
|
||||
BlueprintInstance(path=path).retrieve()
|
||||
except BlueprintRetrievalFailed as exc:
|
||||
raise ValidationError(exc) from exc
|
||||
"""Ensure the path (if set) specified is retrievable"""
|
||||
if path == "":
|
||||
return path
|
||||
files: list[dict] = blueprints_find_dict.delay().get()
|
||||
if path not in [file["path"] for file in files]:
|
||||
raise ValidationError(_("Blueprint file does not exist"))
|
||||
return path
|
||||
|
||||
def validate_content(self, content: str) -> str:
|
||||
|
@ -10,7 +10,7 @@ from rest_framework.serializers import Serializer
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT, is_model_allowed
|
||||
from authentik.blueprints.v1.meta.registry import registry
|
||||
from authentik.blueprints.v1.meta.registry import BaseMetaModel, registry
|
||||
from authentik.lib.models import SerializerModel
|
||||
|
||||
LOGGER = get_logger()
|
||||
@ -74,14 +74,18 @@ class Command(BaseCommand):
|
||||
def build(self):
|
||||
"""Build all models into the schema"""
|
||||
for model in registry.get_models():
|
||||
if model._meta.abstract:
|
||||
continue
|
||||
if not is_model_allowed(model):
|
||||
continue
|
||||
model_instance: Model = model()
|
||||
if not isinstance(model_instance, SerializerModel):
|
||||
continue
|
||||
serializer = model_instance.serializer(
|
||||
if issubclass(model, BaseMetaModel):
|
||||
serializer_class = model.serializer()
|
||||
else:
|
||||
if model._meta.abstract:
|
||||
continue
|
||||
if not is_model_allowed(model):
|
||||
continue
|
||||
model_instance: Model = model()
|
||||
if not isinstance(model_instance, SerializerModel):
|
||||
continue
|
||||
serializer_class = model_instance.serializer
|
||||
serializer = serializer_class(
|
||||
context={
|
||||
SERIALIZER_CONTEXT_BLUEPRINT: False,
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ def check_blueprint_v1_file(BlueprintInstance: type, path: Path):
|
||||
enabled=True,
|
||||
managed_models=[],
|
||||
last_applied_hash="",
|
||||
metadata=metadata,
|
||||
metadata=metadata or {},
|
||||
)
|
||||
instance.save()
|
||||
|
||||
|
@ -11,31 +11,37 @@ metadata:
|
||||
entries:
|
||||
- model: authentik_core.token
|
||||
identifiers:
|
||||
identifier: %(uid)s-token
|
||||
identifier: "%(uid)s-token"
|
||||
attrs:
|
||||
key: %(uid)s
|
||||
user: %(user)s
|
||||
key: "%(uid)s"
|
||||
user: "%(user)s"
|
||||
intent: api
|
||||
- model: authentik_core.application
|
||||
identifiers:
|
||||
slug: %(uid)s-app
|
||||
slug: "%(uid)s-app"
|
||||
attrs:
|
||||
name: %(uid)s-app
|
||||
name: "%(uid)s-app"
|
||||
icon: https://goauthentik.io/img/icon.png
|
||||
- model: authentik_sources_oauth.oauthsource
|
||||
identifiers:
|
||||
slug: %(uid)s-source
|
||||
slug: "%(uid)s-source"
|
||||
attrs:
|
||||
name: %(uid)s-source
|
||||
name: "%(uid)s-source"
|
||||
provider_type: azuread
|
||||
consumer_key: %(uid)s
|
||||
consumer_secret: %(uid)s
|
||||
consumer_key: "%(uid)s"
|
||||
consumer_secret: "%(uid)s"
|
||||
icon: https://goauthentik.io/img/icon.png
|
||||
- model: authentik_flows.flow
|
||||
identifiers:
|
||||
slug: %(uid)s-flow
|
||||
slug: "%(uid)s-flow"
|
||||
attrs:
|
||||
name: %(uid)s-flow
|
||||
title: %(uid)s-flow
|
||||
name: "%(uid)s-flow"
|
||||
title: "%(uid)s-flow"
|
||||
designation: authentication
|
||||
background: https://goauthentik.io/img/icon.png
|
||||
- model: authentik_core.user
|
||||
identifiers:
|
||||
username: "%(uid)s"
|
||||
attrs:
|
||||
name: "%(uid)s"
|
||||
password: "%(uid)s"
|
||||
|
@ -32,6 +32,29 @@ class TestBlueprintOCI(TransactionTestCase):
|
||||
"foo",
|
||||
)
|
||||
|
||||
def test_successful_port(self):
|
||||
"""Successful retrieval with custom port"""
|
||||
with Mocker() as mocker:
|
||||
mocker.get(
|
||||
"https://ghcr.io:1234/v2/goauthentik/blueprints/test/manifests/latest",
|
||||
json={
|
||||
"layers": [
|
||||
{
|
||||
"mediaType": OCI_MEDIA_TYPE,
|
||||
"digest": "foo",
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
mocker.get("https://ghcr.io:1234/v2/goauthentik/blueprints/test/blobs/foo", text="foo")
|
||||
|
||||
self.assertEqual(
|
||||
BlueprintInstance(
|
||||
path="oci://ghcr.io:1234/goauthentik/blueprints/test:latest"
|
||||
).retrieve(),
|
||||
"foo",
|
||||
)
|
||||
|
||||
def test_manifests_error(self):
|
||||
"""Test manifests request erroring"""
|
||||
with Mocker() as mocker:
|
||||
|
@ -2,7 +2,7 @@
|
||||
from django.test import TransactionTestCase
|
||||
|
||||
from authentik.blueprints.v1.importer import Importer
|
||||
from authentik.core.models import Application, Token
|
||||
from authentik.core.models import Application, Token, User
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.lib.generators import generate_id
|
||||
@ -45,3 +45,9 @@ class TestBlueprintsV1ConditionalFields(TransactionTestCase):
|
||||
flow = Flow.objects.filter(slug=f"{self.uid}-flow").first()
|
||||
self.assertIsNotNone(flow)
|
||||
self.assertEqual(flow.background, "https://goauthentik.io/img/icon.png")
|
||||
|
||||
def test_user(self):
|
||||
"""Test user"""
|
||||
user: User = User.objects.filter(username=self.uid).first()
|
||||
self.assertIsNotNone(user)
|
||||
self.assertTrue(user.check_password(self.uid))
|
||||
|
@ -39,11 +39,16 @@ class BlueprintOCIClient:
|
||||
self.logger = get_logger().bind(url=self.sanitized_url)
|
||||
|
||||
self.ref = "latest"
|
||||
# Remove the leading slash of the path to convert it to an image name
|
||||
path = self.url.path[1:]
|
||||
if ":" in self.url.path:
|
||||
if ":" in path:
|
||||
# if there's a colon in the path, use everything after it as a ref
|
||||
path, _, self.ref = path.partition(":")
|
||||
base_url = f"https://{self.url.hostname}"
|
||||
if self.url.port:
|
||||
base_url += f":{self.url.port}"
|
||||
self.client = NewClient(
|
||||
f"https://{self.url.hostname}",
|
||||
base_url,
|
||||
WithUserAgent(authentik_user_agent()),
|
||||
WithUsernamePassword(self.url.username, self.url.password),
|
||||
WithDefaultName(path),
|
||||
|
@ -184,9 +184,9 @@ def apply_blueprint(self: MonitoredTask, instance_pk: str):
|
||||
instance: Optional[BlueprintInstance] = None
|
||||
try:
|
||||
instance: BlueprintInstance = BlueprintInstance.objects.filter(pk=instance_pk).first()
|
||||
self.set_uid(slugify(instance.name))
|
||||
if not instance or not instance.enabled:
|
||||
return
|
||||
self.set_uid(slugify(instance.name))
|
||||
blueprint_content = instance.retrieve()
|
||||
file_hash = sha512(blueprint_content.encode()).hexdigest()
|
||||
importer = Importer(blueprint_content, instance.context)
|
||||
|
@ -33,7 +33,7 @@ class TokenSerializer(ManagedSerializer, ModelSerializer):
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
if SERIALIZER_CONTEXT_BLUEPRINT in self.context:
|
||||
self.fields["key"] = CharField()
|
||||
self.fields["key"] = CharField(required=False)
|
||||
|
||||
def validate(self, attrs: dict[Any, str]) -> dict[Any, str]:
|
||||
"""Ensure only API or App password tokens are created."""
|
||||
|
@ -51,6 +51,7 @@ from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.admin.api.metrics import CoordinateSerializer
|
||||
from authentik.api.decorators import permission_required
|
||||
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.utils import LinkSerializer, PassiveSerializer, is_dict
|
||||
from authentik.core.middleware import (
|
||||
@ -106,12 +107,36 @@ class UserSerializer(ModelSerializer):
|
||||
avatar = CharField(read_only=True)
|
||||
attributes = JSONField(validators=[is_dict], required=False)
|
||||
groups = PrimaryKeyRelatedField(
|
||||
allow_empty=True, many=True, source="ak_groups", queryset=Group.objects.all()
|
||||
allow_empty=True, many=True, source="ak_groups", queryset=Group.objects.all(), default=list
|
||||
)
|
||||
groups_obj = ListSerializer(child=UserGroupSerializer(), read_only=True, source="ak_groups")
|
||||
uid = CharField(read_only=True)
|
||||
username = CharField(max_length=150, validators=[UniqueValidator(queryset=User.objects.all())])
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if SERIALIZER_CONTEXT_BLUEPRINT in self.context:
|
||||
self.fields["password"] = CharField(required=False)
|
||||
|
||||
def create(self, validated_data: dict) -> User:
|
||||
"""If this serializer is used in the blueprint context, we allow for
|
||||
directly setting a password. However should be done via the `set_password`
|
||||
method instead of directly setting it like rest_framework."""
|
||||
instance: User = super().create(validated_data)
|
||||
if SERIALIZER_CONTEXT_BLUEPRINT in self.context and "password" in validated_data:
|
||||
instance.set_password(validated_data["password"])
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
def update(self, instance: User, validated_data: dict) -> User:
|
||||
"""Same as `create` above, set the password directly if we're in a blueprint
|
||||
context"""
|
||||
instance = super().update(instance, validated_data)
|
||||
if SERIALIZER_CONTEXT_BLUEPRINT in self.context and "password" in validated_data:
|
||||
instance.set_password(validated_data["password"])
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
def validate_path(self, path: str) -> str:
|
||||
"""Validate path"""
|
||||
if path[:1] == "/" or path[-1] == "/":
|
||||
|
@ -5,7 +5,6 @@ from typing import Any, Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from deepmerge import always_merger
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.hashers import check_password
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.contrib.auth.models import UserManager as DjangoUserManager
|
||||
@ -33,6 +32,7 @@ from authentik.lib.models import (
|
||||
)
|
||||
from authentik.lib.utils.http import get_client_ip
|
||||
from authentik.policies.models import PolicyBindingModel
|
||||
from authentik.root.install_id import get_install_id
|
||||
|
||||
LOGGER = get_logger()
|
||||
USER_ATTRIBUTE_DEBUG = "goauthentik.io/user/debug"
|
||||
@ -217,7 +217,7 @@ class User(SerializerModel, GuardianUserMixin, AbstractUser):
|
||||
@property
|
||||
def uid(self) -> str:
|
||||
"""Generate a globally unique UID, based on the user ID and the hashed secret key"""
|
||||
return sha256(f"{self.id}-{settings.SECRET_KEY}".encode("ascii")).hexdigest()
|
||||
return sha256(f"{self.id}-{get_install_id()}".encode("ascii")).hexdigest()
|
||||
|
||||
def locale(self, request: Optional[HttpRequest] = None) -> str:
|
||||
"""Get the locale the user has configured"""
|
||||
|
@ -28,7 +28,7 @@ from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_GET, SESSI
|
||||
from authentik.lib.utils.urls import redirect_with_qs
|
||||
from authentik.lib.views import bad_request_message
|
||||
from authentik.policies.denied import AccessDeniedResponse
|
||||
from authentik.policies.utils import delete_none_keys
|
||||
from authentik.policies.utils import delete_none_values
|
||||
from authentik.stages.password import BACKEND_INBUILT
|
||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
|
||||
@ -329,7 +329,7 @@ class SourceFlowManager:
|
||||
)
|
||||
],
|
||||
**{
|
||||
PLAN_CONTEXT_PROMPT: delete_none_keys(self.enroll_info),
|
||||
PLAN_CONTEXT_PROMPT: delete_none_values(self.enroll_info),
|
||||
PLAN_CONTEXT_USER_PATH: self.source.get_user_path(),
|
||||
},
|
||||
)
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
{% block head %}
|
||||
<script src="{% static 'dist/user/UserInterface.js' %}?version={{ version }}" type="module"></script>
|
||||
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: dark)">
|
||||
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: dark)">
|
||||
<link rel="icon" href="{{ tenant.branding_favicon }}">
|
||||
<link rel="shortcut icon" href="{{ tenant.branding_favicon }}">
|
||||
{% include "base/header_js.html" %}
|
||||
|
@ -7,7 +7,6 @@ from smtplib import SMTPException
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.db.models import Count, ExpressionWrapper, F
|
||||
from django.db.models.fields import DurationField
|
||||
@ -207,9 +206,7 @@ class Event(SerializerModel, ExpiringModel):
|
||||
self.user = get_user(user)
|
||||
return self
|
||||
|
||||
def from_http(
|
||||
self, request: HttpRequest, user: Optional[settings.AUTH_USER_MODEL] = None
|
||||
) -> "Event":
|
||||
def from_http(self, request: HttpRequest, user: Optional[User] = None) -> "Event":
|
||||
"""Add data from a Django-HttpRequest, allowing the creation of
|
||||
Events independently from requests.
|
||||
`user` arguments optionally overrides user from requests."""
|
||||
|
@ -87,9 +87,9 @@ class TaskInfo:
|
||||
except TypeError:
|
||||
duration = 0
|
||||
GAUGE_TASKS.labels(
|
||||
task_name=self.task_name,
|
||||
task_name=self.task_name.split(":")[0],
|
||||
task_uid=self.result.uid or "",
|
||||
status=self.result.status,
|
||||
status=self.result.status.value,
|
||||
).set(duration)
|
||||
|
||||
def save(self, timeout_hours=6):
|
||||
|
@ -2,6 +2,7 @@
|
||||
import re
|
||||
from copy import copy
|
||||
from dataclasses import asdict, is_dataclass
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from types import GeneratorType
|
||||
from typing import Any, Optional
|
||||
@ -126,6 +127,8 @@ def sanitize_item(value: Any) -> Any:
|
||||
return str(value)
|
||||
if isinstance(value, YAMLTag):
|
||||
return str(value)
|
||||
if isinstance(value, Enum):
|
||||
return value.value
|
||||
if isinstance(value, type):
|
||||
return {
|
||||
"type": value.__name__,
|
||||
|
@ -23,6 +23,7 @@ from authentik.flows.api.bindings import FlowStageBindingSerializer
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.flows.planner import FlowPlan
|
||||
from authentik.flows.views.executor import SESSION_KEY_HISTORY, SESSION_KEY_PLAN
|
||||
from authentik.root.install_id import get_install_id
|
||||
|
||||
|
||||
class FlowInspectorPlanSerializer(PassiveSerializer):
|
||||
@ -51,7 +52,7 @@ class FlowInspectorPlanSerializer(PassiveSerializer):
|
||||
"""Get a unique session ID"""
|
||||
request: Request = self.context["request"]
|
||||
return sha256(
|
||||
f"{request._request.session.session_key}-{settings.SECRET_KEY}".encode("ascii")
|
||||
f"{request._request.session.session_key}-{get_install_id()}".encode("ascii")
|
||||
).hexdigest()
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@ from contextlib import contextmanager
|
||||
from glob import glob
|
||||
from json import dumps, loads
|
||||
from json.decoder import JSONDecodeError
|
||||
from pathlib import Path
|
||||
from sys import argv, stderr
|
||||
from time import time
|
||||
from typing import Any
|
||||
@ -42,22 +43,25 @@ class ConfigLoader:
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.__config = {}
|
||||
base_dir = os.path.realpath(os.path.join(os.path.dirname(__file__), "../.."))
|
||||
for path in SEARCH_PATHS:
|
||||
base_dir = Path(__file__).parent.joinpath(Path("../..")).resolve()
|
||||
for _path in SEARCH_PATHS:
|
||||
path = Path(_path)
|
||||
# Check if path is relative, and if so join with base_dir
|
||||
if not os.path.isabs(path):
|
||||
path = os.path.join(base_dir, path)
|
||||
if os.path.isfile(path) and os.path.exists(path):
|
||||
if not path.is_absolute():
|
||||
path = base_dir / path
|
||||
if path.is_file() and path.exists():
|
||||
# Path is an existing file, so we just read it and update our config with it
|
||||
self.update_from_file(path)
|
||||
elif os.path.isdir(path) and os.path.exists(path):
|
||||
elif path.is_dir() and path.exists():
|
||||
# Path is an existing dir, so we try to read the env config from it
|
||||
env_paths = [
|
||||
os.path.join(path, ENVIRONMENT + ".yml"),
|
||||
os.path.join(path, ENVIRONMENT + ".env.yml"),
|
||||
path / Path(ENVIRONMENT + ".yml"),
|
||||
path / Path(ENVIRONMENT + ".env.yml"),
|
||||
path / Path(ENVIRONMENT + ".yaml"),
|
||||
path / Path(ENVIRONMENT + ".env.yaml"),
|
||||
]
|
||||
for env_file in env_paths:
|
||||
if os.path.isfile(env_file) and os.path.exists(env_file):
|
||||
if env_file.is_file() and env_file.exists():
|
||||
# Update config with env file
|
||||
self.update_from_file(env_file)
|
||||
self.update_from_env()
|
||||
@ -99,13 +103,13 @@ class ConfigLoader:
|
||||
value = url.query
|
||||
return value
|
||||
|
||||
def update_from_file(self, path: str):
|
||||
def update_from_file(self, path: Path):
|
||||
"""Update config from file contents"""
|
||||
try:
|
||||
with open(path, encoding="utf8") as file:
|
||||
try:
|
||||
self.update(self.__config, yaml.safe_load(file))
|
||||
self.log("debug", "Loaded config", file=path)
|
||||
self.log("debug", "Loaded config", file=str(path))
|
||||
self.loaded_file.append(path)
|
||||
except yaml.YAMLError as exc:
|
||||
raise ImproperlyConfigured from exc
|
||||
|
@ -140,19 +140,21 @@ class BaseEvaluator:
|
||||
def expr_event_create(self, action: str, **kwargs):
|
||||
"""Create event with supplied data and try to extract as much relevant data
|
||||
from the context"""
|
||||
context = self._context.copy()
|
||||
# If the result was a complex variable, we don't want to re-use it
|
||||
self._context.pop("result", None)
|
||||
self._context.pop("handler", None)
|
||||
kwargs["context"] = self._context
|
||||
context.pop("result", None)
|
||||
context.pop("handler", None)
|
||||
event_kwargs = context
|
||||
event_kwargs.update(kwargs)
|
||||
event = Event.new(
|
||||
action,
|
||||
app=self._filename,
|
||||
**kwargs,
|
||||
**event_kwargs,
|
||||
)
|
||||
if "request" in self._context and isinstance(self._context["request"], PolicyRequest):
|
||||
policy_request: PolicyRequest = self._context["request"]
|
||||
if "request" in context and isinstance(context["request"], PolicyRequest):
|
||||
policy_request: PolicyRequest = context["request"]
|
||||
if policy_request.http_request:
|
||||
event.from_http(policy_request)
|
||||
event.from_http(policy_request.http_request)
|
||||
return
|
||||
event.save()
|
||||
|
||||
|
@ -19,7 +19,15 @@ def fallback_names(app: str, model: str, field: str):
|
||||
if value not in seen_names:
|
||||
seen_names.append(value)
|
||||
continue
|
||||
new_value = value + "_2"
|
||||
separator = "_"
|
||||
suffix_index = 2
|
||||
while (
|
||||
klass.objects.using(db_alias)
|
||||
.filter(**{field: f"{value}{separator}{suffix_index}"})
|
||||
.exists()
|
||||
):
|
||||
suffix_index += 1
|
||||
new_value = f"{value}{separator}{suffix_index}"
|
||||
setattr(obj, field, new_value)
|
||||
obj.save()
|
||||
|
||||
|
@ -2,28 +2,41 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.events.models import Event
|
||||
from authentik.lib.expression.evaluator import BaseEvaluator
|
||||
from authentik.lib.generators import generate_id
|
||||
|
||||
|
||||
class TestEvaluator(TestCase):
|
||||
"""Test Evaluator base functions"""
|
||||
|
||||
def test_regex_match(self):
|
||||
def test_expr_regex_match(self):
|
||||
"""Test expr_regex_match"""
|
||||
self.assertFalse(BaseEvaluator.expr_regex_match("foo", "bar"))
|
||||
self.assertTrue(BaseEvaluator.expr_regex_match("foo", "foo"))
|
||||
|
||||
def test_regex_replace(self):
|
||||
def test_expr_regex_replace(self):
|
||||
"""Test expr_regex_replace"""
|
||||
self.assertEqual(BaseEvaluator.expr_regex_replace("foo", "o", "a"), "faa")
|
||||
|
||||
def test_user_by(self):
|
||||
def test_expr_user_by(self):
|
||||
"""Test expr_user_by"""
|
||||
user = create_test_admin_user()
|
||||
self.assertIsNotNone(BaseEvaluator.expr_user_by(username=user.username))
|
||||
self.assertIsNone(BaseEvaluator.expr_user_by(username="bar"))
|
||||
self.assertIsNone(BaseEvaluator.expr_user_by(foo="bar"))
|
||||
|
||||
def test_is_group_member(self):
|
||||
def test_expr_is_group_member(self):
|
||||
"""Test expr_is_group_member"""
|
||||
self.assertFalse(BaseEvaluator.expr_is_group_member(create_test_admin_user(), name="test"))
|
||||
|
||||
def test_expr_event_create(self):
|
||||
"""Test expr_event_create"""
|
||||
evaluator = BaseEvaluator(generate_id())
|
||||
evaluator._context = {
|
||||
"foo": "bar",
|
||||
}
|
||||
evaluator.evaluate("ak_create_event('foo', bar='baz')")
|
||||
event = Event.objects.filter(action="custom_foo").first()
|
||||
self.assertIsNotNone(event)
|
||||
self.assertEqual(event.context, {"bar": "baz", "foo": "bar"})
|
||||
|
@ -42,12 +42,15 @@ from authentik.providers.ldap.controllers.docker import LDAPDockerController
|
||||
from authentik.providers.ldap.controllers.kubernetes import LDAPKubernetesController
|
||||
from authentik.providers.proxy.controllers.docker import ProxyDockerController
|
||||
from authentik.providers.proxy.controllers.kubernetes import ProxyKubernetesController
|
||||
from authentik.providers.radius.controllers.docker import RadiusDockerController
|
||||
from authentik.providers.radius.controllers.kubernetes import RadiusKubernetesController
|
||||
from authentik.root.celery import CELERY_APP
|
||||
|
||||
LOGGER = get_logger()
|
||||
CACHE_KEY_OUTPOST_DOWN = "goauthentik.io/outposts/teardown/%s"
|
||||
|
||||
|
||||
# pylint: disable=too-many-return-statements
|
||||
def controller_for_outpost(outpost: Outpost) -> Optional[type[BaseController]]:
|
||||
"""Get a controller for the outpost, when a service connection is defined"""
|
||||
if not outpost.service_connection:
|
||||
@ -63,6 +66,11 @@ def controller_for_outpost(outpost: Outpost) -> Optional[type[BaseController]]:
|
||||
return LDAPDockerController
|
||||
if isinstance(service_connection, KubernetesServiceConnection):
|
||||
return LDAPKubernetesController
|
||||
if outpost.type == OutpostType.RADIUS:
|
||||
if isinstance(service_connection, DockerServiceConnection):
|
||||
return RadiusDockerController
|
||||
if isinstance(service_connection, KubernetesServiceConnection):
|
||||
return RadiusKubernetesController
|
||||
return None
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
from typing import Any
|
||||
|
||||
|
||||
def delete_none_keys(dict_: dict[Any, Any]) -> dict[Any, Any]:
|
||||
def delete_none_values(dict_: dict[Any, Any]) -> dict[Any, Any]:
|
||||
"""Remove any keys from `dict_` that are None."""
|
||||
new_dict = {}
|
||||
for key, value in dict_.items():
|
||||
|
@ -1,185 +1,40 @@
|
||||
"""Kubernetes Traefik Middleware Reconciler"""
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from dacite.core import from_dict
|
||||
from kubernetes.client import ApiextensionsV1Api, CustomObjectsApi
|
||||
|
||||
from authentik.outposts.controllers.base import FIELD_MANAGER
|
||||
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
|
||||
from authentik.outposts.controllers.k8s.triggers import NeedsUpdate
|
||||
from authentik.providers.proxy.models import ProxyMode, ProxyProvider
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from authentik.outposts.controllers.kubernetes import KubernetesController
|
||||
from authentik.outposts.controllers.kubernetes import KubernetesController
|
||||
from authentik.providers.proxy.controllers.k8s.traefik_2 import Traefik2MiddlewareReconciler
|
||||
from authentik.providers.proxy.controllers.k8s.traefik_3 import (
|
||||
Traefik3MiddlewareReconciler,
|
||||
TraefikMiddleware,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TraefikMiddlewareSpecForwardAuth:
|
||||
"""traefik middleware forwardAuth spec"""
|
||||
|
||||
address: str
|
||||
# pylint: disable=invalid-name
|
||||
authResponseHeadersRegex: str = field(default="")
|
||||
# pylint: disable=invalid-name
|
||||
authResponseHeaders: list[str] = field(default_factory=list)
|
||||
# pylint: disable=invalid-name
|
||||
trustForwardHeader: bool = field(default=True)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TraefikMiddlewareSpec:
|
||||
"""Traefik middleware spec"""
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
forwardAuth: TraefikMiddlewareSpecForwardAuth
|
||||
|
||||
|
||||
@dataclass
|
||||
class TraefikMiddlewareMetadata:
|
||||
"""Traefik Middleware metadata"""
|
||||
|
||||
name: str
|
||||
namespace: str
|
||||
labels: dict = field(default_factory=dict)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TraefikMiddleware:
|
||||
"""Traefik Middleware"""
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
apiVersion: str
|
||||
kind: str
|
||||
metadata: TraefikMiddlewareMetadata
|
||||
spec: TraefikMiddlewareSpec
|
||||
|
||||
|
||||
CRD_NAME = "middlewares.traefik.containo.us"
|
||||
CRD_GROUP = "traefik.containo.us"
|
||||
CRD_VERSION = "v1alpha1"
|
||||
CRD_PLURAL = "middlewares"
|
||||
|
||||
|
||||
class TraefikMiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware]):
|
||||
class TraefikMiddlewareReconciler(KubernetesObjectReconciler):
|
||||
"""Kubernetes Traefik Middleware Reconciler"""
|
||||
|
||||
def __init__(self, controller: "KubernetesController") -> None:
|
||||
super().__init__(controller)
|
||||
self.api_ex = ApiextensionsV1Api(controller.client)
|
||||
self.api = CustomObjectsApi(controller.client)
|
||||
self.reconciler = Traefik3MiddlewareReconciler(controller)
|
||||
if not self.reconciler.crd_exists():
|
||||
self.reconciler = Traefik2MiddlewareReconciler(controller)
|
||||
|
||||
@property
|
||||
def noop(self) -> bool:
|
||||
if not ProxyProvider.objects.filter(
|
||||
outpost__in=[self.controller.outpost],
|
||||
mode__in=[ProxyMode.FORWARD_SINGLE, ProxyMode.FORWARD_DOMAIN],
|
||||
).exists():
|
||||
self.logger.debug("No providers with forward auth enabled.")
|
||||
return True
|
||||
if not self._crd_exists():
|
||||
self.logger.debug("CRD doesn't exist")
|
||||
return True
|
||||
return False
|
||||
|
||||
def _crd_exists(self) -> bool:
|
||||
"""Check if the traefik middleware exists"""
|
||||
return bool(
|
||||
len(
|
||||
self.api_ex.list_custom_resource_definition(
|
||||
field_selector=f"metadata.name={CRD_NAME}"
|
||||
).items
|
||||
)
|
||||
)
|
||||
return self.reconciler.noop
|
||||
|
||||
def reconcile(self, current: TraefikMiddleware, reference: TraefikMiddleware):
|
||||
super().reconcile(current, reference)
|
||||
if current.spec.forwardAuth.address != reference.spec.forwardAuth.address:
|
||||
raise NeedsUpdate()
|
||||
if (
|
||||
current.spec.forwardAuth.authResponseHeadersRegex
|
||||
!= reference.spec.forwardAuth.authResponseHeadersRegex
|
||||
):
|
||||
raise NeedsUpdate()
|
||||
# Ensure all of our headers are set, others can be added by the user.
|
||||
if not set(current.spec.forwardAuth.authResponseHeaders).issubset(
|
||||
reference.spec.forwardAuth.authResponseHeaders
|
||||
):
|
||||
raise NeedsUpdate()
|
||||
return self.reconcile(current, reference)
|
||||
|
||||
def get_reference_object(self) -> TraefikMiddleware:
|
||||
"""Get deployment object for outpost"""
|
||||
return TraefikMiddleware(
|
||||
apiVersion=f"{CRD_GROUP}/{CRD_VERSION}",
|
||||
kind="Middleware",
|
||||
metadata=TraefikMiddlewareMetadata(
|
||||
name=self.name,
|
||||
namespace=self.namespace,
|
||||
labels=self.get_object_meta().labels,
|
||||
),
|
||||
spec=TraefikMiddlewareSpec(
|
||||
forwardAuth=TraefikMiddlewareSpecForwardAuth(
|
||||
address=(
|
||||
f"http://{self.name}.{self.namespace}:9000/"
|
||||
"outpost.goauthentik.io/auth/traefik"
|
||||
),
|
||||
authResponseHeaders=[
|
||||
"X-authentik-username",
|
||||
"X-authentik-groups",
|
||||
"X-authentik-email",
|
||||
"X-authentik-name",
|
||||
"X-authentik-uid",
|
||||
"X-authentik-jwt",
|
||||
"X-authentik-meta-jwks",
|
||||
"X-authentik-meta-outpost",
|
||||
"X-authentik-meta-provider",
|
||||
"X-authentik-meta-app",
|
||||
"X-authentik-meta-version",
|
||||
],
|
||||
authResponseHeadersRegex="",
|
||||
trustForwardHeader=True,
|
||||
)
|
||||
),
|
||||
)
|
||||
return self.get_reference_object()
|
||||
|
||||
def create(self, reference: TraefikMiddleware):
|
||||
return self.api.create_namespaced_custom_object(
|
||||
group=CRD_GROUP,
|
||||
version=CRD_VERSION,
|
||||
plural=CRD_PLURAL,
|
||||
namespace=self.namespace,
|
||||
body=asdict(reference),
|
||||
field_manager=FIELD_MANAGER,
|
||||
)
|
||||
return self.create(reference)
|
||||
|
||||
def delete(self, reference: TraefikMiddleware):
|
||||
return self.api.delete_namespaced_custom_object(
|
||||
group=CRD_GROUP,
|
||||
version=CRD_VERSION,
|
||||
namespace=self.namespace,
|
||||
plural=CRD_PLURAL,
|
||||
name=self.name,
|
||||
)
|
||||
return self.delete(reference)
|
||||
|
||||
def retrieve(self) -> TraefikMiddleware:
|
||||
return from_dict(
|
||||
TraefikMiddleware,
|
||||
self.api.get_namespaced_custom_object(
|
||||
group=CRD_GROUP,
|
||||
version=CRD_VERSION,
|
||||
namespace=self.namespace,
|
||||
plural=CRD_PLURAL,
|
||||
name=self.name,
|
||||
),
|
||||
)
|
||||
return self.retrieve()
|
||||
|
||||
def update(self, current: TraefikMiddleware, reference: TraefikMiddleware):
|
||||
return self.api.patch_namespaced_custom_object(
|
||||
group=CRD_GROUP,
|
||||
version=CRD_VERSION,
|
||||
namespace=self.namespace,
|
||||
plural=CRD_PLURAL,
|
||||
name=self.name,
|
||||
body=asdict(reference),
|
||||
field_manager=FIELD_MANAGER,
|
||||
)
|
||||
return self.update(current, reference)
|
||||
|
18
authentik/providers/proxy/controllers/k8s/traefik_2.py
Normal file
18
authentik/providers/proxy/controllers/k8s/traefik_2.py
Normal file
@ -0,0 +1,18 @@
|
||||
"""Kubernetes Traefik Middleware Reconciler"""
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from authentik.providers.proxy.controllers.k8s.traefik_3 import Traefik3MiddlewareReconciler
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from authentik.outposts.controllers.kubernetes import KubernetesController
|
||||
|
||||
|
||||
class Traefik2MiddlewareReconciler(Traefik3MiddlewareReconciler):
|
||||
"""Kubernetes Traefik Middleware Reconciler"""
|
||||
|
||||
def __init__(self, controller: "KubernetesController") -> None:
|
||||
super().__init__(controller)
|
||||
self.crd_name = "middlewares.traefik.containo.us"
|
||||
self.crd_group = "traefik.containo.us"
|
||||
self.crd_version = "v1alpha1"
|
||||
self.crd_plural = "middlewares"
|
183
authentik/providers/proxy/controllers/k8s/traefik_3.py
Normal file
183
authentik/providers/proxy/controllers/k8s/traefik_3.py
Normal file
@ -0,0 +1,183 @@
|
||||
"""Kubernetes Traefik Middleware Reconciler"""
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from dacite.core import from_dict
|
||||
from kubernetes.client import ApiextensionsV1Api, CustomObjectsApi
|
||||
|
||||
from authentik.outposts.controllers.base import FIELD_MANAGER
|
||||
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
|
||||
from authentik.outposts.controllers.k8s.triggers import NeedsUpdate
|
||||
from authentik.providers.proxy.models import ProxyMode, ProxyProvider
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from authentik.outposts.controllers.kubernetes import KubernetesController
|
||||
|
||||
|
||||
@dataclass
|
||||
class TraefikMiddlewareSpecForwardAuth:
|
||||
"""traefik middleware forwardAuth spec"""
|
||||
|
||||
address: str
|
||||
# pylint: disable=invalid-name
|
||||
authResponseHeadersRegex: str = field(default="")
|
||||
# pylint: disable=invalid-name
|
||||
authResponseHeaders: list[str] = field(default_factory=list)
|
||||
# pylint: disable=invalid-name
|
||||
trustForwardHeader: bool = field(default=True)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TraefikMiddlewareSpec:
|
||||
"""Traefik middleware spec"""
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
forwardAuth: TraefikMiddlewareSpecForwardAuth
|
||||
|
||||
|
||||
@dataclass
|
||||
class TraefikMiddlewareMetadata:
|
||||
"""Traefik Middleware metadata"""
|
||||
|
||||
name: str
|
||||
namespace: str
|
||||
labels: dict = field(default_factory=dict)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TraefikMiddleware:
|
||||
"""Traefik Middleware"""
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
apiVersion: str
|
||||
kind: str
|
||||
metadata: TraefikMiddlewareMetadata
|
||||
spec: TraefikMiddlewareSpec
|
||||
|
||||
|
||||
class Traefik3MiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware]):
|
||||
"""Kubernetes Traefik Middleware Reconciler"""
|
||||
|
||||
def __init__(self, controller: "KubernetesController") -> None:
|
||||
super().__init__(controller)
|
||||
self.api_ex = ApiextensionsV1Api(controller.client)
|
||||
self.api = CustomObjectsApi(controller.client)
|
||||
self.crd_name = "middlewares.traefik.io"
|
||||
self.crd_group = "traefik.io"
|
||||
self.crd_version = "v1alpha1"
|
||||
self.crd_plural = "middlewares"
|
||||
|
||||
@property
|
||||
def noop(self) -> bool:
|
||||
if not ProxyProvider.objects.filter(
|
||||
outpost__in=[self.controller.outpost],
|
||||
mode__in=[ProxyMode.FORWARD_SINGLE, ProxyMode.FORWARD_DOMAIN],
|
||||
).exists():
|
||||
self.logger.debug("No providers with forward auth enabled.")
|
||||
return True
|
||||
if not self.crd_exists():
|
||||
self.logger.debug("CRD doesn't exist")
|
||||
return True
|
||||
return False
|
||||
|
||||
def crd_exists(self) -> bool:
|
||||
"""Check if the traefik middleware exists"""
|
||||
return bool(
|
||||
len(
|
||||
self.api_ex.list_custom_resource_definition(
|
||||
field_selector=f"metadata.name={self.crd_name}"
|
||||
).items
|
||||
)
|
||||
)
|
||||
|
||||
def reconcile(self, current: TraefikMiddleware, reference: TraefikMiddleware):
|
||||
super().reconcile(current, reference)
|
||||
if current.spec.forwardAuth.address != reference.spec.forwardAuth.address:
|
||||
raise NeedsUpdate()
|
||||
if (
|
||||
current.spec.forwardAuth.authResponseHeadersRegex
|
||||
!= reference.spec.forwardAuth.authResponseHeadersRegex
|
||||
):
|
||||
raise NeedsUpdate()
|
||||
# Ensure all of our headers are set, others can be added by the user.
|
||||
if not set(current.spec.forwardAuth.authResponseHeaders).issubset(
|
||||
reference.spec.forwardAuth.authResponseHeaders
|
||||
):
|
||||
raise NeedsUpdate()
|
||||
|
||||
def get_reference_object(self) -> TraefikMiddleware:
|
||||
"""Get deployment object for outpost"""
|
||||
return TraefikMiddleware(
|
||||
apiVersion=f"{self.crd_group}/{self.crd_version}",
|
||||
kind="Middleware",
|
||||
metadata=TraefikMiddlewareMetadata(
|
||||
name=self.name,
|
||||
namespace=self.namespace,
|
||||
labels=self.get_object_meta().labels,
|
||||
),
|
||||
spec=TraefikMiddlewareSpec(
|
||||
forwardAuth=TraefikMiddlewareSpecForwardAuth(
|
||||
address=(
|
||||
f"http://{self.name}.{self.namespace}:9000/"
|
||||
"outpost.goauthentik.io/auth/traefik"
|
||||
),
|
||||
authResponseHeaders=[
|
||||
"X-authentik-username",
|
||||
"X-authentik-groups",
|
||||
"X-authentik-email",
|
||||
"X-authentik-name",
|
||||
"X-authentik-uid",
|
||||
"X-authentik-jwt",
|
||||
"X-authentik-meta-jwks",
|
||||
"X-authentik-meta-outpost",
|
||||
"X-authentik-meta-provider",
|
||||
"X-authentik-meta-app",
|
||||
"X-authentik-meta-version",
|
||||
],
|
||||
authResponseHeadersRegex="",
|
||||
trustForwardHeader=True,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def create(self, reference: TraefikMiddleware):
|
||||
return self.api.create_namespaced_custom_object(
|
||||
group=self.crd_group,
|
||||
version=self.crd_version,
|
||||
plural=self.crd_plural,
|
||||
namespace=self.namespace,
|
||||
body=asdict(reference),
|
||||
field_manager=FIELD_MANAGER,
|
||||
)
|
||||
|
||||
def delete(self, reference: TraefikMiddleware):
|
||||
return self.api.delete_namespaced_custom_object(
|
||||
group=self.crd_group,
|
||||
version=self.crd_version,
|
||||
plural=self.crd_plural,
|
||||
namespace=self.namespace,
|
||||
name=self.name,
|
||||
)
|
||||
|
||||
def retrieve(self) -> TraefikMiddleware:
|
||||
return from_dict(
|
||||
TraefikMiddleware,
|
||||
self.api.get_namespaced_custom_object(
|
||||
group=self.crd_group,
|
||||
version=self.crd_version,
|
||||
plural=self.crd_plural,
|
||||
namespace=self.namespace,
|
||||
name=self.name,
|
||||
),
|
||||
)
|
||||
|
||||
def update(self, current: TraefikMiddleware, reference: TraefikMiddleware):
|
||||
return self.api.patch_namespaced_custom_object(
|
||||
group=self.crd_group,
|
||||
version=self.crd_version,
|
||||
plural=self.crd_plural,
|
||||
namespace=self.namespace,
|
||||
name=self.name,
|
||||
body=asdict(reference),
|
||||
field_manager=FIELD_MANAGER,
|
||||
)
|
@ -1,5 +1,5 @@
|
||||
"""RadiusProvider API Views"""
|
||||
from rest_framework.fields import CharField
|
||||
from rest_framework.fields import CharField, ListField
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
||||
|
||||
@ -11,6 +11,8 @@ from authentik.providers.radius.models import RadiusProvider
|
||||
class RadiusProviderSerializer(ProviderSerializer):
|
||||
"""RadiusProvider Serializer"""
|
||||
|
||||
outpost_set = ListField(child=CharField(), read_only=True, source="outpost_set.all")
|
||||
|
||||
class Meta:
|
||||
model = RadiusProvider
|
||||
fields = ProviderSerializer.Meta.fields + [
|
||||
@ -18,6 +20,7 @@ class RadiusProviderSerializer(ProviderSerializer):
|
||||
# Shared secret is not a write-only field, as
|
||||
# an admin might have to view it
|
||||
"shared_secret",
|
||||
"outpost_set",
|
||||
]
|
||||
extra_kwargs = ProviderSerializer.Meta.extra_kwargs
|
||||
|
||||
|
@ -90,6 +90,7 @@ class TestAuthNRequest(TestCase):
|
||||
issuer="authentik",
|
||||
pre_authentication_flow=create_test_flow(),
|
||||
signing_kp=cert,
|
||||
verification_kp=cert,
|
||||
)
|
||||
|
||||
def test_signed_valid(self):
|
||||
|
@ -24,8 +24,8 @@ class SCIMProviderSerializer(ProviderSerializer):
|
||||
"property_mappings",
|
||||
"property_mappings_group",
|
||||
"component",
|
||||
"assigned_application_slug",
|
||||
"assigned_application_name",
|
||||
"assigned_backchannel_application_slug",
|
||||
"assigned_backchannel_application_name",
|
||||
"verbose_name",
|
||||
"verbose_name_plural",
|
||||
"meta_model_name",
|
||||
|
@ -51,7 +51,7 @@ class SCIMClient(Generic[T, SchemaType]):
|
||||
},
|
||||
)
|
||||
except RequestException as exc:
|
||||
raise SCIMRequestException(None) from exc
|
||||
raise SCIMRequestException(message="Failed to send request") from exc
|
||||
self.logger.debug("scim request", path=path, method=method, **kwargs)
|
||||
if response.status_code >= 400:
|
||||
if response.status_code == 404:
|
||||
|
@ -2,10 +2,10 @@
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import ValidationError
|
||||
from pydanticscim.responses import SCIMError
|
||||
from requests import Response
|
||||
|
||||
from authentik.lib.sentry import SentryIgnoredException
|
||||
from authentik.providers.scim.clients.schema import SCIMError
|
||||
|
||||
|
||||
class StopSync(SentryIgnoredException):
|
||||
@ -16,7 +16,8 @@ class StopSync(SentryIgnoredException):
|
||||
self.obj = obj
|
||||
self.mapping = mapping
|
||||
|
||||
def __str__(self) -> str:
|
||||
def detail(self) -> str:
|
||||
"""Get human readable details of this error"""
|
||||
msg = f"Error {str(self.exc)}, caused by {self.obj}"
|
||||
|
||||
if self.mapping:
|
||||
@ -28,19 +29,22 @@ class SCIMRequestException(SentryIgnoredException):
|
||||
"""Exception raised when an SCIM request fails"""
|
||||
|
||||
_response: Optional[Response]
|
||||
_message: Optional[str]
|
||||
|
||||
def __init__(self, response: Optional[Response] = None) -> None:
|
||||
def __init__(self, response: Optional[Response] = None, message: Optional[str] = None) -> None:
|
||||
self._response = response
|
||||
self._message = message
|
||||
|
||||
def __str__(self) -> str:
|
||||
def detail(self) -> str:
|
||||
"""Get human readable details of this error"""
|
||||
if not self._response:
|
||||
return super().__str__()
|
||||
return self._message
|
||||
try:
|
||||
error = SCIMError.parse_raw(self._response.text)
|
||||
return error.detail
|
||||
except ValidationError:
|
||||
pass
|
||||
return super().__str__()
|
||||
return self._message
|
||||
|
||||
|
||||
class ResourceMissing(SCIMRequestException):
|
||||
|
@ -8,7 +8,7 @@ from authentik.core.exceptions import PropertyMappingExpressionException
|
||||
from authentik.core.models import Group
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.utils.errors import exception_to_string
|
||||
from authentik.policies.utils import delete_none_keys
|
||||
from authentik.policies.utils import delete_none_values
|
||||
from authentik.providers.scim.clients.base import SCIMClient
|
||||
from authentik.providers.scim.clients.exceptions import (
|
||||
ResourceMissing,
|
||||
@ -74,7 +74,7 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
|
||||
if not raw_scim_group:
|
||||
raise StopSync(ValueError("No group mappings configured"), obj)
|
||||
try:
|
||||
scim_group = SCIMGroupSchema.parse_obj(delete_none_keys(raw_scim_group))
|
||||
scim_group = SCIMGroupSchema.parse_obj(delete_none_values(raw_scim_group))
|
||||
except ValidationError as exc:
|
||||
raise StopSync(exc, obj) from exc
|
||||
if not scim_group.externalId:
|
||||
@ -130,10 +130,8 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
|
||||
scim_group.id,
|
||||
PatchOperation(
|
||||
op=PatchOp.replace,
|
||||
value={
|
||||
"id": connection.id,
|
||||
"displayName": group.name,
|
||||
},
|
||||
path="displayName",
|
||||
value=scim_group.displayName,
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -3,6 +3,7 @@ from typing import Optional
|
||||
|
||||
from pydanticscim.group import Group as BaseGroup
|
||||
from pydanticscim.responses import PatchRequest as BasePatchRequest
|
||||
from pydanticscim.responses import SCIMError as BaseSCIMError
|
||||
from pydanticscim.service_provider import Bulk, ChangePassword, Filter, Patch
|
||||
from pydanticscim.service_provider import (
|
||||
ServiceProviderConfiguration as BaseServiceProviderConfiguration,
|
||||
@ -52,3 +53,9 @@ class PatchRequest(BasePatchRequest):
|
||||
"""PatchRequest which correctly sets schemas"""
|
||||
|
||||
schemas: tuple[str] = ["urn:ietf:params:scim:api:messages:2.0:PatchOp"]
|
||||
|
||||
|
||||
class SCIMError(BaseSCIMError):
|
||||
"""SCIM error with optional status code"""
|
||||
|
||||
status: Optional[int]
|
||||
|
@ -6,7 +6,7 @@ from authentik.core.exceptions import PropertyMappingExpressionException
|
||||
from authentik.core.models import User
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.utils.errors import exception_to_string
|
||||
from authentik.policies.utils import delete_none_keys
|
||||
from authentik.policies.utils import delete_none_values
|
||||
from authentik.providers.scim.clients.base import SCIMClient
|
||||
from authentik.providers.scim.clients.exceptions import ResourceMissing, StopSync
|
||||
from authentik.providers.scim.clients.schema import User as SCIMUserSchema
|
||||
@ -64,7 +64,7 @@ class SCIMUserClient(SCIMClient[User, SCIMUserSchema]):
|
||||
if not raw_scim_user:
|
||||
raise StopSync(ValueError("No user mappings configured"), obj)
|
||||
try:
|
||||
scim_user = SCIMUserSchema.parse_obj(delete_none_keys(raw_scim_user))
|
||||
scim_user = SCIMUserSchema.parse_obj(delete_none_values(raw_scim_user))
|
||||
except ValidationError as exc:
|
||||
raise StopSync(exc, obj) from exc
|
||||
if not scim_user.externalId:
|
||||
|
@ -42,7 +42,9 @@ def scim_sync_all():
|
||||
@CELERY_APP.task(bind=True, base=MonitoredTask)
|
||||
def scim_sync(self: MonitoredTask, provider_pk: int) -> None:
|
||||
"""Run SCIM full sync for provider"""
|
||||
provider: SCIMProvider = SCIMProvider.objects.filter(pk=provider_pk).first()
|
||||
provider: SCIMProvider = SCIMProvider.objects.filter(
|
||||
pk=provider_pk, backchannel_application__isnull=False
|
||||
).first()
|
||||
if not provider:
|
||||
return
|
||||
self.set_uid(slugify(provider.name))
|
||||
@ -87,10 +89,10 @@ def scim_sync_users(page: int, provider_pk: int):
|
||||
LOGGER.warning("failed to sync user", exc=exc, user=user)
|
||||
messages.append(
|
||||
_(
|
||||
"Failed to sync user due to remote error %(name)s: %(error)s"
|
||||
"Failed to sync user %(user_name)s due to remote error: %(error)s"
|
||||
% {
|
||||
"name": user.username,
|
||||
"error": str(exc),
|
||||
"user_name": user.username,
|
||||
"error": exc.detail(),
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -100,7 +102,7 @@ def scim_sync_users(page: int, provider_pk: int):
|
||||
_(
|
||||
"Stopping sync due to error: %(error)s"
|
||||
% {
|
||||
"error": str(exc),
|
||||
"error": exc.detail(),
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -128,10 +130,10 @@ def scim_sync_group(page: int, provider_pk: int):
|
||||
LOGGER.warning("failed to sync group", exc=exc, group=group)
|
||||
messages.append(
|
||||
_(
|
||||
"Failed to sync group due to remote error %(name)s: %(error)s"
|
||||
"Failed to sync group %(group_name)s due to remote error: %(error)s"
|
||||
% {
|
||||
"name": group.name,
|
||||
"error": str(exc),
|
||||
"group_name": group.name,
|
||||
"error": exc.detail(),
|
||||
}
|
||||
)
|
||||
)
|
||||
@ -141,7 +143,7 @@ def scim_sync_group(page: int, provider_pk: int):
|
||||
_(
|
||||
"Stopping sync due to error: %(error)s"
|
||||
% {
|
||||
"error": str(exc),
|
||||
"error": exc.detail(),
|
||||
}
|
||||
)
|
||||
)
|
||||
|
@ -36,6 +36,7 @@ class SCIMMembershipTests(TestCase):
|
||||
slug=generate_id(),
|
||||
)
|
||||
self.app.backchannel_providers.add(self.provider)
|
||||
self.provider.save()
|
||||
self.provider.property_mappings.set(
|
||||
[SCIMMapping.objects.get(managed="goauthentik.io/providers/scim/user")]
|
||||
)
|
||||
@ -91,7 +92,6 @@ class SCIMMembershipTests(TestCase):
|
||||
"active": True,
|
||||
"externalId": user.uid,
|
||||
"name": {"familyName": "", "formatted": "", "givenName": ""},
|
||||
"photos": [],
|
||||
"displayName": "",
|
||||
"userName": user.username,
|
||||
},
|
||||
@ -177,7 +177,6 @@ class SCIMMembershipTests(TestCase):
|
||||
"emails": [],
|
||||
"externalId": user.uid,
|
||||
"name": {"familyName": "", "formatted": "", "givenName": ""},
|
||||
"photos": [],
|
||||
"userName": user.username,
|
||||
},
|
||||
)
|
||||
|
@ -81,7 +81,6 @@ class SCIMUserTests(TestCase):
|
||||
"givenName": uid,
|
||||
},
|
||||
"displayName": uid,
|
||||
"photos": [],
|
||||
"userName": uid,
|
||||
},
|
||||
)
|
||||
@ -137,7 +136,6 @@ class SCIMUserTests(TestCase):
|
||||
"formatted": uid,
|
||||
"givenName": uid,
|
||||
},
|
||||
"photos": [],
|
||||
"userName": uid,
|
||||
},
|
||||
)
|
||||
@ -190,7 +188,6 @@ class SCIMUserTests(TestCase):
|
||||
"givenName": uid,
|
||||
},
|
||||
"displayName": uid,
|
||||
"photos": [],
|
||||
"userName": uid,
|
||||
},
|
||||
)
|
||||
@ -258,7 +255,6 @@ class SCIMUserTests(TestCase):
|
||||
"givenName": uid,
|
||||
},
|
||||
"displayName": uid,
|
||||
"photos": [],
|
||||
"userName": uid,
|
||||
},
|
||||
)
|
||||
|
41
authentik/root/install_id.py
Normal file
41
authentik/root/install_id.py
Normal file
@ -0,0 +1,41 @@
|
||||
"""install ID"""
|
||||
from functools import lru_cache
|
||||
from uuid import uuid4
|
||||
|
||||
from psycopg2 import connect
|
||||
|
||||
from authentik.lib.config import CONFIG
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_install_id() -> str:
|
||||
"""Get install ID of this instance. The method is cached as the install ID is
|
||||
not expected to change"""
|
||||
from django.conf import settings
|
||||
from django.db import connection
|
||||
|
||||
if settings.TEST:
|
||||
return str(uuid4())
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("SELECT id FROM authentik_install_id LIMIT 1;")
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_install_id_raw():
|
||||
"""Get install_id without django loaded, this is required for the startup when we get
|
||||
the install_id but django isn't loaded yet and we can't use the function above."""
|
||||
conn = connect(
|
||||
dbname=CONFIG.y("postgresql.name"),
|
||||
user=CONFIG.y("postgresql.user"),
|
||||
password=CONFIG.y("postgresql.password"),
|
||||
host=CONFIG.y("postgresql.host"),
|
||||
port=int(CONFIG.y("postgresql.port")),
|
||||
sslmode=CONFIG.y("postgresql.sslmode"),
|
||||
sslrootcert=CONFIG.y("postgresql.sslrootcert"),
|
||||
sslcert=CONFIG.y("postgresql.sslcert"),
|
||||
sslkey=CONFIG.y("postgresql.sslkey"),
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT id FROM authentik_install_id LIMIT 1;")
|
||||
return cursor.fetchone()[0]
|
@ -1,4 +1,5 @@
|
||||
"""Dynamically set SameSite depending if the upstream connection is TLS or not"""
|
||||
from functools import lru_cache
|
||||
from hashlib import sha512
|
||||
from time import time
|
||||
from timeit import default_timer
|
||||
@ -16,10 +17,16 @@ from jwt import PyJWTError, decode, encode
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.lib.utils.http import get_client_ip
|
||||
from authentik.root.install_id import get_install_id
|
||||
|
||||
LOGGER = get_logger("authentik.asgi")
|
||||
ACR_AUTHENTIK_SESSION = "goauthentik.io/core/default"
|
||||
SIGNING_HASH = sha512(settings.SECRET_KEY.encode()).hexdigest()
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_signing_hash():
|
||||
"""Get cookie JWT signing hash"""
|
||||
return sha512(get_install_id().encode()).hexdigest()
|
||||
|
||||
|
||||
class SessionMiddleware(UpstreamSessionMiddleware):
|
||||
@ -47,7 +54,7 @@ class SessionMiddleware(UpstreamSessionMiddleware):
|
||||
# for testing setups, where the session is directly set
|
||||
session_key = key if settings.TEST else None
|
||||
try:
|
||||
session_payload = decode(key, SIGNING_HASH, algorithms=["HS256"])
|
||||
session_payload = decode(key, get_signing_hash(), algorithms=["HS256"])
|
||||
session_key = session_payload["sid"]
|
||||
except (KeyError, PyJWTError):
|
||||
pass
|
||||
@ -114,7 +121,7 @@ class SessionMiddleware(UpstreamSessionMiddleware):
|
||||
}
|
||||
if request.user.is_authenticated:
|
||||
payload["sub"] = request.user.uid
|
||||
value = encode(payload=payload, key=SIGNING_HASH)
|
||||
value = encode(payload=payload, key=get_signing_hash())
|
||||
if settings.TEST:
|
||||
value = request.session.session_key
|
||||
response.set_cookie(
|
||||
|
@ -4,6 +4,7 @@ import importlib
|
||||
import logging
|
||||
import os
|
||||
from hashlib import sha512
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
import structlog
|
||||
@ -19,11 +20,9 @@ from authentik.stages.password import BACKEND_APP_PASSWORD, BACKEND_INBUILT, BAC
|
||||
|
||||
LOGGER = structlog.get_logger()
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
STATIC_ROOT = BASE_DIR + "/static"
|
||||
STATICFILES_DIRS = [BASE_DIR + "/web"]
|
||||
MEDIA_ROOT = BASE_DIR + "/media"
|
||||
BASE_DIR = Path(__file__).absolute().parent.parent.parent
|
||||
STATICFILES_DIRS = [BASE_DIR / Path("web")]
|
||||
MEDIA_ROOT = BASE_DIR / Path("media")
|
||||
|
||||
DEBUG = CONFIG.y_bool("debug")
|
||||
SECRET_KEY = CONFIG.y("secret_key")
|
||||
|
@ -55,7 +55,7 @@ class LDAPBackend(InbuiltBackend):
|
||||
"""Attempt authentication by binding to the LDAP server as `user`. This
|
||||
method should be avoided as its slow to do the bind."""
|
||||
# Try to bind as new user
|
||||
LOGGER.debug("Attempting Binding as user", user=user)
|
||||
LOGGER.debug("Attempting to bind as user", user=user)
|
||||
try:
|
||||
temp_connection = source.connection(
|
||||
connection_kwargs={
|
||||
@ -65,8 +65,8 @@ class LDAPBackend(InbuiltBackend):
|
||||
)
|
||||
temp_connection.bind()
|
||||
return user
|
||||
except LDAPInvalidCredentialsResult as exception:
|
||||
LOGGER.debug("LDAPInvalidCredentialsResult", user=user, error=exception)
|
||||
except LDAPException as exception:
|
||||
LOGGER.warning(exception)
|
||||
except LDAPInvalidCredentialsResult as exc:
|
||||
LOGGER.debug("invalid LDAP credentials", user=user, exc=exc)
|
||||
except LDAPException as exc:
|
||||
LOGGER.warning("failed to bind to LDAP", exc=exc)
|
||||
return None
|
||||
|
@ -6,6 +6,7 @@ from django.dispatch import receiver
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from ldap3.core.exceptions import LDAPOperationResult
|
||||
from rest_framework.serializers import ValidationError
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.core.signals import password_changed
|
||||
@ -20,6 +21,8 @@ from authentik.sources.ldap.sync.users import UserLDAPSynchronizer
|
||||
from authentik.sources.ldap.tasks import ldap_sync
|
||||
from authentik.stages.prompt.signals import password_validate
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
@receiver(post_save, sender=LDAPSource)
|
||||
def sync_ldap_source_on_save(sender, instance: LDAPSource, **_):
|
||||
@ -67,9 +70,13 @@ def ldap_sync_password(sender, user: User, password: str, **_):
|
||||
try:
|
||||
changer.change_password(user, password)
|
||||
except LDAPOperationResult as exc:
|
||||
LOGGER.warning("failed to set LDAP password", exc=exc)
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
message=f"Result: {exc.result}, Description {exc.description}",
|
||||
message=(
|
||||
"Failed to change password in LDAP source due to remote error: "
|
||||
f"{exc.result}, {exc.message}, {exc.description}"
|
||||
),
|
||||
source=source,
|
||||
).set_user(user).save()
|
||||
raise ValidationError("Failed to set password") from exc
|
||||
|
@ -135,9 +135,9 @@ class BaseLDAPSynchronizer:
|
||||
if key == "attributes":
|
||||
continue
|
||||
setattr(instance, key, value)
|
||||
final_atttributes = {}
|
||||
MERGE_LIST_UNIQUE.merge(final_atttributes, instance.attributes)
|
||||
MERGE_LIST_UNIQUE.merge(final_atttributes, data.get("attributes", {}))
|
||||
instance.attributes = final_atttributes
|
||||
final_attributes = {}
|
||||
MERGE_LIST_UNIQUE.merge(final_attributes, instance.attributes)
|
||||
MERGE_LIST_UNIQUE.merge(final_attributes, data.get("attributes", {}))
|
||||
instance.attributes = final_attributes
|
||||
instance.save()
|
||||
return (instance, False)
|
||||
|
@ -26,6 +26,7 @@ class SAMLSourceSerializer(SourceSerializer):
|
||||
"allow_idp_initiated",
|
||||
"name_id_policy",
|
||||
"binding_type",
|
||||
"verification_kp",
|
||||
"signing_kp",
|
||||
"digest_algorithm",
|
||||
"signature_algorithm",
|
||||
@ -55,6 +56,7 @@ class SAMLSourceViewSet(UsedByMixin, ModelViewSet):
|
||||
"allow_idp_initiated",
|
||||
"name_id_policy",
|
||||
"binding_type",
|
||||
"verification_kp",
|
||||
"signing_kp",
|
||||
"digest_algorithm",
|
||||
"signature_algorithm",
|
||||
|
@ -0,0 +1,53 @@
|
||||
# Generated by Django 4.1.7 on 2023-05-19 21:55
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.apps.registry import Apps
|
||||
from django.db import migrations, models
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
|
||||
|
||||
def migrate_verification_cert(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||
"""Migrate signing cert to verification_kp for backwards compat"""
|
||||
|
||||
SAMLSource = apps.get_model("authentik_sources_saml", "samlsource")
|
||||
for source in SAMLSource.objects.using(schema_editor.connection.alias).all():
|
||||
source.verification_kp = source.signing_kp
|
||||
source.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("authentik_crypto", "0004_alter_certificatekeypair_name"),
|
||||
("authentik_sources_saml", "0012_usersamlsourceconnection"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="samlsource",
|
||||
name="verification_kp",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
default=None,
|
||||
help_text="When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="+",
|
||||
to="authentik_crypto.certificatekeypair",
|
||||
verbose_name="Verification Certificate",
|
||||
),
|
||||
),
|
||||
migrations.RunPython(migrate_verification_cert),
|
||||
migrations.AlterField(
|
||||
model_name="samlsource",
|
||||
name="signing_kp",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
default=None,
|
||||
help_text="Keypair used to sign outgoing Responses going to the Identity Provider.",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="authentik_crypto.certificatekeypair",
|
||||
verbose_name="Signing Keypair",
|
||||
),
|
||||
),
|
||||
]
|
@ -121,16 +121,27 @@ class SAMLSource(Source):
|
||||
),
|
||||
)
|
||||
|
||||
verification_kp = models.ForeignKey(
|
||||
CertificateKeyPair,
|
||||
default=None,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_(
|
||||
"When selected, incoming assertion's Signatures will be validated against this "
|
||||
"certificate. To allow unsigned Requests, leave on default."
|
||||
),
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_("Verification Certificate"),
|
||||
related_name="+",
|
||||
)
|
||||
signing_kp = models.ForeignKey(
|
||||
CertificateKeyPair,
|
||||
default=None,
|
||||
blank=True,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_("Keypair used to sign outgoing Responses going to the Identity Provider."),
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_("Signing Keypair"),
|
||||
help_text=_(
|
||||
"Keypair which is used to sign outgoing requests. Leave empty to disable signing."
|
||||
),
|
||||
on_delete=models.SET_DEFAULT,
|
||||
)
|
||||
|
||||
digest_algorithm = models.CharField(
|
||||
|
@ -21,7 +21,7 @@ from authentik.core.models import (
|
||||
from authentik.core.sources.flow_manager import SourceFlowManager
|
||||
from authentik.lib.expression.evaluator import BaseEvaluator
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.policies.utils import delete_none_keys
|
||||
from authentik.policies.utils import delete_none_values
|
||||
from authentik.sources.saml.exceptions import (
|
||||
InvalidSignature,
|
||||
MismatchedRequestID,
|
||||
@ -72,7 +72,7 @@ class ResponseProcessor:
|
||||
self._root_xml = b64decode(raw_response.encode())
|
||||
self._root = fromstring(self._root_xml)
|
||||
|
||||
if self._source.signing_kp:
|
||||
if self._source.verification_kp:
|
||||
self._verify_signed()
|
||||
self._verify_request_id()
|
||||
self._verify_status()
|
||||
@ -89,7 +89,7 @@ class ResponseProcessor:
|
||||
|
||||
ctx = xmlsec.SignatureContext()
|
||||
key = xmlsec.Key.from_memory(
|
||||
self._source.signing_kp.certificate_data,
|
||||
self._source.verification_kp.certificate_data,
|
||||
xmlsec.constants.KeyDataFormatCertPem,
|
||||
)
|
||||
ctx.key = key
|
||||
@ -160,7 +160,7 @@ class ResponseProcessor:
|
||||
self._source,
|
||||
self._http_request,
|
||||
name_id,
|
||||
delete_none_keys(self.get_attributes()),
|
||||
delete_none_values(self.get_attributes()),
|
||||
)
|
||||
|
||||
def _get_name_id(self) -> "Element":
|
||||
@ -237,7 +237,7 @@ class ResponseProcessor:
|
||||
self._source,
|
||||
self._http_request,
|
||||
name_id.text,
|
||||
delete_none_keys(self.get_attributes()),
|
||||
delete_none_values(self.get_attributes()),
|
||||
)
|
||||
|
||||
|
||||
|
@ -99,7 +99,7 @@ class AuthenticatorSMSStage(ConfigurableStage, FriendlyNamedStage, Stage):
|
||||
"From": self.from_number,
|
||||
"To": device.phone_number,
|
||||
"Body": token,
|
||||
"Message": self.get_message(token),
|
||||
"Message": str(self.get_message(token)),
|
||||
}
|
||||
|
||||
if self.mapping:
|
||||
|
@ -20,6 +20,7 @@ from authentik.flows.models import FlowDesignation, NotConfiguredAction, Stage
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from authentik.flows.stage import ChallengeStageView
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.root.install_id import get_install_id
|
||||
from authentik.stages.authenticator_sms.models import SMSDevice
|
||||
from authentik.stages.authenticator_validate.challenge import (
|
||||
DeviceChallenge,
|
||||
@ -316,7 +317,7 @@ class AuthenticatorValidateStageView(ChallengeStageView):
|
||||
def cookie_jwt_key(self) -> str:
|
||||
"""Signing key for MFA Cookie for this stage"""
|
||||
return sha256(
|
||||
f"{settings.SECRET_KEY}:{self.executor.current_stage.pk.hex}".encode("ascii")
|
||||
f"{get_install_id()}:{self.executor.current_stage.pk.hex}".encode("ascii")
|
||||
).hexdigest()
|
||||
|
||||
def check_mfa_cookie(self, allowed_devices: list[Device]):
|
||||
|
@ -3,7 +3,6 @@ from datetime import datetime, timedelta
|
||||
from hashlib import sha256
|
||||
from time import sleep
|
||||
|
||||
from django.conf import settings
|
||||
from django.test.client import RequestFactory
|
||||
from django.urls.base import reverse
|
||||
from django_otp.oath import TOTP
|
||||
@ -17,6 +16,7 @@ from authentik.flows.stage import StageView
|
||||
from authentik.flows.tests import FlowTestCase
|
||||
from authentik.flows.views.executor import FlowExecutorView
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.root.install_id import get_install_id
|
||||
from authentik.stages.authenticator_validate.challenge import (
|
||||
get_challenge_for_device,
|
||||
validate_challenge_code,
|
||||
@ -194,7 +194,7 @@ class AuthenticatorValidateStageTOTPTests(FlowTestCase):
|
||||
"stage": stage.pk.hex + generate_id(),
|
||||
"exp": (datetime.now() + timedelta(days=3)).timestamp(),
|
||||
},
|
||||
key=sha256(f"{settings.SECRET_KEY}:{stage.pk.hex}".encode("ascii")).hexdigest(),
|
||||
key=sha256(f"{get_install_id()}:{stage.pk.hex}".encode("ascii")).hexdigest(),
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
@ -233,7 +233,7 @@ class AuthenticatorValidateStageTOTPTests(FlowTestCase):
|
||||
"stage": stage.pk.hex,
|
||||
"exp": (datetime.now() + timedelta(days=3)).timestamp(),
|
||||
},
|
||||
key=sha256(f"{settings.SECRET_KEY}:{stage.pk.hex}".encode("ascii")).hexdigest(),
|
||||
key=sha256(f"{get_install_id()}:{stage.pk.hex}".encode("ascii")).hexdigest(),
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
@ -272,7 +272,7 @@ class AuthenticatorValidateStageTOTPTests(FlowTestCase):
|
||||
"stage": stage.pk.hex,
|
||||
"exp": (datetime.now() - timedelta(days=3)).timestamp(),
|
||||
},
|
||||
key=sha256(f"{settings.SECRET_KEY}:{stage.pk.hex}".encode("ascii")).hexdigest(),
|
||||
key=sha256(f"{get_install_id()}:{stage.pk.hex}".encode("ascii")).hexdigest(),
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
|
@ -8,7 +8,7 @@ from authentik.flows.models import Stage
|
||||
|
||||
|
||||
class DenyStage(Stage):
|
||||
"""Cancells the current flow."""
|
||||
"""Cancels the current flow."""
|
||||
|
||||
@property
|
||||
def serializer(self) -> type[BaseSerializer]:
|
||||
|
@ -5,10 +5,10 @@ from authentik.flows.stage import StageView
|
||||
|
||||
|
||||
class DenyStageView(StageView):
|
||||
"""Cancells the current flow"""
|
||||
"""Cancels the current flow"""
|
||||
|
||||
def get(self, request: HttpRequest) -> HttpResponse:
|
||||
"""Cancells the current flow"""
|
||||
"""Cancels the current flow"""
|
||||
return self.executor.stage_invalid()
|
||||
|
||||
def post(self, request: HttpRequest) -> HttpResponse:
|
||||
|
@ -6,6 +6,7 @@ from django.db import transaction
|
||||
from django.db.utils import IntegrityError, InternalError
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.translation import gettext as _
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from authentik.core.middleware import SESSION_KEY_IMPERSONATE_USER
|
||||
from authentik.core.models import USER_ATTRIBUTE_SOURCES, User, UserSourceConnection
|
||||
@ -148,7 +149,11 @@ class UserWriteStageView(StageView):
|
||||
and SESSION_KEY_IMPERSONATE_USER not in self.request.session
|
||||
):
|
||||
should_update_session = True
|
||||
self.update_user(user)
|
||||
try:
|
||||
self.update_user(user)
|
||||
except ValidationError as exc:
|
||||
self.logger.warning("failed to update user", exc=exc)
|
||||
return self.executor.stage_invalid(_("Failed to update user. Please try again later."))
|
||||
# Extra check to prevent flows from saving a user with a blank username
|
||||
if user.username == "":
|
||||
self.logger.warning("Aborting write to empty username", user=user)
|
||||
@ -162,7 +167,7 @@ class UserWriteStageView(StageView):
|
||||
user.ak_groups.add(*self.executor.plan.context[PLAN_CONTEXT_GROUPS])
|
||||
except (IntegrityError, ValueError, TypeError, InternalError) as exc:
|
||||
self.logger.warning("Failed to save user", exc=exc)
|
||||
return self.executor.stage_invalid(_("Failed to save user"))
|
||||
return self.executor.stage_invalid(_("Failed to update user. Please try again later."))
|
||||
user_write.send(sender=self, request=request, user=user, data=data, created=user_created)
|
||||
# Check if the password has been updated, and update the session auth hash
|
||||
if should_update_session:
|
||||
|
@ -2560,6 +2560,42 @@
|
||||
"$ref": "#/$defs/model_authentik_core.token"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"model",
|
||||
"identifiers"
|
||||
],
|
||||
"properties": {
|
||||
"model": {
|
||||
"const": "authentik_blueprints.metaapplyblueprint"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"state": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"absent",
|
||||
"present",
|
||||
"created"
|
||||
],
|
||||
"default": "present"
|
||||
},
|
||||
"conditions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"attrs": {
|
||||
"$ref": "#/$defs/model_authentik_blueprints.metaapplyblueprint"
|
||||
},
|
||||
"identifiers": {
|
||||
"$ref": "#/$defs/model_authentik_blueprints.metaapplyblueprint"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -3852,8 +3888,7 @@
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"name",
|
||||
"groups"
|
||||
"name"
|
||||
],
|
||||
"title": "User"
|
||||
},
|
||||
@ -4044,8 +4079,7 @@
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"name",
|
||||
"groups"
|
||||
"name"
|
||||
],
|
||||
"title": "User"
|
||||
},
|
||||
@ -4240,8 +4274,7 @@
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"name",
|
||||
"groups"
|
||||
"name"
|
||||
],
|
||||
"title": "User"
|
||||
},
|
||||
@ -5221,10 +5254,15 @@
|
||||
],
|
||||
"title": "Binding type"
|
||||
},
|
||||
"verification_kp": {
|
||||
"type": "integer",
|
||||
"title": "Verification Certificate",
|
||||
"description": "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default."
|
||||
},
|
||||
"signing_kp": {
|
||||
"type": "integer",
|
||||
"title": "Signing Keypair",
|
||||
"description": "Keypair which is used to sign outgoing requests. Leave empty to disable signing."
|
||||
"description": "Keypair used to sign outgoing Responses going to the Identity Provider."
|
||||
},
|
||||
"digest_algorithm": {
|
||||
"type": "string",
|
||||
@ -6383,8 +6421,7 @@
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"name",
|
||||
"groups"
|
||||
"name"
|
||||
],
|
||||
"title": "User"
|
||||
},
|
||||
@ -7119,8 +7156,7 @@
|
||||
},
|
||||
"required": [
|
||||
"username",
|
||||
"name",
|
||||
"groups"
|
||||
"name"
|
||||
],
|
||||
"title": "User"
|
||||
},
|
||||
@ -8192,6 +8228,11 @@
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"title": "Path"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"title": "Password"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
@ -8314,6 +8355,21 @@
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"model_authentik_blueprints.metaapplyblueprint": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"identifiers": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"title": "Identifiers"
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"title": "Required"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ entries:
|
||||
|
||||
# photos supports URLs to images, however authentik might return data URIs
|
||||
avatar = request.user.avatar
|
||||
photos = []
|
||||
photos = None
|
||||
if "://" in avatar:
|
||||
photos = [{"value": avatar, "type": "photo"}]
|
||||
|
||||
@ -31,11 +31,11 @@ entries:
|
||||
|
||||
emails = []
|
||||
if request.user.email != "":
|
||||
emails.append({
|
||||
emails = [{
|
||||
"value": request.user.email,
|
||||
"type": "other",
|
||||
"primary": True,
|
||||
})
|
||||
}]
|
||||
return {
|
||||
"userName": request.user.username,
|
||||
"name": {
|
||||
|
@ -32,7 +32,7 @@ services:
|
||||
volumes:
|
||||
- redis:/data
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.4.1}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.5.2}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
@ -49,8 +49,11 @@ services:
|
||||
ports:
|
||||
- "${COMPOSE_PORT_HTTP:-9000}:9000"
|
||||
- "${COMPOSE_PORT_HTTPS:-9443}:9443"
|
||||
depends_on:
|
||||
- postgresql
|
||||
- redis
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.4.1}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.5.2}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
@ -73,6 +76,9 @@ services:
|
||||
- ./custom-templates:/templates
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
- postgresql
|
||||
- redis
|
||||
|
||||
volumes:
|
||||
database:
|
||||
|
6
go.mod
6
go.mod
@ -23,10 +23,10 @@ require (
|
||||
github.com/nmcclain/ldap v0.0.0-20210720162743-7f8d1e44eeba
|
||||
github.com/pires/go-proxyproto v0.7.0
|
||||
github.com/prometheus/client_golang v1.15.1
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/sirupsen/logrus v1.9.2
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/stretchr/testify v1.8.2
|
||||
goauthentik.io/api/v3 v3.2023041.12
|
||||
github.com/stretchr/testify v1.8.3
|
||||
goauthentik.io/api/v3 v3.2023052.1
|
||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
|
||||
golang.org/x/oauth2 v0.8.0
|
||||
golang.org/x/sync v0.2.0
|
||||
|
13
go.sum
13
go.sum
@ -200,8 +200,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y=
|
||||
github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
@ -211,7 +211,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@ -219,8 +218,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
@ -241,8 +240,8 @@ go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvx
|
||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
|
||||
goauthentik.io/api/v3 v3.2023041.12 h1:lk8eCWYW/P8U4r10RgtIq2NyaAqZ3KKrKc7eierV6aY=
|
||||
goauthentik.io/api/v3 v3.2023041.12/go.mod h1:nYECml4jGbp/541hj8GcylKQG1gVBsKppHy4+7G8u4U=
|
||||
goauthentik.io/api/v3 v3.2023052.1 h1:Sp3sBfkdBJCVTAxZte5fvBU4s0IZm6bqqli8ZawiER4=
|
||||
goauthentik.io/api/v3 v3.2023052.1/go.mod h1:nYECml4jGbp/541hj8GcylKQG1gVBsKppHy4+7G8u4U=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
|
@ -29,4 +29,4 @@ func UserAgent() string {
|
||||
return fmt.Sprintf("authentik@%s", FullVersion())
|
||||
}
|
||||
|
||||
const VERSION = "2023.4.1"
|
||||
const VERSION = "2023.5.2"
|
||||
|
@ -15,6 +15,7 @@ from authentik import get_full_version
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.utils.http import get_http_session
|
||||
from authentik.lib.utils.reflection import get_env
|
||||
from authentik.root.install_id import get_install_id_raw
|
||||
from lifecycle.worker import DjangoUvicornWorker
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -148,9 +149,7 @@ if not CONFIG.y_bool("disable_startup_analytics", False):
|
||||
),
|
||||
},
|
||||
headers={
|
||||
"User-Agent": sha512(str(CONFIG.y("secret_key")).encode("ascii")).hexdigest()[
|
||||
:16
|
||||
],
|
||||
"User-Agent": sha512(get_install_id_raw().encode("ascii")).hexdigest()[:16],
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
timeout=5,
|
||||
|
45
lifecycle/system_migrations/install_id.py
Normal file
45
lifecycle/system_migrations/install_id.py
Normal file
@ -0,0 +1,45 @@
|
||||
# flake8: noqa
|
||||
from uuid import uuid4
|
||||
|
||||
from authentik.lib.config import CONFIG
|
||||
from lifecycle.migrate import BaseMigration
|
||||
|
||||
SQL_STATEMENT = """BEGIN TRANSACTION;
|
||||
CREATE TABLE IF NOT EXISTS authentik_install_id (
|
||||
id TEXT NOT NULL
|
||||
);
|
||||
COMMIT;"""
|
||||
|
||||
|
||||
class Migration(BaseMigration):
|
||||
def needs_migration(self) -> bool:
|
||||
self.cur.execute(
|
||||
"select * from information_schema.tables where table_name = 'authentik_install_id';"
|
||||
)
|
||||
return not bool(self.cur.rowcount)
|
||||
|
||||
def upgrade(self, migrate=False):
|
||||
self.cur.execute(SQL_STATEMENT)
|
||||
self.con.commit()
|
||||
if migrate:
|
||||
# If we already have migrations in the database, assume we're upgrading an existing install
|
||||
# and set the install id to the secret key
|
||||
self.cur.execute(
|
||||
"INSERT INTO authentik_install_id (id) VALUES (%s)", (CONFIG.y("secret_key"),)
|
||||
)
|
||||
else:
|
||||
# Otherwise assume a new install, generate an install ID based on a UUID
|
||||
install_id = str(uuid4())
|
||||
self.cur.execute("INSERT INTO authentik_install_id (id) VALUES (%s)", (install_id,))
|
||||
self.con.commit()
|
||||
|
||||
def run(self):
|
||||
self.cur.execute(
|
||||
"select * from information_schema.tables where table_name = 'django_migrations';"
|
||||
)
|
||||
if not bool(self.cur.rowcount):
|
||||
# No django_migrations table, so generate a new id
|
||||
return self.upgrade(migrate=False)
|
||||
self.cur.execute("select count(*) from django_migrations;")
|
||||
migrations = self.cur.fetchone()[0]
|
||||
return self.upgrade(migrate=migrations > 0)
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-10 17:31+0000\n"
|
||||
"POT-Creation-Date: 2023-05-21 21:59+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -31,12 +31,16 @@ msgstr ""
|
||||
msgid "Validation Error"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/blueprints/api.py:53
|
||||
#: authentik/blueprints/api.py:43
|
||||
msgid "Blueprint file does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/blueprints/api.py:54
|
||||
#, python-format
|
||||
msgid "Failed to validate blueprint: %(logs)s"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/blueprints/api.py:58
|
||||
#: authentik/blueprints/api.py:59
|
||||
msgid "Either path or content must be set."
|
||||
msgstr ""
|
||||
|
||||
@ -321,105 +325,105 @@ msgstr ""
|
||||
msgid "Certificate-Key Pairs"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:293
|
||||
#: authentik/events/models.py:290
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:294
|
||||
#: authentik/events/models.py:291
|
||||
msgid "Events"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:300
|
||||
#: authentik/events/models.py:297
|
||||
msgid "authentik inbuilt notifications"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:301
|
||||
#: authentik/events/models.py:298
|
||||
msgid "Generic Webhook"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:302
|
||||
#: authentik/events/models.py:299
|
||||
msgid "Slack Webhook (Slack/Discord)"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:303
|
||||
#: authentik/events/models.py:300
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:321
|
||||
#: authentik/events/models.py:318
|
||||
msgid ""
|
||||
"Only send notification once, for example when sending a webhook into a chat "
|
||||
"channel."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:386
|
||||
#: authentik/events/models.py:383
|
||||
msgid "Severity"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:391
|
||||
#: authentik/events/models.py:388
|
||||
msgid "Dispatched for user"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:400
|
||||
#: authentik/events/models.py:397
|
||||
msgid "Event user"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:487
|
||||
#: authentik/events/models.py:484
|
||||
msgid "Notification Transport"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:488
|
||||
#: authentik/events/models.py:485
|
||||
msgid "Notification Transports"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:494
|
||||
#: authentik/events/models.py:491
|
||||
msgid "Notice"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:495
|
||||
#: authentik/events/models.py:492
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:496
|
||||
#: authentik/events/models.py:493
|
||||
msgid "Alert"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:521
|
||||
#: authentik/events/models.py:518
|
||||
msgid "Notification"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:522
|
||||
#: authentik/events/models.py:519
|
||||
msgid "Notifications"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:532
|
||||
#: authentik/events/models.py:529
|
||||
msgid ""
|
||||
"Select which transports should be used to notify the user. If none are "
|
||||
"selected, the notification will only be shown in the authentik UI."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:540
|
||||
#: authentik/events/models.py:537
|
||||
msgid "Controls which severity level the created notifications will have."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:545
|
||||
#: authentik/events/models.py:542
|
||||
msgid ""
|
||||
"Define which group of users this notification should be sent and shown to. "
|
||||
"If left empty, Notification won't ben sent."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:563
|
||||
#: authentik/events/models.py:560
|
||||
msgid "Notification Rule"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:564
|
||||
#: authentik/events/models.py:561
|
||||
msgid "Notification Rules"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:584
|
||||
#: authentik/events/models.py:581
|
||||
msgid "Webhook Mapping"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:585
|
||||
#: authentik/events/models.py:582
|
||||
msgid "Webhook Mappings"
|
||||
msgstr ""
|
||||
|
||||
@ -1283,49 +1287,49 @@ msgid ""
|
||||
"minutes=2;seconds=3)."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:139
|
||||
#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:150
|
||||
msgid "SHA1"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:140
|
||||
#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:151
|
||||
msgid "SHA256"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:141
|
||||
#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:152
|
||||
msgid "SHA384"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:142
|
||||
#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:153
|
||||
msgid "SHA512"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:149
|
||||
#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:160
|
||||
msgid "RSA-SHA1"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:150
|
||||
#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:161
|
||||
msgid "RSA-SHA256"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:151
|
||||
#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:162
|
||||
msgid "RSA-SHA384"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:152
|
||||
#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:163
|
||||
msgid "RSA-SHA512"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:153
|
||||
#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:164
|
||||
msgid "DSA-SHA1"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:124
|
||||
#: authentik/providers/saml/models.py:124 authentik/sources/saml/models.py:130
|
||||
msgid ""
|
||||
"When selected, incoming assertion's Signatures will be validated against "
|
||||
"this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:128
|
||||
#: authentik/providers/saml/models.py:128 authentik/sources/saml/models.py:134
|
||||
msgid "Verification Certificate"
|
||||
msgstr ""
|
||||
|
||||
@ -1333,7 +1337,7 @@ msgstr ""
|
||||
msgid "Keypair used to sign outgoing Responses going to the Service Provider."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:129
|
||||
#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:144
|
||||
msgid "Signing Keypair"
|
||||
msgstr ""
|
||||
|
||||
@ -1381,33 +1385,33 @@ msgstr ""
|
||||
msgid "SCIM Mappings"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/scim/tasks.py:50
|
||||
#: authentik/providers/scim/tasks.py:52
|
||||
msgid "Starting full SCIM sync"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/scim/tasks.py:57
|
||||
#: authentik/providers/scim/tasks.py:59
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/scim/tasks.py:61
|
||||
#: authentik/providers/scim/tasks.py:63
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of groups"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/scim/tasks.py:90
|
||||
#: authentik/providers/scim/tasks.py:92
|
||||
#, python-format
|
||||
msgid "Failed to sync user due to remote error %(name)s: %(error)s"
|
||||
msgid "Failed to sync user %(user_name)s due to remote error: %(error)s"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/scim/tasks.py:101 authentik/providers/scim/tasks.py:142
|
||||
#: authentik/providers/scim/tasks.py:103 authentik/providers/scim/tasks.py:144
|
||||
#, python-format
|
||||
msgid "Stopping sync due to error: %(error)s"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/scim/tasks.py:131
|
||||
#: authentik/providers/scim/tasks.py:133
|
||||
#, python-format
|
||||
msgid "Failed to sync group due to remote error %(name)s: %(error)s"
|
||||
msgid "Failed to sync group %(group_name)s due to remote error: %(error)s"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/recovery/management/commands/create_admin_group.py:11
|
||||
@ -1498,7 +1502,7 @@ msgstr ""
|
||||
msgid "LDAP Property Mappings"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/signals.py:56
|
||||
#: authentik/sources/ldap/signals.py:59
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr ""
|
||||
|
||||
@ -1764,25 +1768,23 @@ msgid ""
|
||||
"manually. (Format: hours=1;minutes=2;seconds=3)."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/models.py:131
|
||||
msgid ""
|
||||
"Keypair which is used to sign outgoing requests. Leave empty to disable "
|
||||
"signing."
|
||||
#: authentik/sources/saml/models.py:142
|
||||
msgid "Keypair used to sign outgoing Responses going to the Identity Provider."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/models.py:215
|
||||
#: authentik/sources/saml/models.py:226
|
||||
msgid "SAML Source"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/models.py:216
|
||||
#: authentik/sources/saml/models.py:227
|
||||
msgid "SAML Sources"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/models.py:231
|
||||
#: authentik/sources/saml/models.py:242
|
||||
msgid "User SAML Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/models.py:232
|
||||
#: authentik/sources/saml/models.py:243
|
||||
msgid "User SAML Source Connections"
|
||||
msgstr ""
|
||||
|
||||
@ -2106,6 +2108,10 @@ msgid ""
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/identification/api.py:20
|
||||
msgid "When no user fields are selected, at least one source must be selected"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/identification/models.py:29
|
||||
msgid ""
|
||||
"Fields of the user object to match against. (Hold shift to select multiple "
|
||||
@ -2397,16 +2403,17 @@ msgstr ""
|
||||
msgid "User Write Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/user_write/stage.py:132
|
||||
#: authentik/stages/user_write/stage.py:133
|
||||
msgid "No Pending data."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/user_write/stage.py:138
|
||||
#: authentik/stages/user_write/stage.py:139
|
||||
msgid "No user found and can't create new user."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/user_write/stage.py:165
|
||||
msgid "Failed to save user"
|
||||
#: authentik/stages/user_write/stage.py:156
|
||||
#: authentik/stages/user_write/stage.py:170
|
||||
msgid "Failed to update user. Please try again later."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/tenants/models.py:23
|
||||
|
@ -14,7 +14,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-10 17:31+0000\n"
|
||||
"POT-Creation-Date: 2023-05-21 21:59+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: deluxghost, 2023\n"
|
||||
"Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n"
|
||||
@ -37,12 +37,16 @@ msgstr "通用 API 错误"
|
||||
msgid "Validation Error"
|
||||
msgstr "校验错误"
|
||||
|
||||
#: authentik/blueprints/api.py:53
|
||||
#: authentik/blueprints/api.py:43
|
||||
msgid "Blueprint file does not exist"
|
||||
msgstr "蓝图文件不存在"
|
||||
|
||||
#: authentik/blueprints/api.py:54
|
||||
#, python-format
|
||||
msgid "Failed to validate blueprint: %(logs)s"
|
||||
msgstr "验证蓝图失败:%(logs)s"
|
||||
|
||||
#: authentik/blueprints/api.py:58
|
||||
#: authentik/blueprints/api.py:59
|
||||
msgid "Either path or content must be set."
|
||||
msgstr "必须设置路径或内容。"
|
||||
|
||||
@ -337,105 +341,105 @@ msgstr "证书密钥对"
|
||||
msgid "Certificate-Key Pairs"
|
||||
msgstr "证书密钥对"
|
||||
|
||||
#: authentik/events/models.py:293
|
||||
#: authentik/events/models.py:290
|
||||
msgid "Event"
|
||||
msgstr "事件"
|
||||
|
||||
#: authentik/events/models.py:294
|
||||
#: authentik/events/models.py:291
|
||||
msgid "Events"
|
||||
msgstr "事件"
|
||||
|
||||
#: authentik/events/models.py:300
|
||||
#: authentik/events/models.py:297
|
||||
msgid "authentik inbuilt notifications"
|
||||
msgstr "authentik 内置通知"
|
||||
|
||||
#: authentik/events/models.py:301
|
||||
#: authentik/events/models.py:298
|
||||
msgid "Generic Webhook"
|
||||
msgstr "通用 Webhook"
|
||||
|
||||
#: authentik/events/models.py:302
|
||||
#: authentik/events/models.py:299
|
||||
msgid "Slack Webhook (Slack/Discord)"
|
||||
msgstr "Slack Webhook(Slack/Discord)"
|
||||
|
||||
#: authentik/events/models.py:303
|
||||
#: authentik/events/models.py:300
|
||||
msgid "Email"
|
||||
msgstr "电子邮箱"
|
||||
|
||||
#: authentik/events/models.py:321
|
||||
#: authentik/events/models.py:318
|
||||
msgid ""
|
||||
"Only send notification once, for example when sending a webhook into a chat "
|
||||
"channel."
|
||||
msgstr "仅发送一次通知,例如在向聊天频道发送 Webhook 时。"
|
||||
|
||||
#: authentik/events/models.py:386
|
||||
#: authentik/events/models.py:383
|
||||
msgid "Severity"
|
||||
msgstr "严重程度"
|
||||
|
||||
#: authentik/events/models.py:391
|
||||
#: authentik/events/models.py:388
|
||||
msgid "Dispatched for user"
|
||||
msgstr "为用户分派"
|
||||
|
||||
#: authentik/events/models.py:400
|
||||
#: authentik/events/models.py:397
|
||||
msgid "Event user"
|
||||
msgstr "事件用户"
|
||||
|
||||
#: authentik/events/models.py:487
|
||||
#: authentik/events/models.py:484
|
||||
msgid "Notification Transport"
|
||||
msgstr "通知传输"
|
||||
|
||||
#: authentik/events/models.py:488
|
||||
#: authentik/events/models.py:485
|
||||
msgid "Notification Transports"
|
||||
msgstr "通知传输"
|
||||
|
||||
#: authentik/events/models.py:494
|
||||
#: authentik/events/models.py:491
|
||||
msgid "Notice"
|
||||
msgstr "通知"
|
||||
|
||||
#: authentik/events/models.py:495
|
||||
#: authentik/events/models.py:492
|
||||
msgid "Warning"
|
||||
msgstr "警告"
|
||||
|
||||
#: authentik/events/models.py:496
|
||||
#: authentik/events/models.py:493
|
||||
msgid "Alert"
|
||||
msgstr "注意"
|
||||
|
||||
#: authentik/events/models.py:521
|
||||
#: authentik/events/models.py:518
|
||||
msgid "Notification"
|
||||
msgstr "通知"
|
||||
|
||||
#: authentik/events/models.py:522
|
||||
#: authentik/events/models.py:519
|
||||
msgid "Notifications"
|
||||
msgstr "通知"
|
||||
|
||||
#: authentik/events/models.py:532
|
||||
#: authentik/events/models.py:529
|
||||
msgid ""
|
||||
"Select which transports should be used to notify the user. If none are "
|
||||
"selected, the notification will only be shown in the authentik UI."
|
||||
msgstr "选择应使用哪些传输方式来通知用户。如果未选择任何内容,则通知将仅显示在 authentik UI 中。"
|
||||
|
||||
#: authentik/events/models.py:540
|
||||
#: authentik/events/models.py:537
|
||||
msgid "Controls which severity level the created notifications will have."
|
||||
msgstr "控制被创建的通知的严重性级别。"
|
||||
|
||||
#: authentik/events/models.py:545
|
||||
#: authentik/events/models.py:542
|
||||
msgid ""
|
||||
"Define which group of users this notification should be sent and shown to. "
|
||||
"If left empty, Notification won't ben sent."
|
||||
msgstr "定义此通知应该发送到哪些用户组。如果留空,则不会发送通知。"
|
||||
|
||||
#: authentik/events/models.py:563
|
||||
#: authentik/events/models.py:560
|
||||
msgid "Notification Rule"
|
||||
msgstr "通知规则"
|
||||
|
||||
#: authentik/events/models.py:564
|
||||
#: authentik/events/models.py:561
|
||||
msgid "Notification Rules"
|
||||
msgstr "通知规则"
|
||||
|
||||
#: authentik/events/models.py:584
|
||||
#: authentik/events/models.py:581
|
||||
msgid "Webhook Mapping"
|
||||
msgstr "Webhook 映射"
|
||||
|
||||
#: authentik/events/models.py:585
|
||||
#: authentik/events/models.py:582
|
||||
msgid "Webhook Mappings"
|
||||
msgstr "Webhook 映射"
|
||||
|
||||
@ -1312,49 +1316,49 @@ msgid ""
|
||||
"hours=1;minutes=2;seconds=3)."
|
||||
msgstr "从当前时间经过多久时或之后,会话无效(格式:hours=1;minutes=2;seconds=3)。"
|
||||
|
||||
#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:139
|
||||
#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:150
|
||||
msgid "SHA1"
|
||||
msgstr "SHA1"
|
||||
|
||||
#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:140
|
||||
#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:151
|
||||
msgid "SHA256"
|
||||
msgstr "SHA256"
|
||||
|
||||
#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:141
|
||||
#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:152
|
||||
msgid "SHA384"
|
||||
msgstr "SHA384"
|
||||
|
||||
#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:142
|
||||
#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:153
|
||||
msgid "SHA512"
|
||||
msgstr "SHA512"
|
||||
|
||||
#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:149
|
||||
#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:160
|
||||
msgid "RSA-SHA1"
|
||||
msgstr "RSA-SHA1"
|
||||
|
||||
#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:150
|
||||
#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:161
|
||||
msgid "RSA-SHA256"
|
||||
msgstr "RSA-SHA256"
|
||||
|
||||
#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:151
|
||||
#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:162
|
||||
msgid "RSA-SHA384"
|
||||
msgstr "RSA-SHA384"
|
||||
|
||||
#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:152
|
||||
#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:163
|
||||
msgid "RSA-SHA512"
|
||||
msgstr "RSA-SHA512"
|
||||
|
||||
#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:153
|
||||
#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:164
|
||||
msgid "DSA-SHA1"
|
||||
msgstr "DSA-SHA1"
|
||||
|
||||
#: authentik/providers/saml/models.py:124
|
||||
#: authentik/providers/saml/models.py:124 authentik/sources/saml/models.py:130
|
||||
msgid ""
|
||||
"When selected, incoming assertion's Signatures will be validated against "
|
||||
"this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr "选中后,传入断言的签名将根据此证书进行验证。要允许未签名的请求,请保留默认值。"
|
||||
|
||||
#: authentik/providers/saml/models.py:128
|
||||
#: authentik/providers/saml/models.py:128 authentik/sources/saml/models.py:134
|
||||
msgid "Verification Certificate"
|
||||
msgstr "验证证书"
|
||||
|
||||
@ -1362,7 +1366,7 @@ msgstr "验证证书"
|
||||
msgid "Keypair used to sign outgoing Responses going to the Service Provider."
|
||||
msgstr "密钥对,用于签署发送给服务提供程序的传出响应。"
|
||||
|
||||
#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:129
|
||||
#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:144
|
||||
msgid "Signing Keypair"
|
||||
msgstr "签名密钥对"
|
||||
|
||||
@ -1410,34 +1414,34 @@ msgstr "SCIM 映射"
|
||||
msgid "SCIM Mappings"
|
||||
msgstr "SCIM 映射"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:50
|
||||
#: authentik/providers/scim/tasks.py:52
|
||||
msgid "Starting full SCIM sync"
|
||||
msgstr "开始全量 SCIM 同步"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:57
|
||||
#: authentik/providers/scim/tasks.py:59
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of users"
|
||||
msgstr "正在同步用户页面 %(page)d"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:61
|
||||
#: authentik/providers/scim/tasks.py:63
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of groups"
|
||||
msgstr "正在同步群组页面 %(page)d"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:90
|
||||
#: authentik/providers/scim/tasks.py:92
|
||||
#, python-format
|
||||
msgid "Failed to sync user due to remote error %(name)s: %(error)s"
|
||||
msgstr "由于远端错误 %(name)s,同步用户失败:%(error)s"
|
||||
msgid "Failed to sync user %(user_name)s due to remote error: %(error)s"
|
||||
msgstr "由于远端错误,同步用户 %(user_name)s 失败:%(error)s"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:101 authentik/providers/scim/tasks.py:142
|
||||
#: authentik/providers/scim/tasks.py:103 authentik/providers/scim/tasks.py:144
|
||||
#, python-format
|
||||
msgid "Stopping sync due to error: %(error)s"
|
||||
msgstr "由于以下错误,同步停止:%(error)s"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:131
|
||||
#: authentik/providers/scim/tasks.py:133
|
||||
#, python-format
|
||||
msgid "Failed to sync group due to remote error %(name)s: %(error)s"
|
||||
msgstr "由于远端错误 %(name)s,同步群组失败:%(error)s"
|
||||
msgid "Failed to sync group %(group_name)s due to remote error: %(error)s"
|
||||
msgstr "由于远端错误,同步组 %(group_name)s 失败:%(error)s"
|
||||
|
||||
#: authentik/recovery/management/commands/create_admin_group.py:11
|
||||
msgid "Create admin group if the default group gets deleted."
|
||||
@ -1527,7 +1531,7 @@ msgstr "LDAP 属性映射"
|
||||
msgid "LDAP Property Mappings"
|
||||
msgstr "LDAP 属性映射"
|
||||
|
||||
#: authentik/sources/ldap/signals.py:56
|
||||
#: authentik/sources/ldap/signals.py:59
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr "密码与 Active Directory 复杂度不匹配。"
|
||||
|
||||
@ -1797,25 +1801,24 @@ msgstr ""
|
||||
"删除临时用户的时间偏移。这仅适用于您的 IDP 使用 NameID 格式 'transient' "
|
||||
"且用户未手动登出的情况。(格式:hours=1;minutes=2;seconds=3)。"
|
||||
|
||||
#: authentik/sources/saml/models.py:131
|
||||
#: authentik/sources/saml/models.py:142
|
||||
msgid ""
|
||||
"Keypair which is used to sign outgoing requests. Leave empty to disable "
|
||||
"signing."
|
||||
msgstr "用于签署传出请求的密钥对。留空则禁用签名。"
|
||||
"Keypair used to sign outgoing Responses going to the Identity Provider."
|
||||
msgstr "密钥对,用于签署发送给身份提供程序的传出响应。"
|
||||
|
||||
#: authentik/sources/saml/models.py:215
|
||||
#: authentik/sources/saml/models.py:226
|
||||
msgid "SAML Source"
|
||||
msgstr "SAML 源"
|
||||
|
||||
#: authentik/sources/saml/models.py:216
|
||||
#: authentik/sources/saml/models.py:227
|
||||
msgid "SAML Sources"
|
||||
msgstr "SAML 源"
|
||||
|
||||
#: authentik/sources/saml/models.py:231
|
||||
#: authentik/sources/saml/models.py:242
|
||||
msgid "User SAML Source Connection"
|
||||
msgstr "用户 SAML 源连接"
|
||||
|
||||
#: authentik/sources/saml/models.py:232
|
||||
#: authentik/sources/saml/models.py:243
|
||||
msgid "User SAML Source Connections"
|
||||
msgstr "用户 SAML 源连接"
|
||||
|
||||
@ -2150,6 +2153,10 @@ msgstr ""
|
||||
" 这是一封测试电子邮件,用于通知您已成功配置 authentik 电子邮件。\n"
|
||||
" "
|
||||
|
||||
#: authentik/stages/identification/api.py:20
|
||||
msgid "When no user fields are selected, at least one source must be selected"
|
||||
msgstr "如果未选择用户字段,则至少要选择一个源"
|
||||
|
||||
#: authentik/stages/identification/models.py:29
|
||||
msgid ""
|
||||
"Fields of the user object to match against. (Hold shift to select multiple "
|
||||
@ -2443,17 +2450,18 @@ msgstr "用户写入阶段"
|
||||
msgid "User Write Stages"
|
||||
msgstr "用户写入阶段"
|
||||
|
||||
#: authentik/stages/user_write/stage.py:132
|
||||
#: authentik/stages/user_write/stage.py:133
|
||||
msgid "No Pending data."
|
||||
msgstr "没有待处理的数据。"
|
||||
|
||||
#: authentik/stages/user_write/stage.py:138
|
||||
#: authentik/stages/user_write/stage.py:139
|
||||
msgid "No user found and can't create new user."
|
||||
msgstr "未找到用户并且无法创建新用户。"
|
||||
|
||||
#: authentik/stages/user_write/stage.py:165
|
||||
msgid "Failed to save user"
|
||||
msgstr "保存用户失败"
|
||||
#: authentik/stages/user_write/stage.py:156
|
||||
#: authentik/stages/user_write/stage.py:170
|
||||
msgid "Failed to update user. Please try again later."
|
||||
msgstr "更新用户失败。请稍后重试。"
|
||||
|
||||
#: authentik/tenants/models.py:23
|
||||
msgid ""
|
||||
|
@ -14,7 +14,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-05-10 17:31+0000\n"
|
||||
"POT-Creation-Date: 2023-05-21 21:59+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: deluxghost, 2023\n"
|
||||
"Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n"
|
||||
@ -37,12 +37,16 @@ msgstr "通用 API 错误"
|
||||
msgid "Validation Error"
|
||||
msgstr "校验错误"
|
||||
|
||||
#: authentik/blueprints/api.py:53
|
||||
#: authentik/blueprints/api.py:43
|
||||
msgid "Blueprint file does not exist"
|
||||
msgstr "蓝图文件不存在"
|
||||
|
||||
#: authentik/blueprints/api.py:54
|
||||
#, python-format
|
||||
msgid "Failed to validate blueprint: %(logs)s"
|
||||
msgstr "验证蓝图失败:%(logs)s"
|
||||
|
||||
#: authentik/blueprints/api.py:58
|
||||
#: authentik/blueprints/api.py:59
|
||||
msgid "Either path or content must be set."
|
||||
msgstr "必须设置路径或内容。"
|
||||
|
||||
@ -337,105 +341,105 @@ msgstr "证书密钥对"
|
||||
msgid "Certificate-Key Pairs"
|
||||
msgstr "证书密钥对"
|
||||
|
||||
#: authentik/events/models.py:293
|
||||
#: authentik/events/models.py:290
|
||||
msgid "Event"
|
||||
msgstr "事件"
|
||||
|
||||
#: authentik/events/models.py:294
|
||||
#: authentik/events/models.py:291
|
||||
msgid "Events"
|
||||
msgstr "事件"
|
||||
|
||||
#: authentik/events/models.py:300
|
||||
#: authentik/events/models.py:297
|
||||
msgid "authentik inbuilt notifications"
|
||||
msgstr "authentik 内置通知"
|
||||
|
||||
#: authentik/events/models.py:301
|
||||
#: authentik/events/models.py:298
|
||||
msgid "Generic Webhook"
|
||||
msgstr "通用 Webhook"
|
||||
|
||||
#: authentik/events/models.py:302
|
||||
#: authentik/events/models.py:299
|
||||
msgid "Slack Webhook (Slack/Discord)"
|
||||
msgstr "Slack Webhook(Slack/Discord)"
|
||||
|
||||
#: authentik/events/models.py:303
|
||||
#: authentik/events/models.py:300
|
||||
msgid "Email"
|
||||
msgstr "电子邮箱"
|
||||
|
||||
#: authentik/events/models.py:321
|
||||
#: authentik/events/models.py:318
|
||||
msgid ""
|
||||
"Only send notification once, for example when sending a webhook into a chat "
|
||||
"channel."
|
||||
msgstr "仅发送一次通知,例如在向聊天频道发送 Webhook 时。"
|
||||
|
||||
#: authentik/events/models.py:386
|
||||
#: authentik/events/models.py:383
|
||||
msgid "Severity"
|
||||
msgstr "严重程度"
|
||||
|
||||
#: authentik/events/models.py:391
|
||||
#: authentik/events/models.py:388
|
||||
msgid "Dispatched for user"
|
||||
msgstr "为用户分派"
|
||||
|
||||
#: authentik/events/models.py:400
|
||||
#: authentik/events/models.py:397
|
||||
msgid "Event user"
|
||||
msgstr "事件用户"
|
||||
|
||||
#: authentik/events/models.py:487
|
||||
#: authentik/events/models.py:484
|
||||
msgid "Notification Transport"
|
||||
msgstr "通知传输"
|
||||
|
||||
#: authentik/events/models.py:488
|
||||
#: authentik/events/models.py:485
|
||||
msgid "Notification Transports"
|
||||
msgstr "通知传输"
|
||||
|
||||
#: authentik/events/models.py:494
|
||||
#: authentik/events/models.py:491
|
||||
msgid "Notice"
|
||||
msgstr "通知"
|
||||
|
||||
#: authentik/events/models.py:495
|
||||
#: authentik/events/models.py:492
|
||||
msgid "Warning"
|
||||
msgstr "警告"
|
||||
|
||||
#: authentik/events/models.py:496
|
||||
#: authentik/events/models.py:493
|
||||
msgid "Alert"
|
||||
msgstr "注意"
|
||||
|
||||
#: authentik/events/models.py:521
|
||||
#: authentik/events/models.py:518
|
||||
msgid "Notification"
|
||||
msgstr "通知"
|
||||
|
||||
#: authentik/events/models.py:522
|
||||
#: authentik/events/models.py:519
|
||||
msgid "Notifications"
|
||||
msgstr "通知"
|
||||
|
||||
#: authentik/events/models.py:532
|
||||
#: authentik/events/models.py:529
|
||||
msgid ""
|
||||
"Select which transports should be used to notify the user. If none are "
|
||||
"selected, the notification will only be shown in the authentik UI."
|
||||
msgstr "选择应使用哪些传输方式来通知用户。如果未选择任何内容,则通知将仅显示在 authentik UI 中。"
|
||||
|
||||
#: authentik/events/models.py:540
|
||||
#: authentik/events/models.py:537
|
||||
msgid "Controls which severity level the created notifications will have."
|
||||
msgstr "控制被创建的通知的严重性级别。"
|
||||
|
||||
#: authentik/events/models.py:545
|
||||
#: authentik/events/models.py:542
|
||||
msgid ""
|
||||
"Define which group of users this notification should be sent and shown to. "
|
||||
"If left empty, Notification won't ben sent."
|
||||
msgstr "定义此通知应该发送到哪些用户组。如果留空,则不会发送通知。"
|
||||
|
||||
#: authentik/events/models.py:563
|
||||
#: authentik/events/models.py:560
|
||||
msgid "Notification Rule"
|
||||
msgstr "通知规则"
|
||||
|
||||
#: authentik/events/models.py:564
|
||||
#: authentik/events/models.py:561
|
||||
msgid "Notification Rules"
|
||||
msgstr "通知规则"
|
||||
|
||||
#: authentik/events/models.py:584
|
||||
#: authentik/events/models.py:581
|
||||
msgid "Webhook Mapping"
|
||||
msgstr "Webhook 映射"
|
||||
|
||||
#: authentik/events/models.py:585
|
||||
#: authentik/events/models.py:582
|
||||
msgid "Webhook Mappings"
|
||||
msgstr "Webhook 映射"
|
||||
|
||||
@ -1312,49 +1316,49 @@ msgid ""
|
||||
"hours=1;minutes=2;seconds=3)."
|
||||
msgstr "从当前时间经过多久时或之后,会话无效(格式:hours=1;minutes=2;seconds=3)。"
|
||||
|
||||
#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:139
|
||||
#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:150
|
||||
msgid "SHA1"
|
||||
msgstr "SHA1"
|
||||
|
||||
#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:140
|
||||
#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:151
|
||||
msgid "SHA256"
|
||||
msgstr "SHA256"
|
||||
|
||||
#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:141
|
||||
#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:152
|
||||
msgid "SHA384"
|
||||
msgstr "SHA384"
|
||||
|
||||
#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:142
|
||||
#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:153
|
||||
msgid "SHA512"
|
||||
msgstr "SHA512"
|
||||
|
||||
#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:149
|
||||
#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:160
|
||||
msgid "RSA-SHA1"
|
||||
msgstr "RSA-SHA1"
|
||||
|
||||
#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:150
|
||||
#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:161
|
||||
msgid "RSA-SHA256"
|
||||
msgstr "RSA-SHA256"
|
||||
|
||||
#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:151
|
||||
#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:162
|
||||
msgid "RSA-SHA384"
|
||||
msgstr "RSA-SHA384"
|
||||
|
||||
#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:152
|
||||
#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:163
|
||||
msgid "RSA-SHA512"
|
||||
msgstr "RSA-SHA512"
|
||||
|
||||
#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:153
|
||||
#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:164
|
||||
msgid "DSA-SHA1"
|
||||
msgstr "DSA-SHA1"
|
||||
|
||||
#: authentik/providers/saml/models.py:124
|
||||
#: authentik/providers/saml/models.py:124 authentik/sources/saml/models.py:130
|
||||
msgid ""
|
||||
"When selected, incoming assertion's Signatures will be validated against "
|
||||
"this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr "选中后,传入断言的签名将根据此证书进行验证。要允许未签名的请求,请保留默认值。"
|
||||
|
||||
#: authentik/providers/saml/models.py:128
|
||||
#: authentik/providers/saml/models.py:128 authentik/sources/saml/models.py:134
|
||||
msgid "Verification Certificate"
|
||||
msgstr "验证证书"
|
||||
|
||||
@ -1362,7 +1366,7 @@ msgstr "验证证书"
|
||||
msgid "Keypair used to sign outgoing Responses going to the Service Provider."
|
||||
msgstr "密钥对,用于签署发送给服务提供程序的传出响应。"
|
||||
|
||||
#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:129
|
||||
#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:144
|
||||
msgid "Signing Keypair"
|
||||
msgstr "签名密钥对"
|
||||
|
||||
@ -1410,34 +1414,34 @@ msgstr "SCIM 映射"
|
||||
msgid "SCIM Mappings"
|
||||
msgstr "SCIM 映射"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:50
|
||||
#: authentik/providers/scim/tasks.py:52
|
||||
msgid "Starting full SCIM sync"
|
||||
msgstr "开始全量 SCIM 同步"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:57
|
||||
#: authentik/providers/scim/tasks.py:59
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of users"
|
||||
msgstr "正在同步用户页面 %(page)d"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:61
|
||||
#: authentik/providers/scim/tasks.py:63
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of groups"
|
||||
msgstr "正在同步群组页面 %(page)d"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:90
|
||||
#: authentik/providers/scim/tasks.py:92
|
||||
#, python-format
|
||||
msgid "Failed to sync user due to remote error %(name)s: %(error)s"
|
||||
msgstr "由于远端错误 %(name)s,同步用户失败:%(error)s"
|
||||
msgid "Failed to sync user %(user_name)s due to remote error: %(error)s"
|
||||
msgstr "由于远端错误,同步用户 %(user_name)s 失败:%(error)s"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:101 authentik/providers/scim/tasks.py:142
|
||||
#: authentik/providers/scim/tasks.py:103 authentik/providers/scim/tasks.py:144
|
||||
#, python-format
|
||||
msgid "Stopping sync due to error: %(error)s"
|
||||
msgstr "由于以下错误,同步停止:%(error)s"
|
||||
|
||||
#: authentik/providers/scim/tasks.py:131
|
||||
#: authentik/providers/scim/tasks.py:133
|
||||
#, python-format
|
||||
msgid "Failed to sync group due to remote error %(name)s: %(error)s"
|
||||
msgstr "由于远端错误 %(name)s,同步群组失败:%(error)s"
|
||||
msgid "Failed to sync group %(group_name)s due to remote error: %(error)s"
|
||||
msgstr "由于远端错误,同步组 %(group_name)s 失败:%(error)s"
|
||||
|
||||
#: authentik/recovery/management/commands/create_admin_group.py:11
|
||||
msgid "Create admin group if the default group gets deleted."
|
||||
@ -1527,7 +1531,7 @@ msgstr "LDAP 属性映射"
|
||||
msgid "LDAP Property Mappings"
|
||||
msgstr "LDAP 属性映射"
|
||||
|
||||
#: authentik/sources/ldap/signals.py:56
|
||||
#: authentik/sources/ldap/signals.py:59
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr "密码与 Active Directory 复杂度不匹配。"
|
||||
|
||||
@ -1797,25 +1801,24 @@ msgstr ""
|
||||
"删除临时用户的时间偏移。这仅适用于您的 IDP 使用 NameID 格式 'transient' "
|
||||
"且用户未手动登出的情况。(格式:hours=1;minutes=2;seconds=3)。"
|
||||
|
||||
#: authentik/sources/saml/models.py:131
|
||||
#: authentik/sources/saml/models.py:142
|
||||
msgid ""
|
||||
"Keypair which is used to sign outgoing requests. Leave empty to disable "
|
||||
"signing."
|
||||
msgstr "用于签署传出请求的密钥对。留空则禁用签名。"
|
||||
"Keypair used to sign outgoing Responses going to the Identity Provider."
|
||||
msgstr "密钥对,用于签署发送给身份提供程序的传出响应。"
|
||||
|
||||
#: authentik/sources/saml/models.py:215
|
||||
#: authentik/sources/saml/models.py:226
|
||||
msgid "SAML Source"
|
||||
msgstr "SAML 源"
|
||||
|
||||
#: authentik/sources/saml/models.py:216
|
||||
#: authentik/sources/saml/models.py:227
|
||||
msgid "SAML Sources"
|
||||
msgstr "SAML 源"
|
||||
|
||||
#: authentik/sources/saml/models.py:231
|
||||
#: authentik/sources/saml/models.py:242
|
||||
msgid "User SAML Source Connection"
|
||||
msgstr "用户 SAML 源连接"
|
||||
|
||||
#: authentik/sources/saml/models.py:232
|
||||
#: authentik/sources/saml/models.py:243
|
||||
msgid "User SAML Source Connections"
|
||||
msgstr "用户 SAML 源连接"
|
||||
|
||||
@ -2150,6 +2153,10 @@ msgstr ""
|
||||
" 这是一封测试电子邮件,用于通知您已成功配置 authentik 电子邮件。\n"
|
||||
" "
|
||||
|
||||
#: authentik/stages/identification/api.py:20
|
||||
msgid "When no user fields are selected, at least one source must be selected"
|
||||
msgstr "如果未选择用户字段,则至少要选择一个源"
|
||||
|
||||
#: authentik/stages/identification/models.py:29
|
||||
msgid ""
|
||||
"Fields of the user object to match against. (Hold shift to select multiple "
|
||||
@ -2443,17 +2450,18 @@ msgstr "用户写入阶段"
|
||||
msgid "User Write Stages"
|
||||
msgstr "用户写入阶段"
|
||||
|
||||
#: authentik/stages/user_write/stage.py:132
|
||||
#: authentik/stages/user_write/stage.py:133
|
||||
msgid "No Pending data."
|
||||
msgstr "没有待处理的数据。"
|
||||
|
||||
#: authentik/stages/user_write/stage.py:138
|
||||
#: authentik/stages/user_write/stage.py:139
|
||||
msgid "No user found and can't create new user."
|
||||
msgstr "未找到用户并且无法创建新用户。"
|
||||
|
||||
#: authentik/stages/user_write/stage.py:165
|
||||
msgid "Failed to save user"
|
||||
msgstr "保存用户失败"
|
||||
#: authentik/stages/user_write/stage.py:156
|
||||
#: authentik/stages/user_write/stage.py:170
|
||||
msgid "Failed to update user. Please try again later."
|
||||
msgstr "更新用户失败。请稍后重试。"
|
||||
|
||||
#: authentik/tenants/models.py:23
|
||||
msgid ""
|
||||
|
298
poetry.lock
generated
298
poetry.lock
generated
@ -878,63 +878,72 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "7.2.5"
|
||||
version = "7.2.7"
|
||||
description = "Code coverage measurement for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "coverage-7.2.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:883123d0bbe1c136f76b56276074b0c79b5817dd4238097ffa64ac67257f4b6c"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d2fbc2a127e857d2f8898aaabcc34c37771bf78a4d5e17d3e1f5c30cd0cbc62a"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f3671662dc4b422b15776cdca89c041a6349b4864a43aa2350b6b0b03bbcc7f"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780551e47d62095e088f251f5db428473c26db7829884323e56d9c0c3118791a"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:066b44897c493e0dcbc9e6a6d9f8bbb6607ef82367cf6810d387c09f0cd4fe9a"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9a4ee55174b04f6af539218f9f8083140f61a46eabcaa4234f3c2a452c4ed11"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:706ec567267c96717ab9363904d846ec009a48d5f832140b6ad08aad3791b1f5"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ae453f655640157d76209f42c62c64c4d4f2c7f97256d3567e3b439bd5c9b06c"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-win32.whl", hash = "sha256:f81c9b4bd8aa747d417407a7f6f0b1469a43b36a85748145e144ac4e8d303cb5"},
|
||||
{file = "coverage-7.2.5-cp310-cp310-win_amd64.whl", hash = "sha256:dc945064a8783b86fcce9a0a705abd7db2117d95e340df8a4333f00be5efb64c"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:40cc0f91c6cde033da493227797be2826cbf8f388eaa36a0271a97a332bfd7ce"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a66e055254a26c82aead7ff420d9fa8dc2da10c82679ea850d8feebf11074d88"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c10fbc8a64aa0f3ed136b0b086b6b577bc64d67d5581acd7cc129af52654384e"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a22cbb5ede6fade0482111fa7f01115ff04039795d7092ed0db43522431b4f2"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:292300f76440651529b8ceec283a9370532f4ecba9ad67d120617021bb5ef139"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7ff8f3fb38233035028dbc93715551d81eadc110199e14bbbfa01c5c4a43f8d8"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a08c7401d0b24e8c2982f4e307124b671c6736d40d1c39e09d7a8687bddf83ed"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef9659d1cda9ce9ac9585c045aaa1e59223b143f2407db0eaee0b61a4f266fb6"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-win32.whl", hash = "sha256:30dcaf05adfa69c2a7b9f7dfd9f60bc8e36b282d7ed25c308ef9e114de7fc23b"},
|
||||
{file = "coverage-7.2.5-cp311-cp311-win_amd64.whl", hash = "sha256:97072cc90f1009386c8a5b7de9d4fc1a9f91ba5ef2146c55c1f005e7b5c5e068"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bebea5f5ed41f618797ce3ffb4606c64a5de92e9c3f26d26c2e0aae292f015c1"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828189fcdda99aae0d6bf718ea766b2e715eabc1868670a0a07bf8404bf58c33"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e8a95f243d01ba572341c52f89f3acb98a3b6d1d5d830efba86033dd3687ade"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8834e5f17d89e05697c3c043d3e58a8b19682bf365048837383abfe39adaed5"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d1f25ee9de21a39b3a8516f2c5feb8de248f17da7eead089c2e04aa097936b47"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1637253b11a18f453e34013c665d8bf15904c9e3c44fbda34c643fbdc9d452cd"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8e575a59315a91ccd00c7757127f6b2488c2f914096077c745c2f1ba5b8c0969"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-win32.whl", hash = "sha256:509ecd8334c380000d259dc66feb191dd0a93b21f2453faa75f7f9cdcefc0718"},
|
||||
{file = "coverage-7.2.5-cp37-cp37m-win_amd64.whl", hash = "sha256:12580845917b1e59f8a1c2ffa6af6d0908cb39220f3019e36c110c943dc875b0"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b5016e331b75310610c2cf955d9f58a9749943ed5f7b8cfc0bb89c6134ab0a84"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:373ea34dca98f2fdb3e5cb33d83b6d801007a8074f992b80311fc589d3e6b790"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a063aad9f7b4c9f9da7b2550eae0a582ffc7623dca1c925e50c3fbde7a579771"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38c0a497a000d50491055805313ed83ddba069353d102ece8aef5d11b5faf045"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b3b05e22a77bb0ae1a3125126a4e08535961c946b62f30985535ed40e26614"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0342a28617e63ad15d96dca0f7ae9479a37b7d8a295f749c14f3436ea59fdcb3"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf97ed82ca986e5c637ea286ba2793c85325b30f869bf64d3009ccc1a31ae3fd"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c2c41c1b1866b670573657d584de413df701f482574bad7e28214a2362cb1fd1"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-win32.whl", hash = "sha256:10b15394c13544fce02382360cab54e51a9e0fd1bd61ae9ce012c0d1e103c813"},
|
||||
{file = "coverage-7.2.5-cp38-cp38-win_amd64.whl", hash = "sha256:a0b273fe6dc655b110e8dc89b8ec7f1a778d78c9fd9b4bda7c384c8906072212"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c587f52c81211d4530fa6857884d37f514bcf9453bdeee0ff93eaaf906a5c1b"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4436cc9ba5414c2c998eaedee5343f49c02ca93b21769c5fdfa4f9d799e84200"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6599bf92f33ab041e36e06d25890afbdf12078aacfe1f1d08c713906e49a3fe5"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:857abe2fa6a4973f8663e039ead8d22215d31db613ace76e4a98f52ec919068e"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f5cab2d7f0c12f8187a376cc6582c477d2df91d63f75341307fcdcb5d60303"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aa387bd7489f3e1787ff82068b295bcaafbf6f79c3dad3cbc82ef88ce3f48ad3"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:156192e5fd3dbbcb11cd777cc469cf010a294f4c736a2b2c891c77618cb1379a"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bd3b4b8175c1db502adf209d06136c000df4d245105c8839e9d0be71c94aefe1"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-win32.whl", hash = "sha256:ddc5a54edb653e9e215f75de377354e2455376f416c4378e1d43b08ec50acc31"},
|
||||
{file = "coverage-7.2.5-cp39-cp39-win_amd64.whl", hash = "sha256:338aa9d9883aaaad53695cb14ccdeb36d4060485bb9388446330bef9c361c252"},
|
||||
{file = "coverage-7.2.5-pp37.pp38.pp39-none-any.whl", hash = "sha256:8877d9b437b35a85c18e3c6499b23674684bf690f5d96c1006a1ef61f9fdf0f3"},
|
||||
{file = "coverage-7.2.5.tar.gz", hash = "sha256:f99ef080288f09ffc687423b8d60978cf3a465d3f404a18d1a05474bd8575a47"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"},
|
||||
{file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"},
|
||||
{file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"},
|
||||
{file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"},
|
||||
{file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"},
|
||||
{file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"},
|
||||
{file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"},
|
||||
{file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"},
|
||||
{file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@ -988,14 +997,13 @@ tox = ["tox"]
|
||||
|
||||
[[package]]
|
||||
name = "dacite"
|
||||
version = "1.8.0"
|
||||
version = "1.8.1"
|
||||
description = "Simple creation of data classes from dictionaries."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "dacite-1.8.0-py3-none-any.whl", hash = "sha256:f7b1205cc5d9b62835aac8cbc1e6e37c1da862359a401f1edbe2ae08fbdc6193"},
|
||||
{file = "dacite-1.8.0.tar.gz", hash = "sha256:6257a5e505b61a8cafee7ef3ad08cf32ee9b885718f42395d017e0a9b4c6af65"},
|
||||
{file = "dacite-1.8.1-py3-none-any.whl", hash = "sha256:cc31ad6fdea1f49962ea42db9421772afe01ac5442380d9a99fcf3d188c61afe"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@ -1128,14 +1136,14 @@ Django = ">=3.2"
|
||||
|
||||
[[package]]
|
||||
name = "django-otp"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
description = "A pluggable framework for adding two-factor authentication to Django using one-time passwords."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "django_otp-1.2.0-py3-none-any.whl", hash = "sha256:aa14ace751bede7c6c385f2ea3589f6aa3565a31e455fa0ee69801b79761e3b0"},
|
||||
{file = "django_otp-1.2.0.tar.gz", hash = "sha256:2baa30237f46549446d8d17a790b962f9065168bad38968dd208cdeb85901ede"},
|
||||
{file = "django_otp-1.2.1-py3-none-any.whl", hash = "sha256:1758aabfc17c30ba00142e823c961e20d2a0353040a9e4e4be2688cf71085446"},
|
||||
{file = "django_otp-1.2.1.tar.gz", hash = "sha256:d4785291fc97eb61c02574660f7ae82baab04da187fa5d0fb649d57deea2c62e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -1252,14 +1260,14 @@ wmi = ["wmi (>=1.5.1,<2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "docker"
|
||||
version = "6.1.1"
|
||||
version = "6.1.2"
|
||||
description = "A Python library for the Docker Engine API."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "docker-6.1.1-py3-none-any.whl", hash = "sha256:8308b23d3d0982c74f7aa0a3abd774898c0c4fba006e9c3bde4f68354e470fe2"},
|
||||
{file = "docker-6.1.1.tar.gz", hash = "sha256:5ec18b9c49d48ee145a5b5824bb126dc32fc77931e18444783fc07a7724badc0"},
|
||||
{file = "docker-6.1.2-py3-none-any.whl", hash = "sha256:134cd828f84543cbf8e594ff81ca90c38288df3c0a559794c12f2e4b634ea19e"},
|
||||
{file = "docker-6.1.2.tar.gz", hash = "sha256:dcc088adc2ec4e7cfc594e275d8bd2c9738c56c808de97476939ef67db5af8c2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -2263,14 +2271,14 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "paramiko"
|
||||
version = "3.1.0"
|
||||
version = "3.2.0"
|
||||
description = "SSH2 protocol library"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "paramiko-3.1.0-py3-none-any.whl", hash = "sha256:f0caa660e797d9cd10db6fc6ae81e2c9b2767af75c3180fcd0e46158cd368d7f"},
|
||||
{file = "paramiko-3.1.0.tar.gz", hash = "sha256:6950faca6819acd3219d4ae694a23c7a87ee38d084f70c1724b0c0dbb8b75769"},
|
||||
{file = "paramiko-3.2.0-py3-none-any.whl", hash = "sha256:df0f9dd8903bc50f2e10580af687f3015bf592a377cd438d2ec9546467a14eb8"},
|
||||
{file = "paramiko-3.2.0.tar.gz", hash = "sha256:93cdce625a8a1dc12204439d45033f3261bdb2c201648cfcdc06f9fd0f94ec29"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -2494,45 +2502,44 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pycryptodome"
|
||||
version = "3.17"
|
||||
version = "3.18.0"
|
||||
description = "Cryptographic library for Python"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
files = [
|
||||
{file = "pycryptodome-3.17-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:2c5631204ebcc7ae33d11c43037b2dafe25e2ab9c1de6448eb6502ac69c19a56"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:04779cc588ad8f13c80a060b0b1c9d1c203d051d8a43879117fe6b8aaf1cd3fa"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f812d58c5af06d939b2baccdda614a3ffd80531a26e5faca2c9f8b1770b2b7af"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:9453b4e21e752df8737fdffac619e93c9f0ec55ead9a45df782055eb95ef37d9"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:121d61663267f73692e8bde5ec0d23c9146465a0d75cad75c34f75c752527b01"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27m-win32.whl", hash = "sha256:ba2d4fcb844c6ba5df4bbfee9352ad5352c5ae939ac450e06cdceff653280450"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27m-win_amd64.whl", hash = "sha256:87e2ca3aa557781447428c4b6c8c937f10ff215202ab40ece5c13a82555c10d6"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f44c0d28716d950135ff21505f2c764498eda9d8806b7c78764165848aa419bc"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5a790bc045003d89d42e3b9cb3cc938c8561a57a88aaa5691512e8540d1ae79c"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:d086d46774e27b280e4cece8ab3d87299cf0d39063f00f1e9290d096adc5662a"},
|
||||
{file = "pycryptodome-3.17-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:5587803d5b66dfd99e7caa31ed91fba0fdee3661c5d93684028ad6653fce725f"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:e7debd9c439e7b84f53be3cf4ba8b75b3d0b6e6015212355d6daf44ac672e210"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ca1ceb6303be1282148f04ac21cebeebdb4152590842159877778f9cf1634f09"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:dc22cc00f804485a3c2a7e2010d9f14a705555f67020eb083e833cabd5bd82e4"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80ea8333b6a5f2d9e856ff2293dba2e3e661197f90bf0f4d5a82a0a6bc83a626"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c133f6721fba313722a018392a91e3c69d3706ae723484841752559e71d69dc6"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:333306eaea01fde50a73c4619e25631e56c4c61bd0fb0a2346479e67e3d3a820"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:1a30f51b990994491cec2d7d237924e5b6bd0d445da9337d77de384ad7f254f9"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:909e36a43fe4a8a3163e9c7fc103867825d14a2ecb852a63d3905250b308a4e5"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-win32.whl", hash = "sha256:a3228728a3808bc9f18c1797ec1179a0efb5068c817b2ffcf6bcd012494dffb2"},
|
||||
{file = "pycryptodome-3.17-cp35-abi3-win_amd64.whl", hash = "sha256:9ec565e89a6b400eca814f28d78a9ef3f15aea1df74d95b28b7720739b28f37f"},
|
||||
{file = "pycryptodome-3.17-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:e1819b67bcf6ca48341e9b03c2e45b1c891fa8eb1a8458482d14c2805c9616f2"},
|
||||
{file = "pycryptodome-3.17-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:f8e550caf52472ae9126953415e4fc554ab53049a5691c45b8816895c632e4d7"},
|
||||
{file = "pycryptodome-3.17-pp27-pypy_73-win32.whl", hash = "sha256:afbcdb0eda20a0e1d44e3a1ad6d4ec3c959210f4b48cabc0e387a282f4c7deb8"},
|
||||
{file = "pycryptodome-3.17-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a74f45aee8c5cc4d533e585e0e596e9f78521e1543a302870a27b0ae2106381e"},
|
||||
{file = "pycryptodome-3.17-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38bbd6717eac084408b4094174c0805bdbaba1f57fc250fd0309ae5ec9ed7e09"},
|
||||
{file = "pycryptodome-3.17-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f68d6c8ea2974a571cacb7014dbaada21063a0375318d88ac1f9300bc81e93c3"},
|
||||
{file = "pycryptodome-3.17-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:8198f2b04c39d817b206ebe0db25a6653bb5f463c2319d6f6d9a80d012ac1e37"},
|
||||
{file = "pycryptodome-3.17-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a232474cd89d3f51e4295abe248a8b95d0332d153bf46444e415409070aae1e"},
|
||||
{file = "pycryptodome-3.17-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4992ec965606054e8326e83db1c8654f0549cdb26fce1898dc1a20bc7684ec1c"},
|
||||
{file = "pycryptodome-3.17-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53068e33c74f3b93a8158dacaa5d0f82d254a81b1002e0cd342be89fcb3433eb"},
|
||||
{file = "pycryptodome-3.17-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:74794a2e2896cd0cf56fdc9db61ef755fa812b4a4900fa46c49045663a92b8d0"},
|
||||
{file = "pycryptodome-3.17.tar.gz", hash = "sha256:bce2e2d8e82fcf972005652371a3e8731956a0c1fbb719cc897943b3695ad91b"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:d1497a8cd4728db0e0da3c304856cb37c0c4e3d0b36fcbabcc1600f18504fc54"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:928078c530da78ff08e10eb6cada6e0dff386bf3d9fa9871b4bbc9fbc1efe024"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:157c9b5ba5e21b375f052ca78152dd309a09ed04703fd3721dce3ff8ecced148"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:d20082bdac9218649f6abe0b885927be25a917e29ae0502eaf2b53f1233ce0c2"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:e8ad74044e5f5d2456c11ed4cfd3e34b8d4898c0cb201c4038fe41458a82ea27"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27m-win32.whl", hash = "sha256:62a1e8847fabb5213ccde38915563140a5b338f0d0a0d363f996b51e4a6165cf"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27m-win_amd64.whl", hash = "sha256:16bfd98dbe472c263ed2821284118d899c76968db1a6665ade0c46805e6b29a4"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:7a3d22c8ee63de22336679e021c7f2386f7fc465477d59675caa0e5706387944"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:78d863476e6bad2a592645072cc489bb90320972115d8995bcfbee2f8b209918"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:b6a610f8bfe67eab980d6236fdc73bfcdae23c9ed5548192bb2d530e8a92780e"},
|
||||
{file = "pycryptodome-3.18.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:422c89fd8df8a3bee09fb8d52aaa1e996120eafa565437392b781abec2a56e14"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:9ad6f09f670c466aac94a40798e0e8d1ef2aa04589c29faa5b9b97566611d1d1"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:53aee6be8b9b6da25ccd9028caf17dcdce3604f2c7862f5167777b707fbfb6cb"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:10da29526a2a927c7d64b8f34592f461d92ae55fc97981aab5bbcde8cb465bb6"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f21efb8438971aa16924790e1c3dba3a33164eb4000106a55baaed522c261acf"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4944defabe2ace4803f99543445c27dd1edbe86d7d4edb87b256476a91e9ffa4"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:51eae079ddb9c5f10376b4131be9589a6554f6fd84f7f655180937f611cd99a2"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:83c75952dcf4a4cebaa850fa257d7a860644c70a7cd54262c237c9f2be26f76e"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:957b221d062d5752716923d14e0926f47670e95fead9d240fa4d4862214b9b2f"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-win32.whl", hash = "sha256:795bd1e4258a2c689c0b1f13ce9684fa0dd4c0e08680dcf597cf9516ed6bc0f3"},
|
||||
{file = "pycryptodome-3.18.0-cp35-abi3-win_amd64.whl", hash = "sha256:b1d9701d10303eec8d0bd33fa54d44e67b8be74ab449052a8372f12a66f93fb9"},
|
||||
{file = "pycryptodome-3.18.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:cb1be4d5af7f355e7d41d36d8eec156ef1382a88638e8032215c215b82a4b8ec"},
|
||||
{file = "pycryptodome-3.18.0-pp27-pypy_73-win32.whl", hash = "sha256:fc0a73f4db1e31d4a6d71b672a48f3af458f548059aa05e83022d5f61aac9c08"},
|
||||
{file = "pycryptodome-3.18.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f022a4fd2a5263a5c483a2bb165f9cb27f2be06f2f477113783efe3fe2ad887b"},
|
||||
{file = "pycryptodome-3.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:363dd6f21f848301c2dcdeb3c8ae5f0dee2286a5e952a0f04954b82076f23825"},
|
||||
{file = "pycryptodome-3.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12600268763e6fec3cefe4c2dcdf79bde08d0b6dc1813887e789e495cb9f3403"},
|
||||
{file = "pycryptodome-3.18.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4604816adebd4faf8810782f137f8426bf45fee97d8427fa8e1e49ea78a52e2c"},
|
||||
{file = "pycryptodome-3.18.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:01489bbdf709d993f3058e2996f8f40fee3f0ea4d995002e5968965fa2fe89fb"},
|
||||
{file = "pycryptodome-3.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3811e31e1ac3069988f7a1c9ee7331b942e605dfc0f27330a9ea5997e965efb2"},
|
||||
{file = "pycryptodome-3.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f4b967bb11baea9128ec88c3d02f55a3e338361f5e4934f5240afcb667fdaec"},
|
||||
{file = "pycryptodome-3.18.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:9c8eda4f260072f7dbe42f473906c659dcbadd5ae6159dfb49af4da1293ae380"},
|
||||
{file = "pycryptodome-3.18.0.tar.gz", hash = "sha256:c9adee653fc882d98956e33ca2c1fb582e23a8af7ac82fee75bd6113c55a0413"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3014,21 +3021,21 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.28.1"
|
||||
version = "2.31.0"
|
||||
description = "Python HTTP for Humans."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7, <4"
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
|
||||
{file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
|
||||
{file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
|
||||
{file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
charset-normalizer = ">=2,<3"
|
||||
charset-normalizer = ">=2,<4"
|
||||
idna = ">=2.5,<4"
|
||||
urllib3 = ">=1.21.1,<1.27"
|
||||
urllib3 = ">=1.21.1,<3"
|
||||
|
||||
[package.extras]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||
@ -3109,29 +3116,29 @@ pyasn1 = ">=0.1.3"
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.265"
|
||||
version = "0.0.270"
|
||||
description = "An extremely fast Python linter, written in Rust."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.0.265-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:30ddfe22de6ce4eb1260408f4480bbbce998f954dbf470228a21a9b2c45955e4"},
|
||||
{file = "ruff-0.0.265-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:a11bd0889e88d3342e7bc514554bb4461bf6cc30ec115821c2425cfaac0b1b6a"},
|
||||
{file = "ruff-0.0.265-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a9b38bdb40a998cbc677db55b6225a6c4fadcf8819eb30695e1b8470942426b"},
|
||||
{file = "ruff-0.0.265-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8b44a245b60512403a6a03a5b5212da274d33862225c5eed3bcf12037eb19bb"},
|
||||
{file = "ruff-0.0.265-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b279fa55ea175ef953208a6d8bfbcdcffac1c39b38cdb8c2bfafe9222add70bb"},
|
||||
{file = "ruff-0.0.265-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5028950f7af9b119d43d91b215d5044976e43b96a0d1458d193ef0dd3c587bf8"},
|
||||
{file = "ruff-0.0.265-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4057eb539a1d88eb84e9f6a36e0a999e0f261ed850ae5d5817e68968e7b89ed9"},
|
||||
{file = "ruff-0.0.265-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d586e69ab5cbf521a1910b733412a5735936f6a610d805b89d35b6647e2a66aa"},
|
||||
{file = "ruff-0.0.265-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa17b13cd3f29fc57d06bf34c31f21d043735cc9a681203d634549b0e41047d1"},
|
||||
{file = "ruff-0.0.265-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9ac13b11d9ad3001de9d637974ec5402a67cefdf9fffc3929ab44c2fcbb850a1"},
|
||||
{file = "ruff-0.0.265-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:62a9578b48cfd292c64ea3d28681dc16b1aa7445b7a7709a2884510fc0822118"},
|
||||
{file = "ruff-0.0.265-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d0f9967f84da42d28e3d9d9354cc1575f96ed69e6e40a7d4b780a7a0418d9409"},
|
||||
{file = "ruff-0.0.265-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1d5a8de2fbaf91ea5699451a06f4074e7a312accfa774ad9327cde3e4fda2081"},
|
||||
{file = "ruff-0.0.265-py3-none-win32.whl", hash = "sha256:9e9db5ccb810742d621f93272e3cc23b5f277d8d00c4a79668835d26ccbe48dd"},
|
||||
{file = "ruff-0.0.265-py3-none-win_amd64.whl", hash = "sha256:f54facf286103006171a00ce20388d88ed1d6732db3b49c11feb9bf3d46f90e9"},
|
||||
{file = "ruff-0.0.265-py3-none-win_arm64.whl", hash = "sha256:c78470656e33d32ddc54e8482b1b0fc6de58f1195586731e5ff1405d74421499"},
|
||||
{file = "ruff-0.0.265.tar.gz", hash = "sha256:53c17f0dab19ddc22b254b087d1381b601b155acfa8feed514f0d6a413d0ab3a"},
|
||||
{file = "ruff-0.0.270-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:f74c4d550f7b8e808455ac77bbce38daafc458434815ba0bc21ae4bdb276509b"},
|
||||
{file = "ruff-0.0.270-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:643de865fd35cb76c4f0739aea5afe7b8e4d40d623df7e9e6ea99054e5cead0a"},
|
||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eca02e709b3308eb7255b5f74e779be23b5980fca3862eae28bb23069cd61ae4"},
|
||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3ed3b198768d2b3a2300fb18f730cd39948a5cc36ba29ae9d4639a11040880be"},
|
||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:739495d2dbde87cf4e3110c8d27bc20febf93112539a968a4e02c26f0deccd1d"},
|
||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:08188f8351f4c0b6216e8463df0a76eb57894ca59a3da65e4ed205db980fd3ae"},
|
||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0827b074635d37984fc98d99316bfab5c8b1231bb83e60dacc83bd92883eedb4"},
|
||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d61ae4841313f6eeb8292dc349bef27b4ce426e62c36e80ceedc3824e408734"},
|
||||
{file = "ruff-0.0.270-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0eb412f20e77529a01fb94d578b19dcb8331b56f93632aa0cce4a2ea27b7aeba"},
|
||||
{file = "ruff-0.0.270-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b775e2c5fc869359daf8c8b8aa0fd67240201ab2e8d536d14a0edf279af18786"},
|
||||
{file = "ruff-0.0.270-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:21f00e47ab2308617c44435c8dfd9e2e03897461c9e647ec942deb2a235b4cfd"},
|
||||
{file = "ruff-0.0.270-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0bbfbf6fd2436165566ca85f6e57be03ed2f0a994faf40180cfbb3604c9232ef"},
|
||||
{file = "ruff-0.0.270-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8af391ef81f7be960be10886a3c1aac0b298bde7cb9a86ec2b05faeb2081ce6b"},
|
||||
{file = "ruff-0.0.270-py3-none-win32.whl", hash = "sha256:b4c037fe2f75bcd9aed0c89c7c507cb7fa59abae2bd4c8b6fc331a28178655a4"},
|
||||
{file = "ruff-0.0.270-py3-none-win_amd64.whl", hash = "sha256:0012f9b7dc137ab7f1f0355e3c4ca49b562baf6c9fa1180948deeb6648c52957"},
|
||||
{file = "ruff-0.0.270-py3-none-win_arm64.whl", hash = "sha256:9613456b0b375766244c25045e353bc8890c856431cd97893c97b10cc93bd28d"},
|
||||
{file = "ruff-0.0.270.tar.gz", hash = "sha256:95db07b7850b30ebf32b27fe98bc39e0ab99db3985edbbf0754d399eb2f0e690"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3154,14 +3161,14 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
|
||||
|
||||
[[package]]
|
||||
name = "sentry-sdk"
|
||||
version = "1.22.2"
|
||||
version = "1.24.0"
|
||||
description = "Python client for Sentry (https://sentry.io)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "sentry-sdk-1.22.2.tar.gz", hash = "sha256:5932c092c6e6035584eb74d77064e4bce3b7935dfc4a331349719a40db265840"},
|
||||
{file = "sentry_sdk-1.22.2-py2.py3-none-any.whl", hash = "sha256:cf89a5063ef84278d186aceaed6fb595bfe67d099298e537634a323664265669"},
|
||||
{file = "sentry-sdk-1.24.0.tar.gz", hash = "sha256:0bbcecda9f51936904c1030e7fef0fe693e633888f02a14d1cb68646a50e83b3"},
|
||||
{file = "sentry_sdk-1.24.0-py2.py3-none-any.whl", hash = "sha256:56d6d9d194c898d853a7c1dd99bed92ce82334ee1282292c15bcc967ff1a49b5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -3178,10 +3185,11 @@ chalice = ["chalice (>=1.16.0)"]
|
||||
django = ["django (>=1.8)"]
|
||||
falcon = ["falcon (>=1.4)"]
|
||||
fastapi = ["fastapi (>=0.79.0)"]
|
||||
flask = ["blinker (>=1.1)", "flask (>=0.11)"]
|
||||
flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"]
|
||||
grpcio = ["grpcio (>=1.21.1)"]
|
||||
httpx = ["httpx (>=0.16.0)"]
|
||||
huey = ["huey (>=2)"]
|
||||
loguru = ["loguru (>=0.5)"]
|
||||
opentelemetry = ["opentelemetry-distro (>=0.35b0)"]
|
||||
pure-eval = ["asttokens", "executing", "pure-eval"]
|
||||
pymongo = ["pymongo (>=3.1)"]
|
||||
@ -3377,23 +3385,23 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "tornado"
|
||||
version = "6.2"
|
||||
version = "6.3.2"
|
||||
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">= 3.7"
|
||||
python-versions = ">= 3.8"
|
||||
files = [
|
||||
{file = "tornado-6.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72"},
|
||||
{file = "tornado-6.2-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9"},
|
||||
{file = "tornado-6.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba09ef14ca9893954244fd872798b4ccb2367c165946ce2dd7376aebdde8e3ac"},
|
||||
{file = "tornado-6.2-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8150f721c101abdef99073bf66d3903e292d851bee51910839831caba341a75"},
|
||||
{file = "tornado-6.2-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3a2f5999215a3a06a4fc218026cd84c61b8b2b40ac5296a6db1f1451ef04c1e"},
|
||||
{file = "tornado-6.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5f8c52d219d4995388119af7ccaa0bcec289535747620116a58d830e7c25d8a8"},
|
||||
{file = "tornado-6.2-cp37-abi3-musllinux_1_1_i686.whl", hash = "sha256:6fdfabffd8dfcb6cf887428849d30cf19a3ea34c2c248461e1f7d718ad30b66b"},
|
||||
{file = "tornado-6.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:1d54d13ab8414ed44de07efecb97d4ef7c39f7438cf5e976ccd356bebb1b5fca"},
|
||||
{file = "tornado-6.2-cp37-abi3-win32.whl", hash = "sha256:5c87076709343557ef8032934ce5f637dbb552efa7b21d08e89ae7619ed0eb23"},
|
||||
{file = "tornado-6.2-cp37-abi3-win_amd64.whl", hash = "sha256:e5f923aa6a47e133d1cf87d60700889d7eae68988704e20c75fb2d65677a8e4b"},
|
||||
{file = "tornado-6.2.tar.gz", hash = "sha256:9b630419bde84ec666bfd7ea0a4cb2a8a651c2d5cccdbdd1972a0c859dfc3c13"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c367ab6c0393d71171123ca5515c61ff62fe09024fa6bf299cd1339dc9456829"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b46a6ab20f5c7c1cb949c72c1994a4585d2eaa0be4853f50a03b5031e964fc7c"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2de14066c4a38b4ecbbcd55c5cc4b5340eb04f1c5e81da7451ef555859c833f"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05615096845cf50a895026f749195bf0b10b8909f9be672f50b0fe69cba368e4"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b17b1cf5f8354efa3d37c6e28fdfd9c1c1e5122f2cb56dac121ac61baa47cbe"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:29e71c847a35f6e10ca3b5c2990a52ce38b233019d8e858b755ea6ce4dcdd19d"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:834ae7540ad3a83199a8da8f9f2d383e3c3d5130a328889e4cc991acc81e87a0"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6a0848f1aea0d196a7c4f6772197cbe2abc4266f836b0aac76947872cd29b411"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-win32.whl", hash = "sha256:7efcbcc30b7c654eb6a8c9c9da787a851c18f8ccd4a5a3a95b05c7accfa068d2"},
|
||||
{file = "tornado-6.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:0c325e66c8123c606eea33084976c832aa4e766b7dff8aedd7587ea44a604cdf"},
|
||||
{file = "tornado-6.3.2.tar.gz", hash = "sha256:4b927c4f19b71e627b13f3db2324e4ae660527143f9e1f2e2fb404f3a187e2ba"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3436,14 +3444,14 @@ wsproto = ">=0.14"
|
||||
|
||||
[[package]]
|
||||
name = "twilio"
|
||||
version = "8.2.0"
|
||||
version = "8.2.1"
|
||||
description = "Twilio API client and TwiML generator"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "twilio-8.2.0-py2.py3-none-any.whl", hash = "sha256:23eceaec183995fc827e3bfad229cca6e1944bfd9604e57e2712e625b6e01223"},
|
||||
{file = "twilio-8.2.0.tar.gz", hash = "sha256:0c19eb6a5b84dbcd15658e23a142df026297236e4d72ad9304fd95e7dbff2662"},
|
||||
{file = "twilio-8.2.1-py2.py3-none-any.whl", hash = "sha256:9c6bbfda1f3196c64258b6661e372c23e2e6a9630c9986f725d16bb4bfe3275f"},
|
||||
{file = "twilio-8.2.1.tar.gz", hash = "sha256:66fe6a18199955b8abce2699e533b56f605a22d585c3f0b1820113ec068a0b51"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -3584,14 +3592,14 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "1.26.15"
|
||||
version = "1.26.16"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
||||
files = [
|
||||
{file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"},
|
||||
{file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"},
|
||||
{file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"},
|
||||
{file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -4,7 +4,8 @@ FROM --platform=${BUILDPLATFORM} docker.io/node:20 as web-builder
|
||||
COPY ./web /static/
|
||||
|
||||
ENV NODE_ENV=production
|
||||
RUN cd /static && npm ci && npm run build-proxy
|
||||
WORKDIR /static
|
||||
RUN npm ci --include=dev && npm run build-proxy
|
||||
|
||||
# Stage 2: Build
|
||||
FROM docker.io/golang:1.20.4-bullseye AS builder
|
||||
|
@ -113,7 +113,7 @@ filterwarnings = [
|
||||
|
||||
[tool.poetry]
|
||||
name = "authentik"
|
||||
version = "2023.4.1"
|
||||
version = "2023.5.2"
|
||||
description = ""
|
||||
authors = ["authentik Team <hello@goauthentik.io>"]
|
||||
|
||||
|
56
schema.yml
56
schema.yml
@ -1,7 +1,7 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: authentik
|
||||
version: 2023.4.1
|
||||
version: 2023.5.2
|
||||
description: Making authentication simple.
|
||||
contact:
|
||||
email: hello@goauthentik.io
|
||||
@ -18450,6 +18450,11 @@ paths:
|
||||
* `email_deny` - Use the user's email address, but deny enrollment when the email address already exists.
|
||||
* `username_link` - Link to a user with identical username. Can have security implications when a username is used with another source.
|
||||
* `username_deny` - Use the user's username, but deny enrollment when the username already exists.
|
||||
- in: query
|
||||
name: verification_kp
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
tags:
|
||||
- sources
|
||||
security:
|
||||
@ -37280,13 +37285,20 @@ components:
|
||||
* `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` - Transient
|
||||
binding_type:
|
||||
$ref: '#/components/schemas/BindingTypeEnum'
|
||||
verification_kp:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
title: Verification Certificate
|
||||
description: When selected, incoming assertion's Signatures will be validated
|
||||
against this certificate. To allow unsigned Requests, leave on default.
|
||||
signing_kp:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
title: Signing Keypair
|
||||
description: Keypair which is used to sign outgoing requests. Leave empty
|
||||
to disable signing.
|
||||
description: Keypair used to sign outgoing Responses going to the Identity
|
||||
Provider.
|
||||
digest_algorithm:
|
||||
$ref: '#/components/schemas/DigestAlgorithmEnum'
|
||||
signature_algorithm:
|
||||
@ -38956,6 +38968,11 @@ components:
|
||||
shared_secret:
|
||||
type: string
|
||||
description: Shared secret between clients and server to hash packets.
|
||||
outpost_set:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
readOnly: true
|
||||
required:
|
||||
- assigned_application_name
|
||||
- assigned_application_slug
|
||||
@ -38965,6 +38982,7 @@ components:
|
||||
- component
|
||||
- meta_model_name
|
||||
- name
|
||||
- outpost_set
|
||||
- pk
|
||||
- verbose_name
|
||||
- verbose_name_plural
|
||||
@ -39602,13 +39620,20 @@ components:
|
||||
* `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` - Transient
|
||||
binding_type:
|
||||
$ref: '#/components/schemas/BindingTypeEnum'
|
||||
verification_kp:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
title: Verification Certificate
|
||||
description: When selected, incoming assertion's Signatures will be validated
|
||||
against this certificate. To allow unsigned Requests, leave on default.
|
||||
signing_kp:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
title: Signing Keypair
|
||||
description: Keypair which is used to sign outgoing requests. Leave empty
|
||||
to disable signing.
|
||||
description: Keypair used to sign outgoing Responses going to the Identity
|
||||
Provider.
|
||||
digest_algorithm:
|
||||
$ref: '#/components/schemas/DigestAlgorithmEnum'
|
||||
signature_algorithm:
|
||||
@ -39709,13 +39734,20 @@ components:
|
||||
* `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` - Transient
|
||||
binding_type:
|
||||
$ref: '#/components/schemas/BindingTypeEnum'
|
||||
verification_kp:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
title: Verification Certificate
|
||||
description: When selected, incoming assertion's Signatures will be validated
|
||||
against this certificate. To allow unsigned Requests, leave on default.
|
||||
signing_kp:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
title: Signing Keypair
|
||||
description: Keypair which is used to sign outgoing requests. Leave empty
|
||||
to disable signing.
|
||||
description: Keypair used to sign outgoing Responses going to the Identity
|
||||
Provider.
|
||||
digest_algorithm:
|
||||
$ref: '#/components/schemas/DigestAlgorithmEnum'
|
||||
signature_algorithm:
|
||||
@ -39824,11 +39856,11 @@ components:
|
||||
type: string
|
||||
description: Get object component so that we know how to edit the object
|
||||
readOnly: true
|
||||
assigned_application_slug:
|
||||
assigned_backchannel_application_slug:
|
||||
type: string
|
||||
description: Internal application name, used in URLs.
|
||||
readOnly: true
|
||||
assigned_application_name:
|
||||
assigned_backchannel_application_name:
|
||||
type: string
|
||||
description: Application's display Name.
|
||||
readOnly: true
|
||||
@ -39857,8 +39889,8 @@ components:
|
||||
format: uuid
|
||||
nullable: true
|
||||
required:
|
||||
- assigned_application_name
|
||||
- assigned_application_slug
|
||||
- assigned_backchannel_application_name
|
||||
- assigned_backchannel_application_slug
|
||||
- component
|
||||
- meta_model_name
|
||||
- name
|
||||
@ -40971,7 +41003,6 @@ components:
|
||||
type: string
|
||||
required:
|
||||
- avatar
|
||||
- groups
|
||||
- groups_obj
|
||||
- is_superuser
|
||||
- name
|
||||
@ -41429,7 +41460,6 @@ components:
|
||||
type: string
|
||||
minLength: 1
|
||||
required:
|
||||
- groups
|
||||
- name
|
||||
- username
|
||||
UserSAMLSourceConnection:
|
||||
|
@ -243,7 +243,7 @@ class TestSourceOAuth1(SeleniumTestCase):
|
||||
|
||||
def get_container_specs(self) -> Optional[dict[str, Any]]:
|
||||
return {
|
||||
"image": "ghcr.io/beryju/oauth1-test-server:latest",
|
||||
"image": "ghcr.io/beryju/oauth1-test-server:v1.1",
|
||||
"detach": True,
|
||||
"network_mode": "host",
|
||||
"auto_remove": True,
|
||||
|
2961
web/package-lock.json
generated
2961
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -16,45 +16,24 @@
|
||||
"background-image": "npx @squoosh/cli -d src/assets/images --resize '{\"enabled\":true,\"width\":2560,\"method\":\"lanczos3\",\"fitMethod\":\"contain\",\"premultiply\":true,\"linearRGB\":true}' --mozjpeg '{\"quality\":75,\"baseline\":false,\"arithmetic\":false,\"progressive\":true,\"optimize_coding\":true,\"smoothing\":0,\"color_space\":3,\"quant_table\":3,\"trellis_multipass\":false,\"trellis_opt_zero\":false,\"trellis_opt_table\":false,\"trellis_loops\":1,\"auto_subsample\":true,\"chroma_subsample\":2,\"separate_chroma_quality\":false,\"chroma_quality\":75}' src/assets/images/flow_background.jpg"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.21.8",
|
||||
"@babel/plugin-proposal-decorators": "^7.21.0",
|
||||
"@babel/plugin-transform-runtime": "^7.21.4",
|
||||
"@babel/preset-env": "^7.21.5",
|
||||
"@babel/preset-typescript": "^7.21.5",
|
||||
"@codemirror/lang-html": "^6.4.3",
|
||||
"@codemirror/lang-javascript": "^6.1.7",
|
||||
"@codemirror/lang-javascript": "^6.1.8",
|
||||
"@codemirror/lang-python": "^6.1.2",
|
||||
"@codemirror/lang-xml": "^6.0.2",
|
||||
"@codemirror/legacy-modes": "^6.3.2",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@formatjs/intl-listformat": "^7.2.2",
|
||||
"@fortawesome/fontawesome-free": "^6.4.0",
|
||||
"@goauthentik/api": "^2023.4.1-1683802980",
|
||||
"@hcaptcha/types": "^1.0.3",
|
||||
"@jackfranklin/rollup-plugin-markdown": "^0.4.0",
|
||||
"@lingui/cli": "^4.0.0",
|
||||
"@lingui/core": "^4.0.0",
|
||||
"@lingui/detect-locale": "^4.0.0",
|
||||
"@lingui/format-po-gettext": "^4.0.0",
|
||||
"@lingui/macro": "^4.0.0",
|
||||
"@goauthentik/api": "^2023.5.2-1685273038",
|
||||
"@lingui/cli": "^4.2.0",
|
||||
"@lingui/core": "^4.2.0",
|
||||
"@lingui/detect-locale": "^4.2.0",
|
||||
"@lingui/format-po-gettext": "^4.2.0",
|
||||
"@lingui/macro": "^4.2.0",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@rollup/plugin-babel": "^6.0.3",
|
||||
"@rollup/plugin-commonjs": "^24.1.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.2",
|
||||
"@rollup/plugin-replace": "^5.0.2",
|
||||
"@rollup/plugin-typescript": "^11.1.0",
|
||||
"@sentry/browser": "^7.51.2",
|
||||
"@sentry/tracing": "^7.51.2",
|
||||
"@squoosh/cli": "^0.7.3",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
|
||||
"@types/chart.js": "^2.9.37",
|
||||
"@types/codemirror": "5.60.7",
|
||||
"@types/grecaptcha": "^3.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.5",
|
||||
"@typescript-eslint/parser": "^5.59.5",
|
||||
"@sentry/browser": "^7.53.1",
|
||||
"@sentry/tracing": "^7.53.1",
|
||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"babel-plugin-tsconfig-paths": "^1.0.3",
|
||||
"base64-js": "^1.5.1",
|
||||
"chart.js": "^4.3.0",
|
||||
"chartjs-adapter-moment": "^1.0.1",
|
||||
@ -62,27 +41,51 @@
|
||||
"construct-style-sheets-polyfill": "^3.1.0",
|
||||
"core-js": "^3.30.2",
|
||||
"country-flag-icons": "^1.5.7",
|
||||
"eslint": "^8.40.0",
|
||||
"fuse.js": "^6.6.2",
|
||||
"lit": "^2.7.4",
|
||||
"mermaid": "^10.2.0",
|
||||
"rapidoc": "^9.3.4",
|
||||
"webcomponent-qr-code": "^1.1.1",
|
||||
"yaml": "^2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.1",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.22.3",
|
||||
"@babel/plugin-proposal-private-methods": "^7.18.6",
|
||||
"@babel/plugin-transform-runtime": "^7.22.4",
|
||||
"@babel/preset-env": "^7.22.4",
|
||||
"@babel/preset-typescript": "^7.21.5",
|
||||
"@hcaptcha/types": "^1.0.3",
|
||||
"@jackfranklin/rollup-plugin-markdown": "^0.4.0",
|
||||
"@rollup/plugin-babel": "^6.0.3",
|
||||
"@rollup/plugin-commonjs": "^25.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.2",
|
||||
"@rollup/plugin-replace": "^5.0.2",
|
||||
"@rollup/plugin-typescript": "^11.1.1",
|
||||
"@squoosh/cli": "^0.7.3",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
|
||||
"@types/chart.js": "^2.9.37",
|
||||
"@types/codemirror": "5.60.7",
|
||||
"@types/grecaptcha": "^3.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
||||
"@typescript-eslint/parser": "^5.59.8",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"babel-plugin-tsconfig-paths": "^1.0.3",
|
||||
"eslint": "^8.41.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.8",
|
||||
"eslint-plugin-lit": "^1.8.3",
|
||||
"fuse.js": "^6.6.2",
|
||||
"lit": "^2.7.4",
|
||||
"mermaid": "^10.1.0",
|
||||
"moment": "^2.29.4",
|
||||
"prettier": "^2.8.8",
|
||||
"pyright": "^1.1.307",
|
||||
"rapidoc": "^9.3.4",
|
||||
"pyright": "^1.1.310",
|
||||
"rollup": "^2.79.1",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-cssimport": "^1.0.3",
|
||||
"rollup-plugin-minify-html-literals": "^1.2.6",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"ts-lit-plugin": "^1.2.1",
|
||||
"tslib": "^2.5.0",
|
||||
"tslib": "^2.5.2",
|
||||
"turnstile-types": "^1.1.2",
|
||||
"typescript": "^5.0.4",
|
||||
"webcomponent-qr-code": "^1.1.1",
|
||||
"yaml": "^2.2.2"
|
||||
"typescript": "^5.0.4"
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,10 @@ export class ProviderViewPage extends AKElement {
|
||||
return html`<ak-provider-scim-view
|
||||
providerID=${ifDefined(this.provider.pk)}
|
||||
></ak-provider-scim-view>`;
|
||||
case "ak-provider-radius-form":
|
||||
return html`<ak-provider-radius-view
|
||||
providerID=${ifDefined(this.provider.pk)}
|
||||
></ak-provider-radius-view>`;
|
||||
default:
|
||||
return html`<p>Invalid provider type ${this.provider?.component}</p>`;
|
||||
}
|
||||
|
@ -79,6 +79,11 @@ export class RadiusProviderViewPage extends AKElement {
|
||||
data-tab-title="${t`Overview`}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
${this.provider?.outpostSet.length < 1
|
||||
? html`<div slot="header" class="pf-c-banner pf-m-warning">
|
||||
${t`Warning: Provider is not used by any Outpost.`}
|
||||
</div>`
|
||||
: html``}
|
||||
<div class="pf-u-display-flex pf-u-justify-content-center">
|
||||
<div class="pf-u-w-75">
|
||||
<div class="pf-c-card">
|
||||
@ -152,7 +157,7 @@ export class RadiusProviderViewPage extends AKElement {
|
||||
<ak-object-changelog
|
||||
targetModelPk=${this.provider.pk || ""}
|
||||
targetModelApp="authentik_providers_radius"
|
||||
targetModelName="RadiusProvider"
|
||||
targetModelName="radiusprovider"
|
||||
>
|
||||
</ak-object-changelog>
|
||||
</div>
|
||||
|
@ -121,9 +121,14 @@ export class SCIMProviderViewPage extends AKElement {
|
||||
if (!this.provider) {
|
||||
return html``;
|
||||
}
|
||||
return html` <div slot="header" class="pf-c-banner pf-m-info">
|
||||
return html`<div slot="header" class="pf-c-banner pf-m-info">
|
||||
${t`SCIM provider is in preview.`}
|
||||
</div>
|
||||
${!this.provider?.assignedBackchannelApplicationName
|
||||
? html`<div slot="header" class="pf-c-banner pf-m-warning">
|
||||
${t`Warning: Provider is not assigned to an application as backchannel provider.`}
|
||||
</div>`
|
||||
: html``}
|
||||
<div class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter">
|
||||
<div class="pf-l-grid__item pf-m-7-col pf-l-stack pf-m-gutter">
|
||||
<div class="pf-c-card pf-m-12-col pf-l-stack__item">
|
||||
|
@ -304,6 +304,42 @@ export class SAMLSourceForm extends ModelForm<SAMLSource, string> {
|
||||
${t`Keypair which is used to sign outgoing requests. Leave empty to disable signing.`}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Verification Certificate`}
|
||||
name="verificationKp"
|
||||
>
|
||||
<ak-search-select
|
||||
.fetchObjects=${async (
|
||||
query?: string,
|
||||
): Promise<CertificateKeyPair[]> => {
|
||||
const args: CryptoCertificatekeypairsListRequest = {
|
||||
ordering: "name",
|
||||
includeDetails: false,
|
||||
};
|
||||
if (query !== undefined) {
|
||||
args.search = query;
|
||||
}
|
||||
const certificates = await new CryptoApi(
|
||||
DEFAULT_CONFIG,
|
||||
).cryptoCertificatekeypairsList(args);
|
||||
return certificates.results;
|
||||
}}
|
||||
.renderElement=${(item: CertificateKeyPair): string => {
|
||||
return item.name;
|
||||
}}
|
||||
.value=${(item: CertificateKeyPair | undefined): string | undefined => {
|
||||
return item?.pk;
|
||||
}}
|
||||
.selected=${(item: CertificateKeyPair): boolean => {
|
||||
return item.pk === this.instance?.verificationKp;
|
||||
}}
|
||||
?blankable=${true}
|
||||
>
|
||||
</ak-search-select>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${t`When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.`}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</div>
|
||||
</ak-form-group>
|
||||
<ak-form-group>
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 551 KiB After Width: | Height: | Size: 399 KiB |
@ -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 = "2023.4.1";
|
||||
export const VERSION = "2023.5.2";
|
||||
export const TITLE_DEFAULT = "authentik";
|
||||
export const ROUTE_SEPARATOR = ";";
|
||||
|
||||
|
@ -142,6 +142,10 @@ export abstract class Form<T> extends AKElement {
|
||||
if (element.hidden || !inputElement) {
|
||||
return;
|
||||
}
|
||||
// Skip elements that are writeOnly where the user hasn't clicked on the value
|
||||
if (element.writeOnly && !element.writeOnlyActivated) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
inputElement.tagName.toLowerCase() === "select" &&
|
||||
"multiple" in inputElement.attributes
|
||||
|
@ -525,8 +525,7 @@ export class FlowExecutor extends Interface implements StageHost {
|
||||
${this.flowInfo?.background?.startsWith("/static")
|
||||
? html`
|
||||
<li>
|
||||
<a
|
||||
href="https://unsplash.com/@clarissemeyer"
|
||||
<a href="https://unsplash.com/@joshnh"
|
||||
>${t`Background image`}</a
|
||||
>
|
||||
</li>
|
||||
|
@ -39,10 +39,7 @@ export class RedirectStage extends BaseStage<RedirectChallenge, FlowChallengeRes
|
||||
}
|
||||
|
||||
getURL(): string {
|
||||
if (!this.challenge.to.includes("://")) {
|
||||
return window.location.origin + this.challenge.to;
|
||||
}
|
||||
return this.challenge.to;
|
||||
return new URL(this.challenge.to, document.baseURI).toString();
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
|
@ -53,9 +53,10 @@ export class AuthenticatorValidateStage
|
||||
_selectedDeviceChallenge?: DeviceChallenge;
|
||||
|
||||
set selectedDeviceChallenge(value: DeviceChallenge | undefined) {
|
||||
const previousChallenge = this._selectedDeviceChallenge;
|
||||
this._selectedDeviceChallenge = value;
|
||||
if (!value) return;
|
||||
if (value === this._selectedDeviceChallenge) return;
|
||||
if (value === previousChallenge) return;
|
||||
// We don't use this.submit here, as we don't want to advance the flow.
|
||||
// We just want to notify the backend which challenge has been selected.
|
||||
new FlowsApi(DEFAULT_CONFIG).flowsExecutorSolve({
|
||||
@ -134,7 +135,7 @@ export class AuthenticatorValidateStage
|
||||
<small>${t`In case you can't access any other method.`}</small>
|
||||
</div>`;
|
||||
case DeviceClassesEnum.Sms:
|
||||
return html`<i class="fas fa-mobile"></i>
|
||||
return html`<i class="fas fa-mobile-alt"></i>
|
||||
<div class="right">
|
||||
<p>${t`SMS`}</p>
|
||||
<small>${t`Tokens sent via SMS.`}</small>
|
||||
|
@ -7,7 +7,7 @@ import { PasswordManagerPrefill } from "@goauthentik/flow/stages/identification/
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
@ -37,7 +37,24 @@ export class AuthenticatorValidateStageWebCode extends BaseStage<
|
||||
showBackButton = false;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton];
|
||||
return [
|
||||
PFBase,
|
||||
PFLogin,
|
||||
PFForm,
|
||||
PFFormControl,
|
||||
PFTitle,
|
||||
PFButton,
|
||||
css`
|
||||
.icon-description {
|
||||
display: flex;
|
||||
}
|
||||
.icon-description i {
|
||||
font-size: 2em;
|
||||
padding: 0.25em;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
@ -62,13 +79,23 @@ export class AuthenticatorValidateStageWebCode extends BaseStage<
|
||||
>
|
||||
</div>
|
||||
</ak-form-static>
|
||||
${this.deviceChallenge?.deviceClass == DeviceClassesEnum.Sms
|
||||
? html`<p>${t`A code has been sent to you via SMS.`}</p>`
|
||||
: html``}
|
||||
<div class="icon-description">
|
||||
<i
|
||||
class="fa ${this.deviceChallenge?.deviceClass == DeviceClassesEnum.Sms
|
||||
? "fa-key"
|
||||
: "fa-mobile-alt"}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
${this.deviceChallenge?.deviceClass == DeviceClassesEnum.Sms
|
||||
? html`<p>${t`A code has been sent to you via SMS.`}</p>`
|
||||
: html`<p>
|
||||
${t`Open your two-factor authenticator app to view your authentication code.`}
|
||||
</p>`}
|
||||
</div>
|
||||
<ak-form-element
|
||||
label="${this.deviceChallenge?.deviceClass === DeviceClassesEnum.Static
|
||||
? t`Static token`
|
||||
: t`Code`}"
|
||||
: t`Authentication code`}"
|
||||
?required="${true}"
|
||||
class="pf-c-form__group"
|
||||
.errors=${(this.challenge?.responseErrors || {})["code"]}
|
||||
@ -85,7 +112,7 @@ export class AuthenticatorValidateStageWebCode extends BaseStage<
|
||||
DeviceClassesEnum.Static
|
||||
? "[0-9a-zA-Z]*"
|
||||
: "[0-9]*"}"
|
||||
placeholder="${t`Please enter your Code`}"
|
||||
placeholder="${t`Please enter your code`}"
|
||||
autofocus=""
|
||||
autocomplete="one-time-code"
|
||||
class="pf-c-form-control"
|
||||
|
@ -202,7 +202,7 @@ export class IdentificationStage extends BaseStage<
|
||||
}
|
||||
|
||||
renderInput(): TemplateResult {
|
||||
let type = "text";
|
||||
let type: "text" | "email" = "text";
|
||||
if (!this.challenge?.userFields || this.challenge.userFields.length === 0) {
|
||||
return html`<p>${t`Select one of the sources below to login.`}</p>`;
|
||||
}
|
||||
|
@ -64,32 +64,32 @@ export class PromptStage extends BaseStage<PromptChallenge, PromptChallengeRespo
|
||||
/>`;
|
||||
case PromptTypeEnum.TextArea:
|
||||
return html`<textarea
|
||||
type="text"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="off"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
></textarea>`;
|
||||
>
|
||||
${prompt.initialValue}</textarea
|
||||
>`;
|
||||
case PromptTypeEnum.TextReadOnly:
|
||||
return html`<input
|
||||
type="text"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
readonly
|
||||
?readonly=${true}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
case PromptTypeEnum.TextAreaReadOnly:
|
||||
return html`<textarea
|
||||
type="text"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
readonly
|
||||
value="${prompt.initialValue}"
|
||||
></textarea>`;
|
||||
>
|
||||
${prompt.initialValue}</textarea
|
||||
>`;
|
||||
case PromptTypeEnum.Username:
|
||||
return html`<input
|
||||
type="text"
|
||||
@ -186,8 +186,8 @@ export class PromptStage extends BaseStage<PromptChallenge, PromptChallengeRespo
|
||||
class="pf-c-check__input"
|
||||
name="${prompt.fieldKey}"
|
||||
id="${id}"
|
||||
checked="${prompt.initialValue === choice}"
|
||||
required="${prompt.required}"
|
||||
?checked="${prompt.initialValue === choice}"
|
||||
?required="${prompt.required}"
|
||||
value="${choice}"
|
||||
/>
|
||||
<label class="pf-c-check__label" for=${id}>${choice}</label>
|
||||
@ -195,7 +195,7 @@ export class PromptStage extends BaseStage<PromptChallenge, PromptChallengeRespo
|
||||
})}`;
|
||||
case PromptTypeEnum.AkLocale:
|
||||
return html`<select class="pf-c-form-control" name="${prompt.fieldKey}">
|
||||
<option value="" ${prompt.initialValue === "" ? "selected" : ""}>
|
||||
<option value="" ?selected=${prompt.initialValue === ""}>
|
||||
${t`Auto-detect (based on your browser)`}
|
||||
</option>
|
||||
${LOCALES.filter((locale) => {
|
||||
@ -209,7 +209,7 @@ export class PromptStage extends BaseStage<PromptChallenge, PromptChallengeRespo
|
||||
}).map((locale) => {
|
||||
return html`<option
|
||||
value=${locale.code}
|
||||
${prompt.initialValue === locale.code ? "selected" : ""}
|
||||
?selected=${prompt.initialValue === locale.code}
|
||||
>
|
||||
${locale.code.toUpperCase()} - ${locale.label}
|
||||
</option>`;
|
||||
|
@ -420,7 +420,7 @@ msgstr "Erweiterte Einstellungen"
|
||||
msgid "Affected model:"
|
||||
msgstr "Betroffenes Modell:"
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Alert"
|
||||
msgstr "Alarm"
|
||||
|
||||
@ -791,6 +791,10 @@ msgstr "Authentifizierung mit Plex..."
|
||||
msgid "Authentication"
|
||||
msgstr "Authentifizierung"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Authentication code"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderForm.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderForm.ts
|
||||
#: src/admin/providers/radius/RadiusProviderForm.ts
|
||||
@ -1423,7 +1427,6 @@ msgstr "Schließen"
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_sms/AuthenticatorSMSStage.ts
|
||||
#: src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Code"
|
||||
msgstr "Code"
|
||||
|
||||
@ -4382,7 +4385,7 @@ msgstr "Nicht Sie?"
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Notice"
|
||||
msgstr "Hinweis"
|
||||
|
||||
@ -4554,6 +4557,10 @@ msgstr ""
|
||||
msgid "Open settings"
|
||||
msgstr "Einstellungen öffnen"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Open your two-factor authenticator app to view your authentication code."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
msgid "OpenID Configuration Issuer"
|
||||
msgstr "OpenID-Konfigurations-Aussteller"
|
||||
@ -4827,8 +4834,11 @@ msgstr "History"
|
||||
msgid "Please enter the code you received via SMS"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Please enter your code"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
msgid "Please enter your Code"
|
||||
msgstr "Bitte geben Sie Ihren Code ein "
|
||||
|
||||
@ -7160,8 +7170,8 @@ msgstr ""
|
||||
msgid "Unknown proxy mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Unknown severity"
|
||||
msgstr ""
|
||||
|
||||
@ -7756,6 +7766,7 @@ msgid "Verification"
|
||||
msgstr "Überprüfung"
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "Verification Certificate"
|
||||
msgstr "Zertifikat zur Überprüfung"
|
||||
|
||||
@ -7814,7 +7825,7 @@ msgstr ""
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/blueprints/BlueprintListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/system-tasks/SystemTaskListPage.ts
|
||||
msgid "Warning"
|
||||
msgstr "Warnung"
|
||||
@ -7839,6 +7850,10 @@ msgstr "Warnung: Keine Einladungsphase ist an einen Ablauf gebunden. Einladungen
|
||||
msgid "Warning: Policy is not assigned."
|
||||
msgstr "Warnung: Keine Richtlinie zugewiesen"
|
||||
|
||||
#: src/admin/providers/scim/SCIMProviderViewPage.ts
|
||||
msgid "Warning: Provider is not assigned to an application as backchannel provider."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
@ -7847,6 +7862,7 @@ msgstr "Warnung: Der Anbieter wird nicht von einer Anwendung verwendet."
|
||||
|
||||
#: src/admin/providers/ldap/LDAPProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/radius/RadiusProviderViewPage.ts
|
||||
msgid "Warning: Provider is not used by any Outpost."
|
||||
msgstr "Warnung: Der Anbieter wird von keinem Outpost verwendet."
|
||||
|
||||
@ -7976,6 +7992,7 @@ msgid "When selected, a password field is shown on the same page instead of a se
|
||||
msgstr "Wenn diese Option ausgewählt ist, wird ein Passwortfeld auf derselben Seite statt auf einer separaten Seite angezeigt. Dadurch werden Angriffe auf die Aufzählung von Benutzernamen verhindert."
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr "Wenn diese Option ausgewählt ist, werden die Signaturen eingehender Behauptungen anhand dieses Zertifikats validiert. Um nicht signierte Anfragen zuzulassen, belassen Sie die Standardeinstellung."
|
||||
|
||||
|
@ -401,7 +401,7 @@ msgstr "Advanced settings"
|
||||
msgid "Affected model:"
|
||||
msgstr "Affected model:"
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Alert"
|
||||
msgstr "Alert"
|
||||
|
||||
@ -776,6 +776,10 @@ msgstr "Authenticating with Plex..."
|
||||
msgid "Authentication"
|
||||
msgstr "Authentication"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Authentication code"
|
||||
msgstr "Authentication code"
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderForm.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderForm.ts
|
||||
#: src/admin/providers/radius/RadiusProviderForm.ts
|
||||
@ -1420,7 +1424,6 @@ msgstr "Close"
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_sms/AuthenticatorSMSStage.ts
|
||||
#: src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Code"
|
||||
msgstr "Code"
|
||||
|
||||
@ -4444,7 +4447,7 @@ msgstr "Not you?"
|
||||
msgid "Notes"
|
||||
msgstr "Notes"
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Notice"
|
||||
msgstr "Notice"
|
||||
|
||||
@ -4624,6 +4627,10 @@ msgstr "Open login"
|
||||
msgid "Open settings"
|
||||
msgstr "Open settings"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Open your two-factor authenticator app to view your authentication code."
|
||||
msgstr "Open your two-factor authenticator app to view your authentication code."
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
msgid "OpenID Configuration Issuer"
|
||||
msgstr "OpenID Configuration Issuer"
|
||||
@ -4919,8 +4926,11 @@ msgstr "Plan history"
|
||||
msgid "Please enter the code you received via SMS"
|
||||
msgstr "Please enter the code you received via SMS"
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Please enter your code"
|
||||
msgstr "Please enter your code"
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
msgid "Please enter your Code"
|
||||
msgstr "Please enter your Code"
|
||||
|
||||
@ -7318,8 +7328,8 @@ msgstr "Unknown provider type"
|
||||
msgid "Unknown proxy mode"
|
||||
msgstr "Unknown proxy mode"
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Unknown severity"
|
||||
msgstr "Unknown severity"
|
||||
|
||||
@ -7920,6 +7930,7 @@ msgid "Verification"
|
||||
msgstr "Verification"
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "Verification Certificate"
|
||||
msgstr "Verification Certificate"
|
||||
|
||||
@ -7980,7 +7991,7 @@ msgstr "Waiting for authentication..."
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/blueprints/BlueprintListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/system-tasks/SystemTaskListPage.ts
|
||||
msgid "Warning"
|
||||
msgstr "Warning"
|
||||
@ -8005,6 +8016,10 @@ msgstr "Warning: No invitation stage is bound to any flow. Invitations will not
|
||||
msgid "Warning: Policy is not assigned."
|
||||
msgstr "Warning: Policy is not assigned."
|
||||
|
||||
#: src/admin/providers/scim/SCIMProviderViewPage.ts
|
||||
msgid "Warning: Provider is not assigned to an application as backchannel provider."
|
||||
msgstr "Warning: Provider is not assigned to an application as backchannel provider."
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
@ -8013,6 +8028,7 @@ msgstr "Warning: Provider is not used by an Application."
|
||||
|
||||
#: src/admin/providers/ldap/LDAPProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/radius/RadiusProviderViewPage.ts
|
||||
msgid "Warning: Provider is not used by any Outpost."
|
||||
msgstr "Warning: Provider is not used by any Outpost."
|
||||
|
||||
@ -8149,6 +8165,7 @@ msgid "When selected, a password field is shown on the same page instead of a se
|
||||
msgstr "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default."
|
||||
|
||||
|
@ -398,7 +398,7 @@ msgstr "Configuraciones avanzadas"
|
||||
msgid "Affected model:"
|
||||
msgstr "Modelo afectado:"
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Alert"
|
||||
msgstr "Alerta"
|
||||
|
||||
@ -769,6 +769,10 @@ msgstr "Autenticando con Plex..."
|
||||
msgid "Authentication"
|
||||
msgstr "Autenticación"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Authentication code"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderForm.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderForm.ts
|
||||
#: src/admin/providers/radius/RadiusProviderForm.ts
|
||||
@ -1399,7 +1403,6 @@ msgstr "Cerrar"
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_sms/AuthenticatorSMSStage.ts
|
||||
#: src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Code"
|
||||
msgstr "Código"
|
||||
|
||||
@ -4358,7 +4361,7 @@ msgstr "¿No eres tú?"
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Notice"
|
||||
msgstr "Notificación"
|
||||
|
||||
@ -4530,6 +4533,10 @@ msgstr ""
|
||||
msgid "Open settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Open your two-factor authenticator app to view your authentication code."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
msgid "OpenID Configuration Issuer"
|
||||
msgstr "Emisor de configuración de OpenID"
|
||||
@ -4803,8 +4810,11 @@ msgstr "Historial del plan"
|
||||
msgid "Please enter the code you received via SMS"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Please enter your code"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
msgid "Please enter your Code"
|
||||
msgstr "Por favor, introduzca su código"
|
||||
|
||||
@ -7136,8 +7146,8 @@ msgstr ""
|
||||
msgid "Unknown proxy mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Unknown severity"
|
||||
msgstr ""
|
||||
|
||||
@ -7732,6 +7742,7 @@ msgid "Verification"
|
||||
msgstr "Verificación"
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "Verification Certificate"
|
||||
msgstr "Certificado de verificación"
|
||||
|
||||
@ -7790,7 +7801,7 @@ msgstr ""
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/blueprints/BlueprintListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/system-tasks/SystemTaskListPage.ts
|
||||
msgid "Warning"
|
||||
msgstr "Aviso"
|
||||
@ -7815,6 +7826,10 @@ msgstr "Advertencia: ninguna etapa de invitación está vinculada a ningún fluj
|
||||
msgid "Warning: Policy is not assigned."
|
||||
msgstr "Advertencia: la política no está asignada."
|
||||
|
||||
#: src/admin/providers/scim/SCIMProviderViewPage.ts
|
||||
msgid "Warning: Provider is not assigned to an application as backchannel provider."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
@ -7823,6 +7838,7 @@ msgstr "Advertencia: Una aplicación no utiliza el proveedor."
|
||||
|
||||
#: src/admin/providers/ldap/LDAPProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/radius/RadiusProviderViewPage.ts
|
||||
msgid "Warning: Provider is not used by any Outpost."
|
||||
msgstr "Advertencia: ningún puesto avanzado utiliza el proveedor."
|
||||
|
||||
@ -7952,6 +7968,7 @@ msgid "When selected, a password field is shown on the same page instead of a se
|
||||
msgstr "Cuando se selecciona, se muestra un campo de contraseña en la misma página en lugar de en una página separada. Esto evita ataques de enumeración de nombres de usuario."
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr "Cuando se selecciona, las firmas de la aserción entrante se validarán con este certificado. Para permitir solicitudes sin firmar, déjelo en el valor predeterminado."
|
||||
|
||||
|
@ -403,7 +403,7 @@ msgstr "Paramètres avancés"
|
||||
msgid "Affected model:"
|
||||
msgstr "Modèle affecté :"
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Alert"
|
||||
msgstr "Alerte"
|
||||
|
||||
@ -774,6 +774,10 @@ msgstr "Authentification avec Plex..."
|
||||
msgid "Authentication"
|
||||
msgstr "Authentification"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Authentication code"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderForm.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderForm.ts
|
||||
#: src/admin/providers/radius/RadiusProviderForm.ts
|
||||
@ -1404,7 +1408,6 @@ msgstr "Fermer"
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_sms/AuthenticatorSMSStage.ts
|
||||
#: src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Code"
|
||||
msgstr "Code"
|
||||
|
||||
@ -4359,7 +4362,7 @@ msgstr "Pas vous ?"
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Notice"
|
||||
msgstr "Note"
|
||||
|
||||
@ -4531,6 +4534,10 @@ msgstr ""
|
||||
msgid "Open settings"
|
||||
msgstr "Ouvrir les paramètres"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Open your two-factor authenticator app to view your authentication code."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
msgid "OpenID Configuration Issuer"
|
||||
msgstr "Émetteur de la configuration OpenID"
|
||||
@ -4804,8 +4811,11 @@ msgstr "Historique du plan"
|
||||
msgid "Please enter the code you received via SMS"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Please enter your code"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
msgid "Please enter your Code"
|
||||
msgstr "Entrez votre code"
|
||||
|
||||
@ -7127,8 +7137,8 @@ msgstr ""
|
||||
msgid "Unknown proxy mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Unknown severity"
|
||||
msgstr ""
|
||||
|
||||
@ -7723,6 +7733,7 @@ msgid "Verification"
|
||||
msgstr "Vérification"
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "Verification Certificate"
|
||||
msgstr "Certificat de validation"
|
||||
|
||||
@ -7781,7 +7792,7 @@ msgstr ""
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/blueprints/BlueprintListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/system-tasks/SystemTaskListPage.ts
|
||||
msgid "Warning"
|
||||
msgstr "Avertissement"
|
||||
@ -7806,6 +7817,10 @@ msgstr "Attention : aucune étape d’invitation n’a été ajoutée à aucun f
|
||||
msgid "Warning: Policy is not assigned."
|
||||
msgstr "Avertissement : la politique n'est pas assignée."
|
||||
|
||||
#: src/admin/providers/scim/SCIMProviderViewPage.ts
|
||||
msgid "Warning: Provider is not assigned to an application as backchannel provider."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
@ -7814,6 +7829,7 @@ msgstr ""
|
||||
|
||||
#: src/admin/providers/ldap/LDAPProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/radius/RadiusProviderViewPage.ts
|
||||
msgid "Warning: Provider is not used by any Outpost."
|
||||
msgstr "Attention : ce fournisseur n’est utilisé par aucun avant-poste."
|
||||
|
||||
@ -7943,6 +7959,7 @@ msgid "When selected, a password field is shown on the same page instead of a se
|
||||
msgstr "Si activée, un champ de mot de passe est affiché sur la même page au lieu d'une page séparée. Cela permet d'éviter les attaques par énumération de noms d'utilisateur."
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr "Si activée, les signatures des assertions entrantes seront validées par rapport à ce certificat. Pour autoriser les requêtes non signées, laissez la valeur par défaut."
|
||||
|
||||
|
@ -402,7 +402,7 @@ msgstr "Zaawansowane ustawienia"
|
||||
msgid "Affected model:"
|
||||
msgstr "Model, którego dotyczy problem:"
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Alert"
|
||||
msgstr "Alert"
|
||||
|
||||
@ -773,6 +773,10 @@ msgstr "Uwierzytelnianie z Plex..."
|
||||
msgid "Authentication"
|
||||
msgstr "Uwierzytelnianie"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Authentication code"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderForm.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderForm.ts
|
||||
#: src/admin/providers/radius/RadiusProviderForm.ts
|
||||
@ -1405,7 +1409,6 @@ msgstr "Zamknij"
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_sms/AuthenticatorSMSStage.ts
|
||||
#: src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Code"
|
||||
msgstr "Kod"
|
||||
|
||||
@ -4366,7 +4369,7 @@ msgstr "Nie ty?"
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Notice"
|
||||
msgstr "Uwaga"
|
||||
|
||||
@ -4538,6 +4541,10 @@ msgstr ""
|
||||
msgid "Open settings"
|
||||
msgstr "Otwórz ustawienia"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Open your two-factor authenticator app to view your authentication code."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
msgid "OpenID Configuration Issuer"
|
||||
msgstr "Wystawca konfiguracji OpenID"
|
||||
@ -4811,8 +4818,11 @@ msgstr "Historia planu"
|
||||
msgid "Please enter the code you received via SMS"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Please enter your code"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
msgid "Please enter your Code"
|
||||
msgstr "Wprowadź swój kod"
|
||||
|
||||
@ -7146,8 +7156,8 @@ msgstr ""
|
||||
msgid "Unknown proxy mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Unknown severity"
|
||||
msgstr ""
|
||||
|
||||
@ -7742,6 +7752,7 @@ msgid "Verification"
|
||||
msgstr "Weryfikacja"
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "Verification Certificate"
|
||||
msgstr "Certyfikat weryfikacji"
|
||||
|
||||
@ -7800,7 +7811,7 @@ msgstr ""
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/blueprints/BlueprintListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/system-tasks/SystemTaskListPage.ts
|
||||
msgid "Warning"
|
||||
msgstr "Ostrzeżenie"
|
||||
@ -7825,6 +7836,10 @@ msgstr "Ostrzeżenie: żaden etap zaproszenia nie jest powiązany z żadnym prze
|
||||
msgid "Warning: Policy is not assigned."
|
||||
msgstr "Ostrzeżenie: zasada nie jest przypisana."
|
||||
|
||||
#: src/admin/providers/scim/SCIMProviderViewPage.ts
|
||||
msgid "Warning: Provider is not assigned to an application as backchannel provider."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
@ -7833,6 +7848,7 @@ msgstr "Ostrzeżenie: Dostawca nie jest używany przez aplikację."
|
||||
|
||||
#: src/admin/providers/ldap/LDAPProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/radius/RadiusProviderViewPage.ts
|
||||
msgid "Warning: Provider is not used by any Outpost."
|
||||
msgstr "Ostrzeżenie: Dostawca nie jest używany przez żadną placówkę."
|
||||
|
||||
@ -7964,6 +7980,7 @@ msgid "When selected, a password field is shown on the same page instead of a se
|
||||
msgstr "Po wybraniu pole hasła jest wyświetlane na tej samej stronie zamiast na osobnej stronie. Zapobiega to atakom polegającym na wyliczaniu nazw użytkowników."
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr "Po wybraniu, przychodzące podpisy asercji będą sprawdzane względem tego certyfikatu. Aby zezwolić na niepodpisane żądania, pozostaw domyślnie."
|
||||
|
||||
|
@ -397,7 +397,7 @@ msgstr ""
|
||||
msgid "Affected model:"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Alert"
|
||||
msgstr ""
|
||||
|
||||
@ -768,6 +768,10 @@ msgstr ""
|
||||
msgid "Authentication"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Authentication code"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderForm.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderForm.ts
|
||||
#: src/admin/providers/radius/RadiusProviderForm.ts
|
||||
@ -1408,7 +1412,6 @@ msgstr ""
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_sms/AuthenticatorSMSStage.ts
|
||||
#: src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Code"
|
||||
msgstr ""
|
||||
|
||||
@ -4423,7 +4426,7 @@ msgstr ""
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Notice"
|
||||
msgstr ""
|
||||
|
||||
@ -4603,6 +4606,10 @@ msgstr ""
|
||||
msgid "Open settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Open your two-factor authenticator app to view your authentication code."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
msgid "OpenID Configuration Issuer"
|
||||
msgstr ""
|
||||
@ -4889,8 +4896,11 @@ msgstr ""
|
||||
msgid "Please enter the code you received via SMS"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Please enter your code"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
msgid "Please enter your Code"
|
||||
msgstr ""
|
||||
|
||||
@ -7276,8 +7286,8 @@ msgstr ""
|
||||
msgid "Unknown proxy mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Unknown severity"
|
||||
msgstr ""
|
||||
|
||||
@ -7878,6 +7888,7 @@ msgid "Verification"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "Verification Certificate"
|
||||
msgstr ""
|
||||
|
||||
@ -7938,7 +7949,7 @@ msgstr ""
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/blueprints/BlueprintListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/system-tasks/SystemTaskListPage.ts
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
@ -7963,6 +7974,10 @@ msgstr ""
|
||||
msgid "Warning: Policy is not assigned."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/scim/SCIMProviderViewPage.ts
|
||||
msgid "Warning: Provider is not assigned to an application as backchannel provider."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
@ -7971,6 +7986,7 @@ msgstr ""
|
||||
|
||||
#: src/admin/providers/ldap/LDAPProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/radius/RadiusProviderViewPage.ts
|
||||
msgid "Warning: Provider is not used by any Outpost."
|
||||
msgstr ""
|
||||
|
||||
@ -8101,6 +8117,7 @@ msgid "When selected, a password field is shown on the same page instead of a se
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr ""
|
||||
|
||||
|
@ -398,7 +398,7 @@ msgstr "Gelişmiş ayarlar"
|
||||
msgid "Affected model:"
|
||||
msgstr "Etkilenen model:"
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Alert"
|
||||
msgstr "Alarm"
|
||||
|
||||
@ -769,6 +769,10 @@ msgstr "Plex ile kimlik doğrulaması..."
|
||||
msgid "Authentication"
|
||||
msgstr "Kimlik Doğrulama"
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Authentication code"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderForm.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderForm.ts
|
||||
#: src/admin/providers/radius/RadiusProviderForm.ts
|
||||
@ -1399,7 +1403,6 @@ msgstr "Kapat"
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_sms/AuthenticatorSMSStage.ts
|
||||
#: src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Code"
|
||||
msgstr "Kodu"
|
||||
|
||||
@ -4358,7 +4361,7 @@ msgstr "Sen değil mi?"
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Notice"
|
||||
msgstr "Uyarı"
|
||||
|
||||
@ -4530,6 +4533,10 @@ msgstr ""
|
||||
msgid "Open settings"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Open your two-factor authenticator app to view your authentication code."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
msgid "OpenID Configuration Issuer"
|
||||
msgstr "OpenID Yapılandırması Yayımlayıcı"
|
||||
@ -4803,8 +4810,11 @@ msgstr "Plan geçmişi"
|
||||
msgid "Please enter the code you received via SMS"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
#: src/flow/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
|
||||
msgid "Please enter your code"
|
||||
msgstr ""
|
||||
|
||||
#: src/flow/providers/oauth2/DeviceCode.ts
|
||||
msgid "Please enter your Code"
|
||||
msgstr "Lütfen Kodunuzu girin"
|
||||
|
||||
@ -7136,8 +7146,8 @@ msgstr ""
|
||||
msgid "Unknown proxy mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/events/utils.ts
|
||||
msgid "Unknown severity"
|
||||
msgstr ""
|
||||
|
||||
@ -7732,6 +7742,7 @@ msgid "Verification"
|
||||
msgstr "Doğrulama"
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "Verification Certificate"
|
||||
msgstr "Doğrulama Sertifikası"
|
||||
|
||||
@ -7790,7 +7801,7 @@ msgstr ""
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/admin-overview/cards/SystemStatusCard.ts
|
||||
#: src/admin/blueprints/BlueprintListPage.ts
|
||||
#: src/admin/events/RuleListPage.ts
|
||||
#: src/admin/events/utils.ts
|
||||
#: src/admin/system-tasks/SystemTaskListPage.ts
|
||||
msgid "Warning"
|
||||
msgstr "Uyarı"
|
||||
@ -7815,6 +7826,10 @@ msgstr "Uyarı: Hiçbir davetiye aşaması herhangi bir akışa bağlı değildi
|
||||
msgid "Warning: Policy is not assigned."
|
||||
msgstr "Uyarı: İlke atanmamış."
|
||||
|
||||
#: src/admin/providers/scim/SCIMProviderViewPage.ts
|
||||
msgid "Warning: Provider is not assigned to an application as backchannel provider."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
@ -7823,6 +7838,7 @@ msgstr "Uyarı: Sağlayıcı bir Uygulama tarafından kullanılmaz."
|
||||
|
||||
#: src/admin/providers/ldap/LDAPProviderViewPage.ts
|
||||
#: src/admin/providers/proxy/ProxyProviderViewPage.ts
|
||||
#: src/admin/providers/radius/RadiusProviderViewPage.ts
|
||||
msgid "Warning: Provider is not used by any Outpost."
|
||||
msgstr "Uyarı: Sağlayıcı herhangi bir Üs tarafından kullanılmaz."
|
||||
|
||||
@ -7952,6 +7968,7 @@ msgid "When selected, a password field is shown on the same page instead of a se
|
||||
msgstr "Seçildiğinde, ayrı bir sayfa yerine aynı sayfada bir parola alanı gösterilir. Bu, kullanıcı adı numaralandırma saldırılarını engeller."
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderForm.ts
|
||||
#: src/admin/sources/saml/SAMLSourceForm.ts
|
||||
msgid "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default."
|
||||
msgstr "Seçildiğinde, gelen onaylama öğesinin İmzaları bu sertifikaya göre doğrulanır. İmzasız İsteklere izin vermek için varsayılan olarak bırakın."
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user