Compare commits
118 commits
trustchain
...
sources/ld
Author | SHA1 | Date | |
---|---|---|---|
3835734ed4 | |||
e0355b13cd | |||
d092093e94 | |||
f728bbb14b | |||
4080080acd | |||
0a0f87b9ca | |||
7699a119a3 | |||
73fbcde924 | |||
a1efcc4da9 | |||
d594574ffa | |||
dbbb5e75cf | |||
ddb73db287 | |||
143f092153 | |||
d89adef963 | |||
5f3cbf6f7f | |||
a9fdacc60b | |||
9db9ad3d66 | |||
11dcda77fa | |||
4ce5f0931b | |||
f8e2cd5639 | |||
8b4f66e457 | |||
939631c94e | |||
467a149c06 | |||
f62f720c55 | |||
ba8fd9fcb2 | |||
fdc323af62 | |||
44bac0d67b | |||
191514864e | |||
258a4d5283 | |||
62a85fb888 | |||
7685320466 | |||
c30a2406a9 | |||
9232042c55 | |||
d8b1a59dad | |||
1e05d38059 | |||
d5871fef4e | |||
7f4fa70a41 | |||
fa0c4d8410 | |||
aeb24889fd | |||
8ac9042501 | |||
2d821a07c6 | |||
9680106b45 | |||
709358615c | |||
0ad1b42706 | |||
2333e1f434 | |||
4444db9e6d | |||
c5d483a238 | |||
cc1c66aa13 | |||
67d6c0e8af | |||
b9afac5008 | |||
aadda1f314 | |||
293fa2e375 | |||
ddb1597501 | |||
96f8e961ea | |||
f699dba2ae | |||
250e8ee4a1 | |||
ce47755049 | |||
8125a790a9 | |||
b7e653db6a | |||
74958693a1 | |||
cadc311703 | |||
924f3c9075 | |||
a7933c84c1 | |||
fe1a06ebf2 | |||
823e7dbe1a | |||
90b8217eb2 | |||
c897271756 | |||
d1c9d41954 | |||
1906a10b1a | |||
a03cc57473 | |||
e00799b314 | |||
faa5ce3e83 | |||
937d025ef6 | |||
a748a61cd6 | |||
b24420598c | |||
b005ec7684 | |||
6f6ee29738 | |||
ff3fef6d09 | |||
515958157c | |||
dd4e9030b4 | |||
f94670cad7 | |||
b4dd74f2ff | |||
9a2b548bf6 | |||
d6e3de4f48 | |||
30ccaaf97c | |||
3d9f7ee27e | |||
211dcf3272 | |||
1d0b8a065b | |||
7f82b555c8 | |||
f7aec3cf28 | |||
c6c133f67d | |||
73db23f21f | |||
4744f5c6c6 | |||
e92bda2659 | |||
a10392efcc | |||
e52f13afae | |||
07c50a43ae | |||
0cd2f68bf3 | |||
4ef10f1cec | |||
43151c09e2 | |||
871b5f3246 | |||
ed66bdaec4 | |||
345022f1aa | |||
f296862d3c | |||
5aca310d10 | |||
7dab5dc03f | |||
2d6e0984d1 | |||
028c7af00f | |||
6df83e4259 | |||
afdca418e1 | |||
d8728c1749 | |||
e5afabb221 | |||
a0a6ee0769 | |||
a65bb0b29f | |||
3df7b5504e | |||
99f44ea805 | |||
97ccc84796 | |||
a43b2fb17c |
|
@ -1,5 +1,5 @@
|
|||
[bumpversion]
|
||||
current_version = 2023.10.2
|
||||
current_version = 2023.10.3
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
|
||||
|
|
7
.github/workflows/ci-main.yml
vendored
7
.github/workflows/ci-main.yml
vendored
|
@ -11,6 +11,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- version-*
|
||||
|
||||
env:
|
||||
POSTGRES_DB: authentik
|
||||
|
@ -185,6 +186,9 @@ jobs:
|
|||
build:
|
||||
needs: ci-core-mark
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload contianer images to ghcr.io
|
||||
packages: write
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
@ -235,6 +239,9 @@ jobs:
|
|||
build-arm64:
|
||||
needs: ci-core-mark
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload contianer images to ghcr.io
|
||||
packages: write
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
4
.github/workflows/ci-outpost.yml
vendored
4
.github/workflows/ci-outpost.yml
vendored
|
@ -9,6 +9,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- version-*
|
||||
|
||||
jobs:
|
||||
lint-golint:
|
||||
|
@ -65,6 +66,9 @@ jobs:
|
|||
- ldap
|
||||
- radius
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload contianer images to ghcr.io
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
|
1
.github/workflows/ci-web.yml
vendored
1
.github/workflows/ci-web.yml
vendored
|
@ -9,6 +9,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- version-*
|
||||
|
||||
jobs:
|
||||
lint-eslint:
|
||||
|
|
1
.github/workflows/ci-website.yml
vendored
1
.github/workflows/ci-website.yml
vendored
|
@ -9,6 +9,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- version-*
|
||||
|
||||
jobs:
|
||||
lint-prettier:
|
||||
|
|
1
.github/workflows/release-next-branch.yml
vendored
1
.github/workflows/release-next-branch.yml
vendored
|
@ -6,6 +6,7 @@ on:
|
|||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
# Needed to be able to push to the next branch
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
|
|
9
.github/workflows/release-publish.yml
vendored
9
.github/workflows/release-publish.yml
vendored
|
@ -7,6 +7,9 @@ on:
|
|||
jobs:
|
||||
build-server:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload contianer images to ghcr.io
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up QEMU
|
||||
|
@ -52,6 +55,9 @@ jobs:
|
|||
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
|
||||
build-outpost:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload contianer images to ghcr.io
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
@ -106,6 +112,9 @@ jobs:
|
|||
build-outpost-binary:
|
||||
timeout-minutes: 120
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload binaries to the release
|
||||
contents: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
2
.github/workflows/repo-stale.yml
vendored
2
.github/workflows/repo-stale.yml
vendored
|
@ -6,8 +6,8 @@ on:
|
|||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
# Needed to update issues and PRs
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
|
13
Dockerfile
13
Dockerfile
|
@ -35,7 +35,14 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
|
|||
RUN npm run build
|
||||
|
||||
# Stage 3: Build go proxy
|
||||
FROM docker.io/golang:1.21.3-bookworm AS go-builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS go-builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
|
||||
ARG GOOS=$TARGETOS
|
||||
ARG GOARCH=$TARGETARCH
|
||||
|
||||
WORKDIR /go/src/goauthentik.io
|
||||
|
||||
|
@ -57,10 +64,10 @@ ENV CGO_ENABLED=0
|
|||
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
go build -o /go/authentik ./cmd/server
|
||||
GOARM="${TARGETVARIANT#v}" go build -o /go/authentik ./cmd/server
|
||||
|
||||
# Stage 4: MaxMind GeoIP
|
||||
FROM ghcr.io/maxmind/geoipupdate:v6.0 as geoip
|
||||
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v6.0 as geoip
|
||||
|
||||
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City"
|
||||
ENV GEOIPUPDATE_VERBOSE="true"
|
||||
|
|
2
Makefile
2
Makefile
|
@ -110,6 +110,8 @@ gen-diff: ## (Release) generate the changelog diff between the current schema a
|
|||
--markdown /local/diff.md \
|
||||
/local/old_schema.yml /local/schema.yml
|
||||
rm old_schema.yml
|
||||
sed -i 's/{/{/g' diff.md
|
||||
sed -i 's/}/}/g' diff.md
|
||||
npx prettier --write diff.md
|
||||
|
||||
gen-clean:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from os import environ
|
||||
from typing import Optional
|
||||
|
||||
__version__ = "2023.10.2"
|
||||
__version__ = "2023.10.3"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
||||
|
||||
|
|
|
@ -93,10 +93,10 @@ class ConfigView(APIView):
|
|||
"traces_sample_rate": float(CONFIG.get("error_reporting.sample_rate", 0.4)),
|
||||
},
|
||||
"capabilities": self.get_capabilities(),
|
||||
"cache_timeout": CONFIG.get_int("redis.cache_timeout"),
|
||||
"cache_timeout_flows": CONFIG.get_int("redis.cache_timeout_flows"),
|
||||
"cache_timeout_policies": CONFIG.get_int("redis.cache_timeout_policies"),
|
||||
"cache_timeout_reputation": CONFIG.get_int("redis.cache_timeout_reputation"),
|
||||
"cache_timeout": CONFIG.get_int("cache.timeout"),
|
||||
"cache_timeout_flows": CONFIG.get_int("cache.timeout_flows"),
|
||||
"cache_timeout_policies": CONFIG.get_int("cache.timeout_policies"),
|
||||
"cache_timeout_reputation": CONFIG.get_int("cache.timeout_reputation"),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -17,9 +17,15 @@ class Command(BaseCommand):
|
|||
"""Run worker"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("-b", "--beat", action="store_true")
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--beat",
|
||||
action="store_false",
|
||||
help="When set, this worker will _not_ run Beat (scheduled) tasks",
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
LOGGER.debug("Celery options", **options)
|
||||
close_old_connections()
|
||||
if CONFIG.get_bool("remote_debug"):
|
||||
import debugpy
|
||||
|
|
|
@ -13,6 +13,7 @@ from authentik.events.tasks import event_notification_handler, gdpr_cleanup
|
|||
from authentik.flows.models import Stage
|
||||
from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan
|
||||
from authentik.flows.views.executor import SESSION_KEY_PLAN
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.stages.invitation.models import Invitation
|
||||
from authentik.stages.invitation.signals import invitation_used
|
||||
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
|
||||
|
@ -92,4 +93,5 @@ def event_post_save_notification(sender, instance: Event, **_):
|
|||
@receiver(pre_delete, sender=User)
|
||||
def event_user_pre_delete_cleanup(sender, instance: User, **_):
|
||||
"""If gdpr_compliance is enabled, remove all the user's events"""
|
||||
if CONFIG.get_bool("gdpr_compliance", True):
|
||||
gdpr_cleanup.delay(instance.pk)
|
||||
|
|
|
@ -33,7 +33,7 @@ PLAN_CONTEXT_SOURCE = "source"
|
|||
# Is set by the Flow Planner when a FlowToken was used, and the currently active flow plan
|
||||
# was restored.
|
||||
PLAN_CONTEXT_IS_RESTORED = "is_restored"
|
||||
CACHE_TIMEOUT = CONFIG.get_int("redis.cache_timeout_flows")
|
||||
CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_flows")
|
||||
CACHE_PREFIX = "goauthentik.io/flows/planner/"
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
"""authentik core config loader"""
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
from collections.abc import Mapping
|
||||
from contextlib import contextmanager
|
||||
|
@ -22,6 +24,25 @@ SEARCH_PATHS = ["authentik/lib/default.yml", "/etc/authentik/config.yml", ""] +
|
|||
ENV_PREFIX = "AUTHENTIK"
|
||||
ENVIRONMENT = os.getenv(f"{ENV_PREFIX}_ENV", "local")
|
||||
|
||||
REDIS_ENV_KEYS = [
|
||||
f"{ENV_PREFIX}_REDIS__HOST",
|
||||
f"{ENV_PREFIX}_REDIS__PORT",
|
||||
f"{ENV_PREFIX}_REDIS__DB",
|
||||
f"{ENV_PREFIX}_REDIS__USERNAME",
|
||||
f"{ENV_PREFIX}_REDIS__PASSWORD",
|
||||
f"{ENV_PREFIX}_REDIS__TLS",
|
||||
f"{ENV_PREFIX}_REDIS__TLS_REQS",
|
||||
]
|
||||
|
||||
DEPRECATIONS = {
|
||||
"redis.broker_url": "broker.url",
|
||||
"redis.broker_transport_options": "broker.transport_options",
|
||||
"redis.cache_timeout": "cache.timeout",
|
||||
"redis.cache_timeout_flows": "cache.timeout_flows",
|
||||
"redis.cache_timeout_policies": "cache.timeout_policies",
|
||||
"redis.cache_timeout_reputation": "cache.timeout_reputation",
|
||||
}
|
||||
|
||||
|
||||
def get_path_from_dict(root: dict, path: str, sep=".", default=None) -> Any:
|
||||
"""Recursively walk through `root`, checking each part of `path` separated by `sep`.
|
||||
|
@ -81,6 +102,10 @@ class AttrEncoder(JSONEncoder):
|
|||
return super().default(o)
|
||||
|
||||
|
||||
class UNSET:
|
||||
"""Used to test whether configuration key has not been set."""
|
||||
|
||||
|
||||
class ConfigLoader:
|
||||
"""Search through SEARCH_PATHS and load configuration. Environment variables starting with
|
||||
`ENV_PREFIX` are also applied.
|
||||
|
@ -113,6 +138,40 @@ class ConfigLoader:
|
|||
self.update_from_file(env_file)
|
||||
self.update_from_env()
|
||||
self.update(self.__config, kwargs)
|
||||
self.check_deprecations()
|
||||
|
||||
def check_deprecations(self):
|
||||
"""Warn if any deprecated configuration options are used"""
|
||||
|
||||
def _pop_deprecated_key(current_obj, dot_parts, index):
|
||||
"""Recursive function to remove deprecated keys in configuration"""
|
||||
dot_part = dot_parts[index]
|
||||
if index == len(dot_parts) - 1:
|
||||
return current_obj.pop(dot_part)
|
||||
value = _pop_deprecated_key(current_obj[dot_part], dot_parts, index + 1)
|
||||
if not current_obj[dot_part]:
|
||||
current_obj.pop(dot_part)
|
||||
return value
|
||||
|
||||
for deprecation, replacement in DEPRECATIONS.items():
|
||||
if self.get(deprecation, default=UNSET) is not UNSET:
|
||||
message = (
|
||||
f"'{deprecation}' has been deprecated in favor of '{replacement}'! "
|
||||
+ "Please update your configuration."
|
||||
)
|
||||
self.log(
|
||||
"warning",
|
||||
message,
|
||||
)
|
||||
try:
|
||||
from authentik.events.models import Event, EventAction
|
||||
|
||||
Event.new(EventAction.CONFIGURATION_ERROR, message=message).save()
|
||||
except ImportError:
|
||||
continue
|
||||
|
||||
deprecated_attr = _pop_deprecated_key(self.__config, deprecation.split("."), 0)
|
||||
self.set(replacement, deprecated_attr.value)
|
||||
|
||||
def log(self, level: str, message: str, **kwargs):
|
||||
"""Custom Log method, we want to ensure ConfigLoader always logs JSON even when
|
||||
|
@ -180,6 +239,10 @@ class ConfigLoader:
|
|||
error=str(exc),
|
||||
)
|
||||
|
||||
def update_from_dict(self, update: dict):
|
||||
"""Update config from dict"""
|
||||
self.__config.update(update)
|
||||
|
||||
def update_from_env(self):
|
||||
"""Check environment variables"""
|
||||
outer = {}
|
||||
|
@ -188,19 +251,13 @@ class ConfigLoader:
|
|||
if not key.startswith(ENV_PREFIX):
|
||||
continue
|
||||
relative_key = key.replace(f"{ENV_PREFIX}_", "", 1).replace("__", ".").lower()
|
||||
# Recursively convert path from a.b.c into outer[a][b][c]
|
||||
current_obj = outer
|
||||
dot_parts = relative_key.split(".")
|
||||
for dot_part in dot_parts[:-1]:
|
||||
if dot_part not in current_obj:
|
||||
current_obj[dot_part] = {}
|
||||
current_obj = current_obj[dot_part]
|
||||
# Check if the value is json, and try to load it
|
||||
try:
|
||||
value = loads(value)
|
||||
except JSONDecodeError:
|
||||
pass
|
||||
current_obj[dot_parts[-1]] = Attr(value, Attr.Source.ENV, key)
|
||||
attr_value = Attr(value, Attr.Source.ENV, relative_key)
|
||||
set_path_in_dict(outer, relative_key, attr_value)
|
||||
idx += 1
|
||||
if idx > 0:
|
||||
self.log("debug", "Loaded environment variables", count=idx)
|
||||
|
@ -241,6 +298,23 @@ class ConfigLoader:
|
|||
"""Wrapper for get that converts value into boolean"""
|
||||
return str(self.get(path, default)).lower() == "true"
|
||||
|
||||
def get_dict_from_b64_json(self, path: str, default=None) -> dict:
|
||||
"""Wrapper for get that converts value from Base64 encoded string into dictionary"""
|
||||
config_value = self.get(path)
|
||||
if config_value is None:
|
||||
return {}
|
||||
try:
|
||||
b64decoded_str = base64.b64decode(config_value).decode("utf-8")
|
||||
b64decoded_str = b64decoded_str.strip().lstrip("{").rstrip("}")
|
||||
b64decoded_str = "{" + b64decoded_str + "}"
|
||||
return json.loads(b64decoded_str)
|
||||
except (JSONDecodeError, TypeError, ValueError) as exc:
|
||||
self.log(
|
||||
"warning",
|
||||
f"Ignored invalid configuration for '{path}' due to exception: {str(exc)}",
|
||||
)
|
||||
return default if isinstance(default, dict) else {}
|
||||
|
||||
def set(self, path: str, value: Any, sep="."):
|
||||
"""Set value using same syntax as get()"""
|
||||
set_path_in_dict(self.raw, path, Attr(value), sep=sep)
|
||||
|
|
|
@ -28,14 +28,28 @@ listen:
|
|||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
db: 0
|
||||
username: ""
|
||||
password: ""
|
||||
tls: false
|
||||
tls_reqs: "none"
|
||||
db: 0
|
||||
cache_timeout: 300
|
||||
cache_timeout_flows: 300
|
||||
cache_timeout_policies: 300
|
||||
cache_timeout_reputation: 300
|
||||
|
||||
# broker:
|
||||
# url: ""
|
||||
# transport_options: ""
|
||||
|
||||
cache:
|
||||
# url: ""
|
||||
timeout: 300
|
||||
timeout_flows: 300
|
||||
timeout_policies: 300
|
||||
timeout_reputation: 300
|
||||
|
||||
# channel:
|
||||
# url: ""
|
||||
|
||||
# result_backend:
|
||||
# url: ""
|
||||
|
||||
paths:
|
||||
media: ./media
|
||||
|
|
|
@ -1,20 +1,32 @@
|
|||
"""Test config loader"""
|
||||
import base64
|
||||
from json import dumps
|
||||
from os import chmod, environ, unlink, write
|
||||
from tempfile import mkstemp
|
||||
from unittest import mock
|
||||
|
||||
from django.conf import ImproperlyConfigured
|
||||
from django.test import TestCase
|
||||
|
||||
from authentik.lib.config import ENV_PREFIX, ConfigLoader
|
||||
from authentik.lib.config import ENV_PREFIX, UNSET, Attr, AttrEncoder, ConfigLoader
|
||||
|
||||
|
||||
class TestConfig(TestCase):
|
||||
"""Test config loader"""
|
||||
|
||||
check_deprecations_env_vars = {
|
||||
ENV_PREFIX + "_REDIS__BROKER_URL": "redis://myredis:8327/43",
|
||||
ENV_PREFIX + "_REDIS__BROKER_TRANSPORT_OPTIONS": "bWFzdGVybmFtZT1teW1hc3Rlcg==",
|
||||
ENV_PREFIX + "_REDIS__CACHE_TIMEOUT": "124s",
|
||||
ENV_PREFIX + "_REDIS__CACHE_TIMEOUT_FLOWS": "32m",
|
||||
ENV_PREFIX + "_REDIS__CACHE_TIMEOUT_POLICIES": "3920ns",
|
||||
ENV_PREFIX + "_REDIS__CACHE_TIMEOUT_REPUTATION": "298382us",
|
||||
}
|
||||
|
||||
@mock.patch.dict(environ, {ENV_PREFIX + "_test__test": "bar"})
|
||||
def test_env(self):
|
||||
"""Test simple instance"""
|
||||
config = ConfigLoader()
|
||||
environ[ENV_PREFIX + "_test__test"] = "bar"
|
||||
config.update_from_env()
|
||||
self.assertEqual(config.get("test.test"), "bar")
|
||||
|
||||
|
@ -27,12 +39,20 @@ class TestConfig(TestCase):
|
|||
self.assertEqual(config.get("foo.bar"), "baz")
|
||||
self.assertEqual(config.get("foo.bar"), "bar")
|
||||
|
||||
@mock.patch.dict(environ, {"foo": "bar"})
|
||||
def test_uri_env(self):
|
||||
"""Test URI parsing (environment)"""
|
||||
config = ConfigLoader()
|
||||
environ["foo"] = "bar"
|
||||
self.assertEqual(config.parse_uri("env://foo").value, "bar")
|
||||
self.assertEqual(config.parse_uri("env://foo?bar").value, "bar")
|
||||
foo_uri = "env://foo"
|
||||
foo_parsed = config.parse_uri(foo_uri)
|
||||
self.assertEqual(foo_parsed.value, "bar")
|
||||
self.assertEqual(foo_parsed.source_type, Attr.Source.URI)
|
||||
self.assertEqual(foo_parsed.source, foo_uri)
|
||||
foo_bar_uri = "env://foo?bar"
|
||||
foo_bar_parsed = config.parse_uri(foo_bar_uri)
|
||||
self.assertEqual(foo_bar_parsed.value, "bar")
|
||||
self.assertEqual(foo_bar_parsed.source_type, Attr.Source.URI)
|
||||
self.assertEqual(foo_bar_parsed.source, foo_bar_uri)
|
||||
|
||||
def test_uri_file(self):
|
||||
"""Test URI parsing (file load)"""
|
||||
|
@ -91,3 +111,60 @@ class TestConfig(TestCase):
|
|||
config = ConfigLoader()
|
||||
config.set("foo", "bar")
|
||||
self.assertEqual(config.get_int("foo", 1234), 1234)
|
||||
|
||||
def test_get_dict_from_b64_json(self):
|
||||
"""Test get_dict_from_b64_json"""
|
||||
config = ConfigLoader()
|
||||
test_value = ' { "foo": "bar" } '.encode("utf-8")
|
||||
b64_value = base64.b64encode(test_value)
|
||||
config.set("foo", b64_value)
|
||||
self.assertEqual(config.get_dict_from_b64_json("foo"), {"foo": "bar"})
|
||||
|
||||
def test_get_dict_from_b64_json_missing_brackets(self):
|
||||
"""Test get_dict_from_b64_json with missing brackets"""
|
||||
config = ConfigLoader()
|
||||
test_value = ' "foo": "bar" '.encode("utf-8")
|
||||
b64_value = base64.b64encode(test_value)
|
||||
config.set("foo", b64_value)
|
||||
self.assertEqual(config.get_dict_from_b64_json("foo"), {"foo": "bar"})
|
||||
|
||||
def test_get_dict_from_b64_json_invalid(self):
|
||||
"""Test get_dict_from_b64_json with invalid value"""
|
||||
config = ConfigLoader()
|
||||
config.set("foo", "bar")
|
||||
self.assertEqual(config.get_dict_from_b64_json("foo"), {})
|
||||
|
||||
def test_attr_json_encoder(self):
|
||||
"""Test AttrEncoder"""
|
||||
test_attr = Attr("foo", Attr.Source.ENV, "AUTHENTIK_REDIS__USERNAME")
|
||||
json_attr = dumps(test_attr, indent=4, cls=AttrEncoder)
|
||||
self.assertEqual(json_attr, '"foo"')
|
||||
|
||||
def test_attr_json_encoder_no_attr(self):
|
||||
"""Test AttrEncoder if no Attr is passed"""
|
||||
|
||||
class Test:
|
||||
"""Non Attr class"""
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
test_obj = Test()
|
||||
dumps(test_obj, indent=4, cls=AttrEncoder)
|
||||
|
||||
@mock.patch.dict(environ, check_deprecations_env_vars)
|
||||
def test_check_deprecations(self):
|
||||
"""Test config key re-write for deprecated env vars"""
|
||||
config = ConfigLoader()
|
||||
config.update_from_env()
|
||||
config.check_deprecations()
|
||||
self.assertEqual(config.get("redis.broker_url", UNSET), UNSET)
|
||||
self.assertEqual(config.get("redis.broker_transport_options", UNSET), UNSET)
|
||||
self.assertEqual(config.get("redis.cache_timeout", UNSET), UNSET)
|
||||
self.assertEqual(config.get("redis.cache_timeout_flows", UNSET), UNSET)
|
||||
self.assertEqual(config.get("redis.cache_timeout_policies", UNSET), UNSET)
|
||||
self.assertEqual(config.get("redis.cache_timeout_reputation", UNSET), UNSET)
|
||||
self.assertEqual(config.get("broker.url"), "redis://myredis:8327/43")
|
||||
self.assertEqual(config.get("broker.transport_options"), "bWFzdGVybmFtZT1teW1hc3Rlcg==")
|
||||
self.assertEqual(config.get("cache.timeout"), "124s")
|
||||
self.assertEqual(config.get("cache.timeout_flows"), "32m")
|
||||
self.assertEqual(config.get("cache.timeout_policies"), "3920ns")
|
||||
self.assertEqual(config.get("cache.timeout_reputation"), "298382us")
|
||||
|
|
|
@ -93,7 +93,7 @@ class OutpostConsumer(AuthJsonConsumer):
|
|||
expected=self.outpost.config.kubernetes_replicas,
|
||||
).dec()
|
||||
|
||||
def receive_json(self, content: Data):
|
||||
def receive_json(self, content: Data, **kwargs):
|
||||
msg = from_dict(WebsocketMessage, content)
|
||||
uid = msg.args.get("uuid", self.channel_name)
|
||||
self.last_uid = uid
|
||||
|
|
|
@ -20,7 +20,7 @@ from authentik.policies.types import CACHE_PREFIX, PolicyRequest, PolicyResult
|
|||
LOGGER = get_logger()
|
||||
|
||||
FORK_CTX = get_context("fork")
|
||||
CACHE_TIMEOUT = CONFIG.get_int("redis.cache_timeout_policies")
|
||||
CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_policies")
|
||||
PROCESS_CLASS = FORK_CTX.Process
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ from authentik.policies.reputation.tasks import save_reputation
|
|||
from authentik.stages.identification.signals import identification_failed
|
||||
|
||||
LOGGER = get_logger()
|
||||
CACHE_TIMEOUT = CONFIG.get_int("redis.cache_timeout_reputation")
|
||||
CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_reputation")
|
||||
|
||||
|
||||
def update_score(request: HttpRequest, identifier: str, amount: int):
|
||||
|
|
|
@ -188,6 +188,7 @@ def authenticate_provider(request: HttpRequest) -> Optional[OAuth2Provider]:
|
|||
if client_id != provider.client_id or client_secret != provider.client_secret:
|
||||
LOGGER.debug("(basic) Provider for basic auth does not exist")
|
||||
return None
|
||||
CTX_AUTH_VIA.set("oauth_client_secret")
|
||||
return provider
|
||||
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ from jwt import PyJWK, PyJWT, PyJWTError, decode
|
|||
from sentry_sdk.hub import Hub
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.middleware import CTX_AUTH_VIA
|
||||
from authentik.core.models import (
|
||||
USER_ATTRIBUTE_EXPIRES,
|
||||
USER_ATTRIBUTE_GENERATED,
|
||||
|
@ -448,6 +449,7 @@ class TokenView(View):
|
|||
if not self.provider:
|
||||
LOGGER.warning("OAuth2Provider does not exist", client_id=client_id)
|
||||
raise TokenError("invalid_client")
|
||||
CTX_AUTH_VIA.set("oauth_client_secret")
|
||||
self.params = TokenParams.parse(request, self.provider, client_id, client_secret)
|
||||
|
||||
with Hub.current.start_span(
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
"""root settings for authentik"""
|
||||
|
||||
import importlib
|
||||
import os
|
||||
from hashlib import sha512
|
||||
|
@ -195,8 +194,8 @@ _redis_url = (
|
|||
CACHES = {
|
||||
"default": {
|
||||
"BACKEND": "django_redis.cache.RedisCache",
|
||||
"LOCATION": f"{_redis_url}/{CONFIG.get('redis.db')}",
|
||||
"TIMEOUT": CONFIG.get_int("redis.cache_timeout", 300),
|
||||
"LOCATION": CONFIG.get("cache.url") or f"{_redis_url}/{CONFIG.get('redis.db')}",
|
||||
"TIMEOUT": CONFIG.get_int("cache.timeout", 300),
|
||||
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
|
||||
"KEY_PREFIX": "authentik_cache",
|
||||
}
|
||||
|
@ -256,7 +255,7 @@ CHANNEL_LAYERS = {
|
|||
"default": {
|
||||
"BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer",
|
||||
"CONFIG": {
|
||||
"hosts": [f"{_redis_url}/{CONFIG.get('redis.db')}"],
|
||||
"hosts": [CONFIG.get("channel.url", f"{_redis_url}/{CONFIG.get('redis.db')}")],
|
||||
"prefix": "authentik_channels_",
|
||||
},
|
||||
},
|
||||
|
@ -349,8 +348,11 @@ CELERY = {
|
|||
},
|
||||
"task_create_missing_queues": True,
|
||||
"task_default_queue": "authentik",
|
||||
"broker_url": f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}",
|
||||
"result_backend": f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}",
|
||||
"broker_url": CONFIG.get("broker.url")
|
||||
or f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}",
|
||||
"broker_transport_options": CONFIG.get_dict_from_b64_json("broker.transport_options"),
|
||||
"result_backend": CONFIG.get("result_backend.url")
|
||||
or f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}",
|
||||
}
|
||||
|
||||
# Sentry integration
|
||||
|
|
40
authentik/sources/ldap/api/property_mappings.py
Normal file
40
authentik/sources/ldap/api/property_mappings.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
"""Source API Views"""
|
||||
from django_filters.filters import AllValuesMultipleFilter
|
||||
from django_filters.filterset import FilterSet
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik.core.api.propertymappings import PropertyMappingSerializer
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.sources.ldap.models import LDAPPropertyMapping
|
||||
|
||||
|
||||
class LDAPPropertyMappingSerializer(PropertyMappingSerializer):
|
||||
"""LDAP PropertyMapping Serializer"""
|
||||
|
||||
class Meta:
|
||||
model = LDAPPropertyMapping
|
||||
fields = PropertyMappingSerializer.Meta.fields + [
|
||||
"object_field",
|
||||
]
|
||||
|
||||
|
||||
class LDAPPropertyMappingFilter(FilterSet):
|
||||
"""Filter for LDAPPropertyMapping"""
|
||||
|
||||
managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed"))
|
||||
|
||||
class Meta:
|
||||
model = LDAPPropertyMapping
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class LDAPPropertyMappingViewSet(UsedByMixin, ModelViewSet):
|
||||
"""LDAP PropertyMapping Viewset"""
|
||||
|
||||
queryset = LDAPPropertyMapping.objects.all()
|
||||
serializer_class = LDAPPropertyMappingSerializer
|
||||
filterset_class = LDAPPropertyMappingFilter
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
|
@ -1,31 +1,30 @@
|
|||
"""Source API Views"""
|
||||
from typing import Any
|
||||
from typing import Any, Optional
|
||||
|
||||
from django_filters.filters import AllValuesMultipleFilter
|
||||
from django_filters.filterset import FilterSet
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_field, inline_serializer
|
||||
from django.core.cache import cache
|
||||
from drf_spectacular.utils import extend_schema, inline_serializer
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.fields import DictField, ListField
|
||||
from rest_framework.fields import BooleanField, DictField, ListField, SerializerMethodField
|
||||
from rest_framework.relations import PrimaryKeyRelatedField
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik.admin.api.tasks import TaskSerializer
|
||||
from authentik.core.api.propertymappings import PropertyMappingSerializer
|
||||
from authentik.core.api.sources import SourceSerializer
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
from authentik.crypto.models import CertificateKeyPair
|
||||
from authentik.events.monitored_tasks import TaskInfo
|
||||
from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
|
||||
from authentik.sources.ldap.tasks import SYNC_CLASSES
|
||||
from authentik.sources.ldap.models import LDAPSource
|
||||
from authentik.sources.ldap.tasks import CACHE_KEY_STATUS, SYNC_CLASSES, ldap_sync_single
|
||||
|
||||
|
||||
class LDAPSourceSerializer(SourceSerializer):
|
||||
"""LDAP Source Serializer"""
|
||||
|
||||
connectivity = SerializerMethodField()
|
||||
client_certificate = PrimaryKeyRelatedField(
|
||||
allow_null=True,
|
||||
help_text="Client certificate to authenticate against the LDAP Server's Certificate.",
|
||||
|
@ -35,6 +34,10 @@ class LDAPSourceSerializer(SourceSerializer):
|
|||
required=False,
|
||||
)
|
||||
|
||||
def get_connectivity(self, source: LDAPSource) -> Optional[dict[str, dict[str, str]]]:
|
||||
"""Get cached source connectivity"""
|
||||
return cache.get(CACHE_KEY_STATUS + source.slug, None)
|
||||
|
||||
def validate(self, attrs: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Check that only a single source has password_sync on"""
|
||||
sync_users_password = attrs.get("sync_users_password", True)
|
||||
|
@ -52,6 +55,20 @@ class LDAPSourceSerializer(SourceSerializer):
|
|||
)
|
||||
return super().validate(attrs)
|
||||
|
||||
def create(self, validated_data) -> LDAPSource:
|
||||
# Create both creates the actual model and assigns m2m fields
|
||||
instance: LDAPSource = super().create(validated_data)
|
||||
if not instance.enabled:
|
||||
return instance
|
||||
# Don't sync sources when they don't have any property mappings. This will only happen if:
|
||||
# - the user forgets to set them or
|
||||
# - the source is newly created, this is the first save event
|
||||
# and the mappings are created with an m2m event
|
||||
if not instance.property_mappings.exists() or not instance.property_mappings_group.exists():
|
||||
return instance
|
||||
ldap_sync_single.delay(instance.pk)
|
||||
return instance
|
||||
|
||||
class Meta:
|
||||
model = LDAPSource
|
||||
fields = SourceSerializer.Meta.fields + [
|
||||
|
@ -75,10 +92,18 @@ class LDAPSourceSerializer(SourceSerializer):
|
|||
"sync_parent_group",
|
||||
"property_mappings",
|
||||
"property_mappings_group",
|
||||
"connectivity",
|
||||
]
|
||||
extra_kwargs = {"bind_password": {"write_only": True}}
|
||||
|
||||
|
||||
class LDAPSyncStatusSerializer(PassiveSerializer):
|
||||
"""LDAP Source sync status"""
|
||||
|
||||
is_running = BooleanField(read_only=True)
|
||||
tasks = TaskSerializer(many=True, read_only=True)
|
||||
|
||||
|
||||
class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
|
||||
"""LDAP Source Viewset"""
|
||||
|
||||
|
@ -113,20 +138,24 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
|
|||
ordering = ["name"]
|
||||
|
||||
@extend_schema(
|
||||
request=None,
|
||||
responses={
|
||||
200: TaskSerializer(many=True),
|
||||
}
|
||||
200: LDAPSyncStatusSerializer(),
|
||||
},
|
||||
)
|
||||
@action(methods=["GET"], detail=True, pagination_class=None, filter_backends=[])
|
||||
def sync_status(self, request: Request, slug: str) -> Response:
|
||||
"""Get source's sync status"""
|
||||
@action(methods=["GET", "POST"], detail=True, pagination_class=None, filter_backends=[])
|
||||
def sync(self, request: Request, slug: str) -> Response:
|
||||
"""Get source's sync status or start source sync"""
|
||||
source = self.get_object()
|
||||
results = []
|
||||
tasks = TaskInfo.by_name(f"ldap_sync:{source.slug}:*")
|
||||
if tasks:
|
||||
for task in tasks:
|
||||
results.append(task)
|
||||
return Response(TaskSerializer(results, many=True).data)
|
||||
if request.method == "POST":
|
||||
# We're not waiting for the sync to finish here as it could take multiple hours
|
||||
ldap_sync_single.delay(source.pk)
|
||||
tasks = TaskInfo.by_name(f"ldap_sync:{source.slug}:*") or []
|
||||
status = {
|
||||
"tasks": tasks,
|
||||
"is_running": source.sync_lock.locked(),
|
||||
}
|
||||
return Response(LDAPSyncStatusSerializer(status).data)
|
||||
|
||||
@extend_schema(
|
||||
responses={
|
||||
|
@ -154,33 +183,3 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
|
|||
obj.pop("raw_dn", None)
|
||||
all_objects[class_name].append(obj)
|
||||
return Response(data=all_objects)
|
||||
|
||||
|
||||
class LDAPPropertyMappingSerializer(PropertyMappingSerializer):
|
||||
"""LDAP PropertyMapping Serializer"""
|
||||
|
||||
class Meta:
|
||||
model = LDAPPropertyMapping
|
||||
fields = PropertyMappingSerializer.Meta.fields + [
|
||||
"object_field",
|
||||
]
|
||||
|
||||
|
||||
class LDAPPropertyMappingFilter(FilterSet):
|
||||
"""Filter for LDAPPropertyMapping"""
|
||||
|
||||
managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed"))
|
||||
|
||||
class Meta:
|
||||
model = LDAPPropertyMapping
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class LDAPPropertyMappingViewSet(UsedByMixin, ModelViewSet):
|
||||
"""LDAP PropertyMapping Viewset"""
|
||||
|
||||
queryset = LDAPPropertyMapping.objects.all()
|
||||
serializer_class = LDAPPropertyMappingSerializer
|
||||
filterset_class = LDAPPropertyMappingFilter
|
||||
search_fields = ["name"]
|
||||
ordering = ["name"]
|
|
@ -0,0 +1,24 @@
|
|||
"""LDAP Connection check"""
|
||||
from json import dumps
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.sources.ldap.models import LDAPSource
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""Check connectivity to LDAP servers for a source"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("source_slugs", nargs="?", type=str)
|
||||
|
||||
def handle(self, **options):
|
||||
sources = LDAPSource.objects.filter(enabled=True)
|
||||
if options["source_slugs"]:
|
||||
sources = LDAPSource.objects.filter(slug__in=options["source_slugs"])
|
||||
for source in sources.order_by("slug"):
|
||||
status = source.check_connection()
|
||||
self.stdout.write(dumps(status, indent=4))
|
|
@ -4,10 +4,12 @@ from ssl import CERT_REQUIRED
|
|||
from tempfile import NamedTemporaryFile, mkdtemp
|
||||
from typing import Optional
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from ldap3 import ALL, NONE, RANDOM, Connection, Server, ServerPool, Tls
|
||||
from ldap3.core.exceptions import LDAPInsufficientAccessRightsResult, LDAPSchemaError
|
||||
from ldap3.core.exceptions import LDAPException, LDAPInsufficientAccessRightsResult, LDAPSchemaError
|
||||
from redis.lock import Lock
|
||||
from rest_framework.serializers import Serializer
|
||||
|
||||
from authentik.core.models import Group, PropertyMapping, Source
|
||||
|
@ -113,11 +115,11 @@ class LDAPSource(Source):
|
|||
|
||||
@property
|
||||
def serializer(self) -> type[Serializer]:
|
||||
from authentik.sources.ldap.api import LDAPSourceSerializer
|
||||
from authentik.sources.ldap.api.sources import LDAPSourceSerializer
|
||||
|
||||
return LDAPSourceSerializer
|
||||
|
||||
def server(self, **kwargs) -> Server:
|
||||
def server(self, **kwargs) -> ServerPool:
|
||||
"""Get LDAP Server/ServerPool"""
|
||||
servers = []
|
||||
tls_kwargs = {}
|
||||
|
@ -154,7 +156,10 @@ class LDAPSource(Source):
|
|||
return ServerPool(servers, RANDOM, active=5, exhaust=True)
|
||||
|
||||
def connection(
|
||||
self, server_kwargs: Optional[dict] = None, connection_kwargs: Optional[dict] = None
|
||||
self,
|
||||
server: Optional[Server] = None,
|
||||
server_kwargs: Optional[dict] = None,
|
||||
connection_kwargs: Optional[dict] = None,
|
||||
) -> Connection:
|
||||
"""Get a fully connected and bound LDAP Connection"""
|
||||
server_kwargs = server_kwargs or {}
|
||||
|
@ -164,7 +169,7 @@ class LDAPSource(Source):
|
|||
if self.bind_password is not None:
|
||||
connection_kwargs.setdefault("password", self.bind_password)
|
||||
connection = Connection(
|
||||
self.server(**server_kwargs),
|
||||
server or self.server(**server_kwargs),
|
||||
raise_exceptions=True,
|
||||
receive_timeout=LDAP_TIMEOUT,
|
||||
**connection_kwargs,
|
||||
|
@ -183,9 +188,55 @@ class LDAPSource(Source):
|
|||
if server_kwargs.get("get_info", ALL) == NONE:
|
||||
raise exc
|
||||
server_kwargs["get_info"] = NONE
|
||||
return self.connection(server_kwargs, connection_kwargs)
|
||||
return self.connection(server, server_kwargs, connection_kwargs)
|
||||
return RuntimeError("Failed to bind")
|
||||
|
||||
@property
|
||||
def sync_lock(self) -> Lock:
|
||||
"""Redis lock for syncing LDAP to prevent multiple parallel syncs happening"""
|
||||
return Lock(
|
||||
cache.client.get_client(),
|
||||
name=f"goauthentik.io/sources/ldap/sync-{self.slug}",
|
||||
# Convert task timeout hours to seconds, and multiply times 3
|
||||
# (see authentik/sources/ldap/tasks.py:54)
|
||||
# multiply by 3 to add even more leeway
|
||||
timeout=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 3,
|
||||
)
|
||||
|
||||
def check_connection(self) -> dict[str, dict[str, str]]:
|
||||
"""Check LDAP Connection"""
|
||||
from authentik.sources.ldap.sync.base import flatten
|
||||
|
||||
servers = self.server()
|
||||
server_info = {}
|
||||
# Check each individual server
|
||||
for server in servers.servers:
|
||||
server: Server
|
||||
try:
|
||||
connection = self.connection(server=server)
|
||||
server_info[server.host] = {
|
||||
"vendor": str(flatten(connection.server.info.vendor_name)),
|
||||
"version": str(flatten(connection.server.info.vendor_version)),
|
||||
"status": "ok",
|
||||
}
|
||||
except LDAPException as exc:
|
||||
server_info[server.host] = {
|
||||
"status": str(exc),
|
||||
}
|
||||
# Check server pool
|
||||
try:
|
||||
connection = self.connection()
|
||||
server_info["__all__"] = {
|
||||
"vendor": str(flatten(connection.server.info.vendor_name)),
|
||||
"version": str(flatten(connection.server.info.vendor_version)),
|
||||
"status": "ok",
|
||||
}
|
||||
except LDAPException as exc:
|
||||
server_info["__all__"] = {
|
||||
"status": str(exc),
|
||||
}
|
||||
return server_info
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("LDAP Source")
|
||||
verbose_name_plural = _("LDAP Sources")
|
||||
|
@ -202,7 +253,7 @@ class LDAPPropertyMapping(PropertyMapping):
|
|||
|
||||
@property
|
||||
def serializer(self) -> type[Serializer]:
|
||||
from authentik.sources.ldap.api import LDAPPropertyMappingSerializer
|
||||
from authentik.sources.ldap.api.property_mappings import LDAPPropertyMappingSerializer
|
||||
|
||||
return LDAPPropertyMappingSerializer
|
||||
|
||||
|
|
|
@ -8,5 +8,10 @@ CELERY_BEAT_SCHEDULE = {
|
|||
"task": "authentik.sources.ldap.tasks.ldap_sync_all",
|
||||
"schedule": crontab(minute=fqdn_rand("sources_ldap_sync"), hour="*/2"),
|
||||
"options": {"queue": "authentik_scheduled"},
|
||||
}
|
||||
},
|
||||
"sources_ldap_connectivity_check": {
|
||||
"task": "authentik.sources.ldap.tasks.ldap_connectivity_check",
|
||||
"schedule": crontab(minute=fqdn_rand("sources_ldap_connectivity_check"), hour="*"),
|
||||
"options": {"queue": "authentik_scheduled"},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -14,24 +14,18 @@ from authentik.events.models import Event, EventAction
|
|||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from authentik.sources.ldap.models import LDAPSource
|
||||
from authentik.sources.ldap.password import LDAPPasswordChanger
|
||||
from authentik.sources.ldap.tasks import ldap_sync_single
|
||||
from authentik.sources.ldap.tasks import ldap_connectivity_check
|
||||
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, **_):
|
||||
"""Ensure that source is synced on save (if enabled)"""
|
||||
def check_ldap_source_on_save(sender, instance: LDAPSource, **_):
|
||||
"""Check LDAP source's connectivity on save (if enabled)"""
|
||||
if not instance.enabled:
|
||||
return
|
||||
# Don't sync sources when they don't have any property mappings. This will only happen if:
|
||||
# - the user forgets to set them or
|
||||
# - the source is newly created, this is the first save event
|
||||
# and the mappings are created with an m2m event
|
||||
if not instance.property_mappings.exists() or not instance.property_mappings_group.exists():
|
||||
return
|
||||
ldap_sync_single.delay(instance.pk)
|
||||
ldap_connectivity_check.delay(instance.pk)
|
||||
|
||||
|
||||
@receiver(password_validate)
|
||||
|
|
|
@ -17,6 +17,15 @@ from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
|
|||
LDAP_UNIQUENESS = "ldap_uniq"
|
||||
|
||||
|
||||
def flatten(value: Any) -> Any:
|
||||
"""Flatten `value` if its a list"""
|
||||
if isinstance(value, list):
|
||||
if len(value) < 1:
|
||||
return None
|
||||
return value[0]
|
||||
return value
|
||||
|
||||
|
||||
class BaseLDAPSynchronizer:
|
||||
"""Sync LDAP Users and groups into authentik"""
|
||||
|
||||
|
@ -122,14 +131,6 @@ class BaseLDAPSynchronizer:
|
|||
cookie = None
|
||||
yield self._connection.response
|
||||
|
||||
def _flatten(self, value: Any) -> Any:
|
||||
"""Flatten `value` if its a list"""
|
||||
if isinstance(value, list):
|
||||
if len(value) < 1:
|
||||
return None
|
||||
return value[0]
|
||||
return value
|
||||
|
||||
def build_user_properties(self, user_dn: str, **kwargs) -> dict[str, Any]:
|
||||
"""Build attributes for User object based on property mappings."""
|
||||
props = self._build_object_properties(user_dn, self._source.property_mappings, **kwargs)
|
||||
|
@ -163,10 +164,10 @@ class BaseLDAPSynchronizer:
|
|||
object_field = mapping.object_field
|
||||
if object_field.startswith("attributes."):
|
||||
# Because returning a list might desired, we can't
|
||||
# rely on self._flatten here. Instead, just save the result as-is
|
||||
# rely on flatten here. Instead, just save the result as-is
|
||||
set_path_in_dict(properties, object_field, value)
|
||||
else:
|
||||
properties[object_field] = self._flatten(value)
|
||||
properties[object_field] = flatten(value)
|
||||
except PropertyMappingExpressionException as exc:
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
|
@ -177,7 +178,7 @@ class BaseLDAPSynchronizer:
|
|||
self._logger.warning("Mapping failed to evaluate", exc=exc, mapping=mapping)
|
||||
continue
|
||||
if self._source.object_uniqueness_field in kwargs:
|
||||
properties["attributes"][LDAP_UNIQUENESS] = self._flatten(
|
||||
properties["attributes"][LDAP_UNIQUENESS] = flatten(
|
||||
kwargs.get(self._source.object_uniqueness_field)
|
||||
)
|
||||
properties["attributes"][LDAP_DISTINGUISHED_NAME] = object_dn
|
||||
|
|
|
@ -7,7 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE
|
|||
|
||||
from authentik.core.models import Group
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer
|
||||
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer, flatten
|
||||
|
||||
|
||||
class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
|
||||
|
@ -39,7 +39,7 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
|
|||
if "attributes" not in group:
|
||||
continue
|
||||
attributes = group.get("attributes", {})
|
||||
group_dn = self._flatten(self._flatten(group.get("entryDN", group.get("dn"))))
|
||||
group_dn = flatten(flatten(group.get("entryDN", group.get("dn"))))
|
||||
if self._source.object_uniqueness_field not in attributes:
|
||||
self.message(
|
||||
f"Cannot find uniqueness field in attributes: '{group_dn}'",
|
||||
|
@ -47,7 +47,7 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
|
|||
dn=group_dn,
|
||||
)
|
||||
continue
|
||||
uniq = self._flatten(attributes[self._source.object_uniqueness_field])
|
||||
uniq = flatten(attributes[self._source.object_uniqueness_field])
|
||||
try:
|
||||
defaults = self.build_group_properties(group_dn, **attributes)
|
||||
defaults["parent"] = self._source.sync_parent_group
|
||||
|
|
|
@ -7,7 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE
|
|||
|
||||
from authentik.core.models import User
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer
|
||||
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer, flatten
|
||||
from authentik.sources.ldap.sync.vendor.freeipa import FreeIPA
|
||||
from authentik.sources.ldap.sync.vendor.ms_ad import MicrosoftActiveDirectory
|
||||
|
||||
|
@ -41,7 +41,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
|
|||
if "attributes" not in user:
|
||||
continue
|
||||
attributes = user.get("attributes", {})
|
||||
user_dn = self._flatten(user.get("entryDN", user.get("dn")))
|
||||
user_dn = flatten(user.get("entryDN", user.get("dn")))
|
||||
if self._source.object_uniqueness_field not in attributes:
|
||||
self.message(
|
||||
f"Cannot find uniqueness field in attributes: '{user_dn}'",
|
||||
|
@ -49,7 +49,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
|
|||
dn=user_dn,
|
||||
)
|
||||
continue
|
||||
uniq = self._flatten(attributes[self._source.object_uniqueness_field])
|
||||
uniq = flatten(attributes[self._source.object_uniqueness_field])
|
||||
try:
|
||||
defaults = self.build_user_properties(user_dn, **attributes)
|
||||
self._logger.debug("Writing user with attributes", **defaults)
|
||||
|
|
|
@ -5,7 +5,7 @@ from typing import Any, Generator
|
|||
from pytz import UTC
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer
|
||||
from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer, flatten
|
||||
|
||||
|
||||
class FreeIPA(BaseLDAPSynchronizer):
|
||||
|
@ -47,7 +47,7 @@ class FreeIPA(BaseLDAPSynchronizer):
|
|||
return
|
||||
# For some reason, nsaccountlock is not defined properly in the schema as bool
|
||||
# hence we get it as a list of strings
|
||||
_is_locked = str(self._flatten(attributes.get("nsaccountlock", ["FALSE"])))
|
||||
_is_locked = str(flatten(attributes.get("nsaccountlock", ["FALSE"])))
|
||||
# So we have to attempt to convert it to a bool
|
||||
is_locked = _is_locked.lower() == "true"
|
||||
# And then invert it since freeipa saves locked and we save active
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
"""LDAP Sync tasks"""
|
||||
from typing import Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from celery import chain, group
|
||||
from django.core.cache import cache
|
||||
from ldap3.core.exceptions import LDAPException
|
||||
from redis.exceptions import LockError
|
||||
from redis.lock import Lock
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.events.monitored_tasks import CACHE_KEY_PREFIX as CACHE_KEY_PREFIX_TASKS
|
||||
from authentik.events.monitored_tasks import MonitoredTask, TaskResult, TaskResultStatus
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.utils.errors import exception_to_string
|
||||
|
@ -26,6 +27,7 @@ SYNC_CLASSES = [
|
|||
MembershipLDAPSynchronizer,
|
||||
]
|
||||
CACHE_KEY_PREFIX = "goauthentik.io/sources/ldap/page/"
|
||||
CACHE_KEY_STATUS = "goauthentik.io/sources/ldap/status/"
|
||||
|
||||
|
||||
@CELERY_APP.task()
|
||||
|
@ -35,6 +37,19 @@ def ldap_sync_all():
|
|||
ldap_sync_single.apply_async(args=[source.pk])
|
||||
|
||||
|
||||
@CELERY_APP.task()
|
||||
def ldap_connectivity_check(pk: Optional[str] = None):
|
||||
"""Check connectivity for LDAP Sources"""
|
||||
# 2 hour timeout, this task should run every hour
|
||||
timeout = 60 * 60 * 2
|
||||
sources = LDAPSource.objects.filter(enabled=True)
|
||||
if pk:
|
||||
sources = sources.filter(pk=pk)
|
||||
for source in sources:
|
||||
status = source.check_connection()
|
||||
cache.set(CACHE_KEY_STATUS + source.slug, status, timeout=timeout)
|
||||
|
||||
|
||||
@CELERY_APP.task(
|
||||
# We take the configured hours timeout time by 2.5 as we run user and
|
||||
# group in parallel and then membership, so 2x is to cover the serial tasks,
|
||||
|
@ -47,12 +62,15 @@ def ldap_sync_single(source_pk: str):
|
|||
source: LDAPSource = LDAPSource.objects.filter(pk=source_pk).first()
|
||||
if not source:
|
||||
return
|
||||
lock = Lock(cache.client.get_client(), name=f"goauthentik.io/sources/ldap/sync-{source.slug}")
|
||||
lock = source.sync_lock
|
||||
if lock.locked():
|
||||
LOGGER.debug("LDAP sync locked, skipping task", source=source.slug)
|
||||
return
|
||||
try:
|
||||
with lock:
|
||||
# Delete all sync tasks from the cache
|
||||
keys = cache.keys(f"{CACHE_KEY_PREFIX_TASKS}ldap_sync:{source.slug}*")
|
||||
cache.delete_many(keys)
|
||||
task = chain(
|
||||
# User and group sync can happen at once, they have no dependencies on each other
|
||||
group(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""API URLs"""
|
||||
from authentik.sources.ldap.api import LDAPPropertyMappingViewSet, LDAPSourceViewSet
|
||||
from authentik.sources.ldap.api.property_mappings import LDAPPropertyMappingViewSet
|
||||
from authentik.sources.ldap.api.sources import LDAPSourceViewSet
|
||||
|
||||
api_urlpatterns = [
|
||||
("propertymappings/ldap", LDAPPropertyMappingViewSet),
|
||||
|
|
|
@ -12,8 +12,9 @@ class PatreonOAuthRedirect(OAuthRedirect):
|
|||
"""Patreon OAuth2 Redirect"""
|
||||
|
||||
def get_additional_parameters(self, source: OAuthSource): # pragma: no cover
|
||||
# https://docs.patreon.com/#scopes
|
||||
return {
|
||||
"scope": ["openid", "email", "profile"],
|
||||
"scope": ["identity", "identity[email]"],
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,17 +52,13 @@ class EmailStageView(ChallengeStageView):
|
|||
kwargs={"flow_slug": self.executor.flow.slug},
|
||||
)
|
||||
# Parse query string from current URL (full query string)
|
||||
query_params = QueryDict(self.request.META.get("QUERY_STRING", ""), mutable=True)
|
||||
# this view is only run within a flow executor, where we need to get the query string
|
||||
# from the query= parameter (double encoded); but for the redirect
|
||||
# we need to expand it since it'll go through the flow interface
|
||||
query_params = QueryDict(self.request.GET.get(QS_QUERY), mutable=True)
|
||||
query_params.pop(QS_KEY_TOKEN, None)
|
||||
|
||||
# Check for nested query string used by flow executor, and remove any
|
||||
# kind of flow token from that
|
||||
if QS_QUERY in query_params:
|
||||
inner_query_params = QueryDict(query_params.get(QS_QUERY), mutable=True)
|
||||
inner_query_params.pop(QS_KEY_TOKEN, None)
|
||||
query_params[QS_QUERY] = inner_query_params.urlencode()
|
||||
|
||||
query_params.update(kwargs)
|
||||
print(query_params)
|
||||
full_url = base_url
|
||||
if len(query_params) > 0:
|
||||
full_url = f"{full_url}?{query_params.urlencode()}"
|
||||
|
|
|
@ -259,7 +259,7 @@ class TestEmailStage(FlowTestCase):
|
|||
session.save()
|
||||
|
||||
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
|
||||
url += "?foo=bar"
|
||||
url += "?query=" + urlencode({"foo": "bar"})
|
||||
request = self.factory.get(url)
|
||||
stage_view = EmailStageView(
|
||||
FlowExecutorView(
|
||||
|
@ -273,31 +273,3 @@ class TestEmailStage(FlowTestCase):
|
|||
stage_view.get_full_url(**{QS_KEY_TOKEN: token}),
|
||||
f"http://testserver/if/flow/{self.flow.slug}/?foo=bar&flow_token={token}",
|
||||
)
|
||||
|
||||
def test_url_existing_params_nested(self):
|
||||
"""Test to ensure that URL params are preserved in the URL being sent (including nested)"""
|
||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
|
||||
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
|
||||
url += "?foo=bar&"
|
||||
url += "query=" + urlencode({"nested": "value"})
|
||||
request = self.factory.get(url)
|
||||
stage_view = EmailStageView(
|
||||
FlowExecutorView(
|
||||
request=request,
|
||||
flow=self.flow,
|
||||
),
|
||||
request=request,
|
||||
)
|
||||
token = generate_id()
|
||||
self.assertEqual(
|
||||
stage_view.get_full_url(**{QS_KEY_TOKEN: token}),
|
||||
(
|
||||
f"http://testserver/if/flow/{self.flow.slug}"
|
||||
f"/?foo=bar&query=nested%3Dvalue&flow_token={token}"
|
||||
),
|
||||
)
|
||||
|
|
|
@ -32,7 +32,7 @@ services:
|
|||
volumes:
|
||||
- redis:/data
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.2}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.3}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
|
@ -53,7 +53,7 @@ services:
|
|||
- postgresql
|
||||
- redis
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.2}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.3}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
|
|
30
go.mod
30
go.mod
|
@ -13,24 +13,24 @@ require (
|
|||
github.com/go-openapi/strfmt v0.21.7
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/google/uuid v1.4.0
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/securecookie v1.1.1
|
||||
github.com/gorilla/sessions v1.2.1
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/gorilla/handlers v1.5.2
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/gorilla/securecookie v1.1.2
|
||||
github.com/gorilla/sessions v1.2.2
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/jellydator/ttlcache/v3 v3.1.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
|
||||
github.com/pires/go-proxyproto v0.7.0
|
||||
github.com/prometheus/client_golang v1.17.0
|
||||
github.com/redis/go-redis/v9 v9.2.1
|
||||
github.com/redis/go-redis/v9 v9.3.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
goauthentik.io/api/v3 v3.2023101.1
|
||||
goauthentik.io/api/v3 v3.2023103.1
|
||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
|
||||
golang.org/x/oauth2 v0.13.0
|
||||
golang.org/x/sync v0.4.0
|
||||
golang.org/x/oauth2 v0.14.0
|
||||
golang.org/x/sync v0.5.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
layeh.com/radius v0.0.0-20210819152912-ad72663a72ab
|
||||
)
|
||||
|
@ -42,7 +42,7 @@ require (
|
|||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect
|
||||
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect
|
||||
|
@ -72,10 +72,10 @@ require (
|
|||
go.mongodb.org/mongo-driver v1.11.3 // indirect
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/crypto v0.15.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||
|
|
63
go.sum
63
go.sum
|
@ -62,7 +62,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -73,8 +73,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
|||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI=
|
||||
github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
||||
|
@ -200,6 +200,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
|
@ -216,16 +218,16 @@ github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
|||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
||||
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
|
@ -295,8 +297,8 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO
|
|||
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
|
||||
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
|
||||
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
|
||||
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg=
|
||||
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0=
|
||||
github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
|
@ -309,8 +311,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
|||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/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=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
|
@ -356,8 +358,8 @@ go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyK
|
|||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
goauthentik.io/api/v3 v3.2023101.1 h1:KIQ4wmxjE+geAVB0wBfmxW9Uzo/tA0dbd2hSUJ7YJ3M=
|
||||
goauthentik.io/api/v3 v3.2023101.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
||||
goauthentik.io/api/v3 v3.2023103.1 h1:KqZny4BPDEQ6cIDuZ9pn6/kpvyu+o6o/EekAfujffow=
|
||||
goauthentik.io/api/v3 v3.2023103.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
||||
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=
|
||||
|
@ -370,8 +372,8 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh
|
|||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -438,16 +440,16 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
|
||||
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
|
||||
golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0=
|
||||
golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -460,8 +462,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -502,8 +504,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
|
@ -519,8 +521,9 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
|
|
@ -27,14 +27,11 @@ type Config struct {
|
|||
type RedisConfig struct {
|
||||
Host string `yaml:"host" env:"AUTHENTIK_REDIS__HOST"`
|
||||
Port int `yaml:"port" env:"AUTHENTIK_REDIS__PORT"`
|
||||
DB int `yaml:"db" env:"AUTHENTIK_REDIS__DB"`
|
||||
Username string `yaml:"username" env:"AUTHENTIK_REDIS__USERNAME"`
|
||||
Password string `yaml:"password" env:"AUTHENTIK_REDIS__PASSWORD"`
|
||||
TLS bool `yaml:"tls" env:"AUTHENTIK_REDIS__TLS"`
|
||||
TLSReqs string `yaml:"tls_reqs" env:"AUTHENTIK_REDIS__TLS_REQS"`
|
||||
DB int `yaml:"cache_db" env:"AUTHENTIK_REDIS__DB"`
|
||||
CacheTimeout int `yaml:"cache_timeout" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT"`
|
||||
CacheTimeoutFlows int `yaml:"cache_timeout_flows" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT_FLOWS"`
|
||||
CacheTimeoutPolicies int `yaml:"cache_timeout_policies" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT_POLICIES"`
|
||||
CacheTimeoutReputation int `yaml:"cache_timeout_reputation" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION"`
|
||||
}
|
||||
|
||||
type ListenConfig struct {
|
||||
|
|
|
@ -29,4 +29,4 @@ func UserAgent() string {
|
|||
return fmt.Sprintf("authentik@%s", FullVersion())
|
||||
}
|
||||
|
||||
const VERSION = "2023.10.2"
|
||||
const VERSION = "2023.10.3"
|
||||
|
|
|
@ -29,16 +29,6 @@ var (
|
|||
Name: "authentik_outpost_flow_timing_post_seconds",
|
||||
Help: "Duration it took to send a challenge in seconds",
|
||||
}, []string{"stage", "flow"})
|
||||
|
||||
// NOTE: the following metrics are kept for compatibility purpose
|
||||
FlowTimingGetLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "authentik_outpost_flow_timing_get",
|
||||
Help: "Duration it took to get a challenge",
|
||||
}, []string{"stage", "flow"})
|
||||
FlowTimingPostLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "authentik_outpost_flow_timing_post",
|
||||
Help: "Duration it took to send a challenge",
|
||||
}, []string{"stage", "flow"})
|
||||
)
|
||||
|
||||
type SolverFunction func(*api.ChallengeTypes, api.ApiFlowsExecutorSolveRequest) (api.FlowChallengeResponseRequest, error)
|
||||
|
@ -198,10 +188,6 @@ func (fe *FlowExecutor) getInitialChallenge() (*api.ChallengeTypes, error) {
|
|||
"stage": ch.GetComponent(),
|
||||
"flow": fe.flowSlug,
|
||||
}).Observe(float64(gcsp.EndTime.Sub(gcsp.StartTime)) / float64(time.Second))
|
||||
FlowTimingGetLegacy.With(prometheus.Labels{
|
||||
"stage": ch.GetComponent(),
|
||||
"flow": fe.flowSlug,
|
||||
}).Observe(float64(gcsp.EndTime.Sub(gcsp.StartTime)))
|
||||
return challenge, nil
|
||||
}
|
||||
|
||||
|
@ -259,10 +245,6 @@ func (fe *FlowExecutor) solveFlowChallenge(challenge *api.ChallengeTypes, depth
|
|||
"stage": ch.GetComponent(),
|
||||
"flow": fe.flowSlug,
|
||||
}).Observe(float64(scsp.EndTime.Sub(scsp.StartTime)) / float64(time.Second))
|
||||
FlowTimingPostLegacy.With(prometheus.Labels{
|
||||
"stage": ch.GetComponent(),
|
||||
"flow": fe.flowSlug,
|
||||
}).Observe(float64(scsp.EndTime.Sub(scsp.StartTime)))
|
||||
|
||||
if depth >= 10 {
|
||||
return false, errors.New("exceeded stage recursion depth")
|
||||
|
|
|
@ -22,11 +22,6 @@ func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LD
|
|||
"type": "bind",
|
||||
"app": selectedApp,
|
||||
}).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second))
|
||||
metrics.RequestsLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ls.ac.Outpost.Name,
|
||||
"type": "bind",
|
||||
"app": selectedApp,
|
||||
}).Observe(float64(span.EndTime.Sub(span.StartTime)))
|
||||
req.Log().WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Bind request")
|
||||
}()
|
||||
|
||||
|
@ -55,12 +50,6 @@ func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LD
|
|||
"reason": "no_provider",
|
||||
"app": "",
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ls.ac.Outpost.Name,
|
||||
"type": "bind",
|
||||
"reason": "no_provider",
|
||||
"app": "",
|
||||
}).Inc()
|
||||
|
||||
return ldap.LDAPResultInsufficientAccessRights, nil
|
||||
}
|
||||
|
|
|
@ -47,12 +47,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
|
|||
"reason": "flow_error",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": db.si.GetOutpostName(),
|
||||
"type": "bind",
|
||||
"reason": "flow_error",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
req.Log().WithError(err).Warning("failed to execute flow")
|
||||
return ldap.LDAPResultInvalidCredentials, nil
|
||||
}
|
||||
|
@ -63,12 +57,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
|
|||
"reason": "invalid_credentials",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": db.si.GetOutpostName(),
|
||||
"type": "bind",
|
||||
"reason": "invalid_credentials",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
req.Log().Info("Invalid credentials")
|
||||
return ldap.LDAPResultInvalidCredentials, nil
|
||||
}
|
||||
|
@ -82,12 +70,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
|
|||
"reason": "access_denied",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": db.si.GetOutpostName(),
|
||||
"type": "bind",
|
||||
"reason": "access_denied",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
return ldap.LDAPResultInsufficientAccessRights, nil
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -97,12 +79,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
|
|||
"reason": "access_check_fail",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": db.si.GetOutpostName(),
|
||||
"type": "bind",
|
||||
"reason": "access_check_fail",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
req.Log().WithError(err).Warning("failed to check access")
|
||||
return ldap.LDAPResultOperationsError, nil
|
||||
}
|
||||
|
@ -117,12 +93,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
|
|||
"reason": "user_info_fail",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": db.si.GetOutpostName(),
|
||||
"type": "bind",
|
||||
"reason": "user_info_fail",
|
||||
"app": db.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
req.Log().WithError(err).Warning("failed to get user info")
|
||||
return ldap.LDAPResultOperationsError, nil
|
||||
}
|
||||
|
|
|
@ -22,16 +22,6 @@ var (
|
|||
Name: "authentik_outpost_ldap_requests_rejected_total",
|
||||
Help: "Total number of rejected requests",
|
||||
}, []string{"outpost_name", "type", "reason", "app"})
|
||||
|
||||
// NOTE: the following metrics are kept for compatibility purpose
|
||||
RequestsLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "authentik_outpost_ldap_requests",
|
||||
Help: "The total number of configured providers",
|
||||
}, []string{"outpost_name", "type", "app"})
|
||||
RequestsRejectedLegacy = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "authentik_outpost_ldap_requests_rejected",
|
||||
Help: "Total number of rejected requests",
|
||||
}, []string{"outpost_name", "type", "reason", "app"})
|
||||
)
|
||||
|
||||
func RunServer() {
|
||||
|
|
|
@ -23,11 +23,6 @@ func (ls *LDAPServer) Search(bindDN string, searchReq ldap.SearchRequest, conn n
|
|||
"type": "search",
|
||||
"app": selectedApp,
|
||||
}).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second))
|
||||
metrics.RequestsLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ls.ac.Outpost.Name,
|
||||
"type": "search",
|
||||
"app": selectedApp,
|
||||
}).Observe(float64(span.EndTime.Sub(span.StartTime)))
|
||||
req.Log().WithField("attributes", searchReq.Attributes).WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Search request")
|
||||
}()
|
||||
|
||||
|
|
|
@ -45,12 +45,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult,
|
|||
"reason": "empty_bind_dn",
|
||||
"app": ds.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ds.si.GetOutpostName(),
|
||||
"type": "search",
|
||||
"reason": "empty_bind_dn",
|
||||
"app": ds.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN)
|
||||
}
|
||||
if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) {
|
||||
|
@ -60,12 +54,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult,
|
|||
"reason": "invalid_bind_dn",
|
||||
"app": ds.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ds.si.GetOutpostName(),
|
||||
"type": "search",
|
||||
"reason": "invalid_bind_dn",
|
||||
"app": ds.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: BindDN %s not in our BaseDN %s", req.BindDN, ds.si.GetBaseDN())
|
||||
}
|
||||
|
||||
|
@ -78,12 +66,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult,
|
|||
"reason": "user_info_not_cached",
|
||||
"app": ds.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ds.si.GetOutpostName(),
|
||||
"type": "search",
|
||||
"reason": "user_info_not_cached",
|
||||
"app": ds.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied")
|
||||
}
|
||||
accsp.Finish()
|
||||
|
@ -96,12 +78,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult,
|
|||
"reason": "filter_parse_fail",
|
||||
"app": ds.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ds.si.GetOutpostName(),
|
||||
"type": "search",
|
||||
"reason": "filter_parse_fail",
|
||||
"app": ds.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("Search Error: error parsing filter: %s", req.Filter)
|
||||
}
|
||||
|
||||
|
|
|
@ -62,12 +62,6 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult,
|
|||
"reason": "empty_bind_dn",
|
||||
"app": ms.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ms.si.GetOutpostName(),
|
||||
"type": "search",
|
||||
"reason": "empty_bind_dn",
|
||||
"app": ms.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN)
|
||||
}
|
||||
if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) {
|
||||
|
@ -77,12 +71,6 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult,
|
|||
"reason": "invalid_bind_dn",
|
||||
"app": ms.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ms.si.GetOutpostName(),
|
||||
"type": "search",
|
||||
"reason": "invalid_bind_dn",
|
||||
"app": ms.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: BindDN %s not in our BaseDN %s", req.BindDN, ms.si.GetBaseDN())
|
||||
}
|
||||
|
||||
|
@ -95,12 +83,6 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult,
|
|||
"reason": "user_info_not_cached",
|
||||
"app": ms.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ms.si.GetOutpostName(),
|
||||
"type": "search",
|
||||
"reason": "user_info_not_cached",
|
||||
"app": ms.si.GetAppSlug(),
|
||||
}).Inc()
|
||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied")
|
||||
}
|
||||
accsp.Finish()
|
||||
|
|
|
@ -22,11 +22,6 @@ func (ls *LDAPServer) Unbind(boundDN string, conn net.Conn) (ldap.LDAPResultCode
|
|||
"type": "unbind",
|
||||
"app": selectedApp,
|
||||
}).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second))
|
||||
metrics.RequestsLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ls.ac.Outpost.Name,
|
||||
"type": "unbind",
|
||||
"app": selectedApp,
|
||||
}).Observe(float64(span.EndTime.Sub(span.StartTime)))
|
||||
req.Log().WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Unbind request")
|
||||
}()
|
||||
|
||||
|
@ -55,11 +50,5 @@ func (ls *LDAPServer) Unbind(boundDN string, conn net.Conn) (ldap.LDAPResultCode
|
|||
"reason": "no_provider",
|
||||
"app": "",
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ls.ac.Outpost.Name,
|
||||
"type": "unbind",
|
||||
"reason": "no_provider",
|
||||
"app": "",
|
||||
}).Inc()
|
||||
return ldap.LDAPResultOperationsError, nil
|
||||
}
|
||||
|
|
|
@ -173,12 +173,6 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A
|
|||
"method": r.Method,
|
||||
"host": web.GetHost(r),
|
||||
}).Observe(float64(elapsed) / float64(time.Second))
|
||||
metrics.RequestsLegacy.With(prometheus.Labels{
|
||||
"outpost_name": a.outpostName,
|
||||
"type": "app",
|
||||
"method": r.Method,
|
||||
"host": web.GetHost(r),
|
||||
}).Observe(float64(elapsed))
|
||||
})
|
||||
})
|
||||
if server.API().GlobalConfig.ErrorReporting.Enabled {
|
||||
|
|
|
@ -64,13 +64,6 @@ func (a *Application) configureProxy() error {
|
|||
"scheme": r.URL.Scheme,
|
||||
"host": web.GetHost(r),
|
||||
}).Observe(float64(elapsed) / float64(time.Second))
|
||||
metrics.UpstreamTimingLegacy.With(prometheus.Labels{
|
||||
"outpost_name": a.outpostName,
|
||||
"upstream_host": r.URL.Host,
|
||||
"method": r.Method,
|
||||
"scheme": r.URL.Scheme,
|
||||
"host": web.GetHost(r),
|
||||
}).Observe(float64(elapsed))
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -131,7 +131,6 @@ func (a *Application) Logout(ctx context.Context, filter func(c Claims) bool) er
|
|||
}
|
||||
if rs, ok := a.sessions.(*redisstore.RedisStore); ok {
|
||||
client := rs.Client()
|
||||
defer client.Close()
|
||||
keys, err := client.Keys(ctx, fmt.Sprintf("%s*", RedisKeyPrefix)).Result()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -26,12 +26,6 @@ func (ps *ProxyServer) HandlePing(rw http.ResponseWriter, r *http.Request) {
|
|||
"host": web.GetHost(r),
|
||||
"type": "ping",
|
||||
}).Observe(float64(elapsed) / float64(time.Second))
|
||||
metrics.RequestsLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ps.akAPI.Outpost.Name,
|
||||
"method": r.Method,
|
||||
"host": web.GetHost(r),
|
||||
"type": "ping",
|
||||
}).Observe(float64(elapsed))
|
||||
}
|
||||
|
||||
func (ps *ProxyServer) HandleStatic(rw http.ResponseWriter, r *http.Request) {
|
||||
|
@ -44,12 +38,6 @@ func (ps *ProxyServer) HandleStatic(rw http.ResponseWriter, r *http.Request) {
|
|||
"host": web.GetHost(r),
|
||||
"type": "static",
|
||||
}).Observe(float64(elapsed) / float64(time.Second))
|
||||
metrics.RequestsLegacy.With(prometheus.Labels{
|
||||
"outpost_name": ps.akAPI.Outpost.Name,
|
||||
"method": r.Method,
|
||||
"host": web.GetHost(r),
|
||||
"type": "static",
|
||||
}).Observe(float64(elapsed))
|
||||
}
|
||||
|
||||
func (ps *ProxyServer) lookupApp(r *http.Request) (*application.Application, string) {
|
||||
|
|
|
@ -22,16 +22,6 @@ var (
|
|||
Name: "authentik_outpost_proxy_upstream_response_duration_seconds",
|
||||
Help: "Proxy upstream response latencies in seconds",
|
||||
}, []string{"outpost_name", "method", "scheme", "host", "upstream_host"})
|
||||
|
||||
// NOTE: the following metric is kept for compatibility purpose
|
||||
RequestsLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "authentik_outpost_proxy_requests",
|
||||
Help: "The total number of configured providers",
|
||||
}, []string{"outpost_name", "method", "host", "type"})
|
||||
UpstreamTimingLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "authentik_outpost_proxy_upstream_time",
|
||||
Help: "A summary of the duration we wait for the upstream reply",
|
||||
}, []string{"outpost_name", "method", "scheme", "host", "upstream_host"})
|
||||
)
|
||||
|
||||
func RunServer() {
|
||||
|
|
|
@ -35,11 +35,6 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR
|
|||
"reason": "flow_error",
|
||||
"app": r.pi.appSlug,
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": rs.ac.Outpost.Name,
|
||||
"reason": "flow_error",
|
||||
"app": r.pi.appSlug,
|
||||
}).Inc()
|
||||
_ = w.Write(r.Response(radius.CodeAccessReject))
|
||||
return
|
||||
}
|
||||
|
@ -49,11 +44,6 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR
|
|||
"reason": "invalid_credentials",
|
||||
"app": r.pi.appSlug,
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": rs.ac.Outpost.Name,
|
||||
"reason": "invalid_credentials",
|
||||
"app": r.pi.appSlug,
|
||||
}).Inc()
|
||||
_ = w.Write(r.Response(radius.CodeAccessReject))
|
||||
return
|
||||
}
|
||||
|
@ -66,11 +56,6 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR
|
|||
"reason": "access_check_fail",
|
||||
"app": r.pi.appSlug,
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": rs.ac.Outpost.Name,
|
||||
"reason": "access_check_fail",
|
||||
"app": r.pi.appSlug,
|
||||
}).Inc()
|
||||
return
|
||||
}
|
||||
if !access {
|
||||
|
@ -81,11 +66,6 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR
|
|||
"reason": "access_denied",
|
||||
"app": r.pi.appSlug,
|
||||
}).Inc()
|
||||
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
|
||||
"outpost_name": rs.ac.Outpost.Name,
|
||||
"reason": "access_denied",
|
||||
"app": r.pi.appSlug,
|
||||
}).Inc()
|
||||
return
|
||||
}
|
||||
_ = w.Write(r.Response(radius.CodeAccessAccept))
|
||||
|
|
|
@ -47,10 +47,6 @@ func (rs *RadiusServer) ServeRADIUS(w radius.ResponseWriter, r *radius.Request)
|
|||
"outpost_name": rs.ac.Outpost.Name,
|
||||
"app": selectedApp,
|
||||
}).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second))
|
||||
metrics.RequestsLegacy.With(prometheus.Labels{
|
||||
"outpost_name": rs.ac.Outpost.Name,
|
||||
"app": selectedApp,
|
||||
}).Observe(float64(span.EndTime.Sub(span.StartTime)))
|
||||
}()
|
||||
|
||||
nr := &RadiusRequest{
|
||||
|
|
|
@ -22,16 +22,6 @@ var (
|
|||
Name: "authentik_outpost_radius_requests_rejected_total",
|
||||
Help: "Total number of rejected requests",
|
||||
}, []string{"outpost_name", "reason", "app"})
|
||||
|
||||
// NOTE: the following metric is kept for compatibility purpose
|
||||
RequestsLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "authentik_outpost_radius_requests",
|
||||
Help: "The total number of successful requests",
|
||||
}, []string{"outpost_name", "app"})
|
||||
RequestsRejectedLegacy = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "authentik_outpost_radius_requests_rejected",
|
||||
Help: "Total number of rejected requests",
|
||||
}, []string{"outpost_name", "reason", "app"})
|
||||
)
|
||||
|
||||
func RunServer() {
|
||||
|
|
|
@ -19,12 +19,6 @@ var (
|
|||
Name: "authentik_main_request_duration_seconds",
|
||||
Help: "API request latencies in seconds",
|
||||
}, []string{"dest"})
|
||||
|
||||
// NOTE: the following metric is kept for compatibility purpose
|
||||
RequestsLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "authentik_main_requests",
|
||||
Help: "The total number of configured providers",
|
||||
}, []string{"dest"})
|
||||
)
|
||||
|
||||
func (ws *WebServer) runMetricsServer() {
|
||||
|
|
|
@ -40,9 +40,6 @@ func (ws *WebServer) configureProxy() {
|
|||
Requests.With(prometheus.Labels{
|
||||
"dest": "embedded_outpost",
|
||||
}).Observe(float64(elapsed) / float64(time.Second))
|
||||
RequestsLegacy.With(prometheus.Labels{
|
||||
"dest": "embedded_outpost",
|
||||
}).Observe(float64(elapsed))
|
||||
return
|
||||
}
|
||||
ws.proxyErrorHandler(rw, r, errors.New("proxy not running"))
|
||||
|
@ -62,9 +59,6 @@ func (ws *WebServer) configureProxy() {
|
|||
Requests.With(prometheus.Labels{
|
||||
"dest": "embedded_outpost",
|
||||
}).Observe(float64(elapsed) / float64(time.Second))
|
||||
RequestsLegacy.With(prometheus.Labels{
|
||||
"dest": "embedded_outpost",
|
||||
}).Observe(float64(elapsed))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -72,9 +66,6 @@ func (ws *WebServer) configureProxy() {
|
|||
Requests.With(prometheus.Labels{
|
||||
"dest": "core",
|
||||
}).Observe(float64(elapsed) / float64(time.Second))
|
||||
RequestsLegacy.With(prometheus.Labels{
|
||||
"dest": "core",
|
||||
}).Observe(float64(elapsed))
|
||||
r.Body = http.MaxBytesReader(rw, r.Body, 32*1024*1024)
|
||||
rp.ServeHTTP(rw, r)
|
||||
}))
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# Stage 1: Build
|
||||
FROM docker.io/golang:1.21.3-bookworm AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
|
||||
ARG GOOS=$TARGETOS
|
||||
ARG GOARCH=$TARGETARCH
|
||||
|
||||
WORKDIR /go/src/goauthentik.io
|
||||
|
||||
|
@ -13,7 +20,7 @@ ENV CGO_ENABLED=0
|
|||
COPY . .
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
go build -o /go/ldap ./cmd/ldap
|
||||
GOARM="${TARGETVARIANT#v}" go build -o /go/ldap ./cmd/ldap
|
||||
|
||||
# Stage 2: Run
|
||||
FROM gcr.io/distroless/static-debian11:debug
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
187
poetry.lock
generated
187
poetry.lock
generated
|
@ -422,40 +422,40 @@ typecheck = ["mypy"]
|
|||
|
||||
[[package]]
|
||||
name = "billiard"
|
||||
version = "4.1.0"
|
||||
version = "4.2.0"
|
||||
description = "Python multiprocessing fork with improvements and bugfixes"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "billiard-4.1.0-py3-none-any.whl", hash = "sha256:0f50d6be051c6b2b75bfbc8bfd85af195c5739c281d3f5b86a5640c65563614a"},
|
||||
{file = "billiard-4.1.0.tar.gz", hash = "sha256:1ad2eeae8e28053d729ba3373d34d9d6e210f6e4d8bf0a9c64f92bd053f1edf5"},
|
||||
{file = "billiard-4.2.0-py3-none-any.whl", hash = "sha256:07aa978b308f334ff8282bd4a746e681b3513db5c9a514cbdd810cbbdc19714d"},
|
||||
{file = "billiard-4.2.0.tar.gz", hash = "sha256:9a3c3184cb275aa17a732f93f65b20c525d3d9f253722d26a82194803ade5a2c"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "23.10.1"
|
||||
version = "23.11.0"
|
||||
description = "The uncompromising code formatter."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "black-23.10.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:ec3f8e6234c4e46ff9e16d9ae96f4ef69fa328bb4ad08198c8cee45bb1f08c69"},
|
||||
{file = "black-23.10.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:1b917a2aa020ca600483a7b340c165970b26e9029067f019e3755b56e8dd5916"},
|
||||
{file = "black-23.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c74de4c77b849e6359c6f01987e94873c707098322b91490d24296f66d067dc"},
|
||||
{file = "black-23.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b4d10b0f016616a0d93d24a448100adf1699712fb7a4efd0e2c32bbb219b173"},
|
||||
{file = "black-23.10.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b15b75fc53a2fbcac8a87d3e20f69874d161beef13954747e053bca7a1ce53a0"},
|
||||
{file = "black-23.10.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:e293e4c2f4a992b980032bbd62df07c1bcff82d6964d6c9496f2cd726e246ace"},
|
||||
{file = "black-23.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d56124b7a61d092cb52cce34182a5280e160e6aff3137172a68c2c2c4b76bcb"},
|
||||
{file = "black-23.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f157a8945a7b2d424da3335f7ace89c14a3b0625e6593d21139c2d8214d55ce"},
|
||||
{file = "black-23.10.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:cfcce6f0a384d0da692119f2d72d79ed07c7159879d0bb1bb32d2e443382bf3a"},
|
||||
{file = "black-23.10.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:33d40f5b06be80c1bbce17b173cda17994fbad096ce60eb22054da021bf933d1"},
|
||||
{file = "black-23.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:840015166dbdfbc47992871325799fd2dc0dcf9395e401ada6d88fe11498abad"},
|
||||
{file = "black-23.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:037e9b4664cafda5f025a1728c50a9e9aedb99a759c89f760bd83730e76ba884"},
|
||||
{file = "black-23.10.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:7cb5936e686e782fddb1c73f8aa6f459e1ad38a6a7b0e54b403f1f05a1507ee9"},
|
||||
{file = "black-23.10.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:7670242e90dc129c539e9ca17665e39a146a761e681805c54fbd86015c7c84f7"},
|
||||
{file = "black-23.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed45ac9a613fb52dad3b61c8dea2ec9510bf3108d4db88422bacc7d1ba1243d"},
|
||||
{file = "black-23.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:6d23d7822140e3fef190734216cefb262521789367fbdc0b3f22af6744058982"},
|
||||
{file = "black-23.10.1-py3-none-any.whl", hash = "sha256:d431e6739f727bb2e0495df64a6c7a5310758e87505f5f8cde9ff6c0f2d7e4fe"},
|
||||
{file = "black-23.10.1.tar.gz", hash = "sha256:1f8ce316753428ff68749c65a5f7844631aa18c8679dfd3ca9dc1a289979c258"},
|
||||
{file = "black-23.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911"},
|
||||
{file = "black-23.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f"},
|
||||
{file = "black-23.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394"},
|
||||
{file = "black-23.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f"},
|
||||
{file = "black-23.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479"},
|
||||
{file = "black-23.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244"},
|
||||
{file = "black-23.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221"},
|
||||
{file = "black-23.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5"},
|
||||
{file = "black-23.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:45aa1d4675964946e53ab81aeec7a37613c1cb71647b5394779e6efb79d6d187"},
|
||||
{file = "black-23.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c44b7211a3a0570cc097e81135faa5f261264f4dfaa22bd5ee2875a4e773bd6"},
|
||||
{file = "black-23.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a9acad1451632021ee0d146c8765782a0c3846e0e0ea46659d7c4f89d9b212b"},
|
||||
{file = "black-23.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142"},
|
||||
{file = "black-23.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055"},
|
||||
{file = "black-23.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4"},
|
||||
{file = "black-23.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06"},
|
||||
{file = "black-23.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07"},
|
||||
{file = "black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e"},
|
||||
{file = "black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -544,29 +544,29 @@ test = ["pytest", "pytest-cov"]
|
|||
|
||||
[[package]]
|
||||
name = "celery"
|
||||
version = "5.3.4"
|
||||
version = "5.3.5"
|
||||
description = "Distributed Task Queue."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "celery-5.3.4-py3-none-any.whl", hash = "sha256:1e6ed40af72695464ce98ca2c201ad0ef8fd192246f6c9eac8bba343b980ad34"},
|
||||
{file = "celery-5.3.4.tar.gz", hash = "sha256:9023df6a8962da79eb30c0c84d5f4863d9793a466354cc931d7f72423996de28"},
|
||||
{file = "celery-5.3.5-py3-none-any.whl", hash = "sha256:30b75ac60fb081c2d9f8881382c148ed7c9052031a75a1e8743ff4b4b071f184"},
|
||||
{file = "celery-5.3.5.tar.gz", hash = "sha256:6b65d8dd5db499dd6190c45aa6398e171b99592f2af62c312f7391587feb5458"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
billiard = ">=4.1.0,<5.0"
|
||||
billiard = ">=4.2.0,<5.0"
|
||||
click = ">=8.1.2,<9.0"
|
||||
click-didyoumean = ">=0.3.0"
|
||||
click-plugins = ">=1.1.1"
|
||||
click-repl = ">=0.2.0"
|
||||
kombu = ">=5.3.2,<6.0"
|
||||
kombu = ">=5.3.3,<6.0"
|
||||
python-dateutil = ">=2.8.2"
|
||||
tzdata = ">=2022.7"
|
||||
vine = ">=5.0.0,<6.0"
|
||||
vine = ">=5.1.0,<6.0"
|
||||
|
||||
[package.extras]
|
||||
arangodb = ["pyArango (>=2.0.2)"]
|
||||
auth = ["cryptography (==41.0.3)"]
|
||||
auth = ["cryptography (==41.0.5)"]
|
||||
azureblockblob = ["azure-storage-blob (>=12.15.0)"]
|
||||
brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"]
|
||||
cassandra = ["cassandra-driver (>=3.25.0,<4)"]
|
||||
|
@ -576,26 +576,26 @@ couchbase = ["couchbase (>=3.0.0)"]
|
|||
couchdb = ["pycouchdb (==1.14.2)"]
|
||||
django = ["Django (>=2.2.28)"]
|
||||
dynamodb = ["boto3 (>=1.26.143)"]
|
||||
elasticsearch = ["elasticsearch (<8.0)"]
|
||||
elasticsearch = ["elastic-transport (<=8.10.0)", "elasticsearch (<=8.10.1)"]
|
||||
eventlet = ["eventlet (>=0.32.0)"]
|
||||
gevent = ["gevent (>=1.5.0)"]
|
||||
librabbitmq = ["librabbitmq (>=2.0.0)"]
|
||||
memcache = ["pylibmc (==1.6.3)"]
|
||||
mongodb = ["pymongo[srv] (>=4.0.2)"]
|
||||
msgpack = ["msgpack (==1.0.5)"]
|
||||
msgpack = ["msgpack (==1.0.7)"]
|
||||
pymemcache = ["python-memcached (==1.59)"]
|
||||
pyro = ["pyro4 (==4.82)"]
|
||||
pytest = ["pytest-celery (==0.0.0)"]
|
||||
redis = ["redis (>=4.5.2,!=4.5.5,<5.0.0)"]
|
||||
redis = ["redis (>=4.5.2,!=4.5.5,<6.0.0)"]
|
||||
s3 = ["boto3 (>=1.26.143)"]
|
||||
slmq = ["softlayer-messaging (>=1.0.3)"]
|
||||
solar = ["ephem (==4.1.4)"]
|
||||
solar = ["ephem (==4.1.5)"]
|
||||
sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"]
|
||||
sqs = ["boto3 (>=1.26.143)", "kombu[sqs] (>=5.3.0)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"]
|
||||
tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"]
|
||||
yaml = ["PyYAML (>=3.10)"]
|
||||
zookeeper = ["kazoo (>=1.3.1)"]
|
||||
zstd = ["zstandard (==0.21.0)"]
|
||||
zstd = ["zstandard (==0.22.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
|
@ -1117,13 +1117,13 @@ graph = ["objgraph (>=1.7.2)"]
|
|||
|
||||
[[package]]
|
||||
name = "django"
|
||||
version = "4.2.6"
|
||||
version = "4.2.7"
|
||||
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "Django-4.2.6-py3-none-any.whl", hash = "sha256:a64d2487cdb00ad7461434320ccc38e60af9c404773a2f95ab0093b4453a3215"},
|
||||
{file = "Django-4.2.6.tar.gz", hash = "sha256:08f41f468b63335aea0d904c5729e0250300f6a1907bf293a65499496cdbc68f"},
|
||||
{file = "Django-4.2.7-py3-none-any.whl", hash = "sha256:e1d37c51ad26186de355cbcec16613ebdabfa9689bbade9c538835205a8abbe9"},
|
||||
{file = "Django-4.2.7.tar.gz", hash = "sha256:8e0f1c2c2786b5c0e39fe1afce24c926040fad47c8ea8ad30aaf1188df29fc41"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -1868,13 +1868,13 @@ referencing = ">=0.28.0"
|
|||
|
||||
[[package]]
|
||||
name = "kombu"
|
||||
version = "5.3.2"
|
||||
version = "5.3.3"
|
||||
description = "Messaging library for Python."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "kombu-5.3.2-py3-none-any.whl", hash = "sha256:b753c9cfc9b1e976e637a7cbc1a65d446a22e45546cd996ea28f932082b7dc9e"},
|
||||
{file = "kombu-5.3.2.tar.gz", hash = "sha256:0ba213f630a2cb2772728aef56ac6883dc3a2f13435e10048f6e97d48506dbbd"},
|
||||
{file = "kombu-5.3.3-py3-none-any.whl", hash = "sha256:6cd5c5d5ef77538434b8f81f3e265c414269418645dbb47dbf130a8a05c3e357"},
|
||||
{file = "kombu-5.3.3.tar.gz", hash = "sha256:1491df826cfc5178c80f3e89dd6dfba68e484ef334db81070eb5cb8094b31167"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -1884,14 +1884,14 @@ vine = "*"
|
|||
[package.extras]
|
||||
azureservicebus = ["azure-servicebus (>=7.10.0)"]
|
||||
azurestoragequeues = ["azure-identity (>=1.12.0)", "azure-storage-queue (>=12.6.0)"]
|
||||
confluentkafka = ["confluent-kafka (==2.1.1)"]
|
||||
confluentkafka = ["confluent-kafka (>=2.2.0)"]
|
||||
consul = ["python-consul2"]
|
||||
librabbitmq = ["librabbitmq (>=2.0.0)"]
|
||||
mongodb = ["pymongo (>=4.1.1)"]
|
||||
msgpack = ["msgpack"]
|
||||
pyro = ["pyro4"]
|
||||
qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"]
|
||||
redis = ["redis (>=4.5.2)"]
|
||||
redis = ["redis (>=4.5.2,!=4.5.5,<6.0.0)"]
|
||||
slmq = ["softlayer-messaging (>=1.0.3)"]
|
||||
sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"]
|
||||
sqs = ["boto3 (>=1.26.143)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"]
|
||||
|
@ -2978,17 +2978,17 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no
|
|||
|
||||
[[package]]
|
||||
name = "pytest-django"
|
||||
version = "4.5.2"
|
||||
version = "4.7.0"
|
||||
description = "A Django plugin for pytest."
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-django-4.5.2.tar.gz", hash = "sha256:d9076f759bb7c36939dbdd5ae6633c18edfc2902d1a69fdbefd2426b970ce6c2"},
|
||||
{file = "pytest_django-4.5.2-py3-none-any.whl", hash = "sha256:c60834861933773109334fe5a53e83d1ef4828f2203a1d6a0fa9972f4f75ab3e"},
|
||||
{file = "pytest-django-4.7.0.tar.gz", hash = "sha256:92d6fd46b1d79b54fb6b060bbb39428073396cec717d5f2e122a990d4b6aa5e8"},
|
||||
{file = "pytest_django-4.7.0-py3-none-any.whl", hash = "sha256:4e1c79d5261ade2dd58d91208017cd8f62cb4710b56e012ecd361d15d5d662a2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pytest = ">=5.4.0"
|
||||
pytest = ">=7.0.0"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx", "sphinx-rtd-theme"]
|
||||
|
@ -3374,39 +3374,39 @@ pyasn1 = ">=0.1.3"
|
|||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.1.3"
|
||||
description = "An extremely fast Python linter, written in Rust."
|
||||
version = "0.1.5"
|
||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.1.3-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b46d43d51f7061652eeadb426a9e3caa1e0002470229ab2fc19de8a7b0766901"},
|
||||
{file = "ruff-0.1.3-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b8afeb9abd26b4029c72adc9921b8363374f4e7edb78385ffaa80278313a15f9"},
|
||||
{file = "ruff-0.1.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca3cf365bf32e9ba7e6db3f48a4d3e2c446cd19ebee04f05338bc3910114528b"},
|
||||
{file = "ruff-0.1.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4874c165f96c14a00590dcc727a04dca0cfd110334c24b039458c06cf78a672e"},
|
||||
{file = "ruff-0.1.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eec2dd31eed114e48ea42dbffc443e9b7221976554a504767ceaee3dd38edeb8"},
|
||||
{file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dc3ec4edb3b73f21b4aa51337e16674c752f1d76a4a543af56d7d04e97769613"},
|
||||
{file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e3de9ed2e39160800281848ff4670e1698037ca039bda7b9274f849258d26ce"},
|
||||
{file = "ruff-0.1.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c595193881922cc0556a90f3af99b1c5681f0c552e7a2a189956141d8666fe8"},
|
||||
{file = "ruff-0.1.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f75e670d529aa2288cd00fc0e9b9287603d95e1536d7a7e0cafe00f75e0dd9d"},
|
||||
{file = "ruff-0.1.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:76dd49f6cd945d82d9d4a9a6622c54a994689d8d7b22fa1322983389b4892e20"},
|
||||
{file = "ruff-0.1.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:918b454bc4f8874a616f0d725590277c42949431ceb303950e87fef7a7d94cb3"},
|
||||
{file = "ruff-0.1.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d8859605e729cd5e53aa38275568dbbdb4fe882d2ea2714c5453b678dca83784"},
|
||||
{file = "ruff-0.1.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0b6c55f5ef8d9dd05b230bb6ab80bc4381ecb60ae56db0330f660ea240cb0d4a"},
|
||||
{file = "ruff-0.1.3-py3-none-win32.whl", hash = "sha256:3e7afcbdcfbe3399c34e0f6370c30f6e529193c731b885316c5a09c9e4317eef"},
|
||||
{file = "ruff-0.1.3-py3-none-win_amd64.whl", hash = "sha256:7a18df6638cec4a5bd75350639b2bb2a2366e01222825562c7346674bdceb7ea"},
|
||||
{file = "ruff-0.1.3-py3-none-win_arm64.whl", hash = "sha256:12fd53696c83a194a2db7f9a46337ce06445fb9aa7d25ea6f293cf75b21aca9f"},
|
||||
{file = "ruff-0.1.3.tar.gz", hash = "sha256:3ba6145369a151401d5db79f0a47d50e470384d0d89d0d6f7fab0b589ad07c34"},
|
||||
{file = "ruff-0.1.5-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:32d47fc69261c21a4c48916f16ca272bf2f273eb635d91c65d5cd548bf1f3d96"},
|
||||
{file = "ruff-0.1.5-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:171276c1df6c07fa0597fb946139ced1c2978f4f0b8254f201281729981f3c17"},
|
||||
{file = "ruff-0.1.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ef33cd0bb7316ca65649fc748acc1406dfa4da96a3d0cde6d52f2e866c7b39"},
|
||||
{file = "ruff-0.1.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b2c205827b3f8c13b4a432e9585750b93fd907986fe1aec62b2a02cf4401eee6"},
|
||||
{file = "ruff-0.1.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb408e3a2ad8f6881d0f2e7ad70cddb3ed9f200eb3517a91a245bbe27101d379"},
|
||||
{file = "ruff-0.1.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f20dc5e5905ddb407060ca27267c7174f532375c08076d1a953cf7bb016f5a24"},
|
||||
{file = "ruff-0.1.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aafb9d2b671ed934998e881e2c0f5845a4295e84e719359c71c39a5363cccc91"},
|
||||
{file = "ruff-0.1.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4894dddb476597a0ba4473d72a23151b8b3b0b5f958f2cf4d3f1c572cdb7af7"},
|
||||
{file = "ruff-0.1.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a00a7ec893f665ed60008c70fe9eeb58d210e6b4d83ec6654a9904871f982a2a"},
|
||||
{file = "ruff-0.1.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a8c11206b47f283cbda399a654fd0178d7a389e631f19f51da15cbe631480c5b"},
|
||||
{file = "ruff-0.1.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fa29e67b3284b9a79b1a85ee66e293a94ac6b7bb068b307a8a373c3d343aa8ec"},
|
||||
{file = "ruff-0.1.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9b97fd6da44d6cceb188147b68db69a5741fbc736465b5cea3928fdac0bc1aeb"},
|
||||
{file = "ruff-0.1.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:721f4b9d3b4161df8dc9f09aa8562e39d14e55a4dbaa451a8e55bdc9590e20f4"},
|
||||
{file = "ruff-0.1.5-py3-none-win32.whl", hash = "sha256:f80c73bba6bc69e4fdc73b3991db0b546ce641bdcd5b07210b8ad6f64c79f1ab"},
|
||||
{file = "ruff-0.1.5-py3-none-win_amd64.whl", hash = "sha256:c21fe20ee7d76206d290a76271c1af7a5096bc4c73ab9383ed2ad35f852a0087"},
|
||||
{file = "ruff-0.1.5-py3-none-win_arm64.whl", hash = "sha256:82bfcb9927e88c1ed50f49ac6c9728dab3ea451212693fe40d08d314663e412f"},
|
||||
{file = "ruff-0.1.5.tar.gz", hash = "sha256:5cbec0ef2ae1748fb194f420fb03fb2c25c3258c86129af7172ff8f198f125ab"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "selenium"
|
||||
version = "4.14.0"
|
||||
version = "4.15.2"
|
||||
description = ""
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "selenium-4.14.0-py3-none-any.whl", hash = "sha256:be9824a9354a7fe288e3fad9ceb6a9c65ddc7c44545d23ad0ebf4ce202b19893"},
|
||||
{file = "selenium-4.14.0.tar.gz", hash = "sha256:0d14b0d9842366f38fb5f8f842cf7c042bcfa062affc6a0a86e4d634bdd0fe54"},
|
||||
{file = "selenium-4.15.2-py3-none-any.whl", hash = "sha256:9e82cd1ac647fb73cf0d4a6e280284102aaa3c9d94f0fa6e6cc4b5db6a30afbf"},
|
||||
{file = "selenium-4.15.2.tar.gz", hash = "sha256:22eab5a1724c73d51b240a69ca702997b717eee4ba1f6065bf5d6b44dba01d48"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -3417,13 +3417,13 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
|
|||
|
||||
[[package]]
|
||||
name = "sentry-sdk"
|
||||
version = "1.32.0"
|
||||
version = "1.34.0"
|
||||
description = "Python client for Sentry (https://sentry.io)"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "sentry-sdk-1.32.0.tar.gz", hash = "sha256:935e8fbd7787a3702457393b74b13d89a5afb67185bc0af85c00cb27cbd42e7c"},
|
||||
{file = "sentry_sdk-1.32.0-py2.py3-none-any.whl", hash = "sha256:eeb0b3550536f3bbc05bb1c7e0feb3a78d74acb43b607159a606ed2ec0a33a4d"},
|
||||
{file = "sentry-sdk-1.34.0.tar.gz", hash = "sha256:e5d0d2b25931d88fa10986da59d941ac6037f742ab6ff2fce4143a27981d60c3"},
|
||||
{file = "sentry_sdk-1.34.0-py2.py3-none-any.whl", hash = "sha256:76dd087f38062ac6c1e30ed6feb533ee0037ff9e709974802db7b5dbf2e5db21"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -3675,13 +3675,13 @@ wsproto = ">=0.14"
|
|||
|
||||
[[package]]
|
||||
name = "twilio"
|
||||
version = "8.10.0"
|
||||
version = "8.10.1"
|
||||
description = "Twilio API client and TwiML generator"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "twilio-8.10.0-py2.py3-none-any.whl", hash = "sha256:1eb04af92f3e70fcc87a2fd30617f53784e34045d054e4ae3dc9cfe7bdf1e692"},
|
||||
{file = "twilio-8.10.0.tar.gz", hash = "sha256:3bf2def228ceaa7519f4d6e58b2e3c9cb5d865af02b4618239e52c9d9e75e29d"},
|
||||
{file = "twilio-8.10.1-py2.py3-none-any.whl", hash = "sha256:eb08ac17c8eb4f6176907b4e7dea984102488fb86ad146ecd47e8a8dfcf3cfa3"},
|
||||
{file = "twilio-8.10.1.tar.gz", hash = "sha256:902267856d09cf1f59b7fa4af594edae0225fdd8b473a6ef8e5799e823e0a611"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -3692,13 +3692,13 @@ requests = ">=2.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "twisted"
|
||||
version = "23.8.0"
|
||||
version = "23.10.0"
|
||||
description = "An asynchronous networking framework written in Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7.1"
|
||||
python-versions = ">=3.8.0"
|
||||
files = [
|
||||
{file = "twisted-23.8.0-py3-none-any.whl", hash = "sha256:b8bdba145de120ffb36c20e6e071cce984e89fba798611ed0704216fb7f884cd"},
|
||||
{file = "twisted-23.8.0.tar.gz", hash = "sha256:3c73360add17336a622c0d811c2a2ce29866b6e59b1125fd6509b17252098a24"},
|
||||
{file = "twisted-23.10.0-py3-none-any.whl", hash = "sha256:4ae8bce12999a35f7fe6443e7f1893e6fe09588c8d2bed9c35cdce8ff2d5b444"},
|
||||
{file = "twisted-23.10.0.tar.gz", hash = "sha256:987847a0790a2c597197613686e2784fd54167df3a55d0fb17c8412305d76ce5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -3711,19 +3711,18 @@ incremental = ">=22.10.0"
|
|||
pyopenssl = {version = ">=21.0.0", optional = true, markers = "extra == \"tls\""}
|
||||
service-identity = {version = ">=18.1.0", optional = true, markers = "extra == \"tls\""}
|
||||
twisted-iocpsupport = {version = ">=1.0.2,<2", markers = "platform_system == \"Windows\""}
|
||||
typing-extensions = ">=3.10.0"
|
||||
typing-extensions = ">=4.2.0"
|
||||
zope-interface = ">=5"
|
||||
|
||||
[package.extras]
|
||||
all-non-platform = ["twisted[conch,contextvars,http2,serial,test,tls]", "twisted[conch,contextvars,http2,serial,test,tls]"]
|
||||
all-non-platform = ["twisted[conch,http2,serial,test,tls]", "twisted[conch,http2,serial,test,tls]"]
|
||||
conch = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)"]
|
||||
contextvars = ["contextvars (>=2.4,<3)"]
|
||||
dev = ["coverage (>=6b1,<7)", "pyflakes (>=2.2,<3.0)", "python-subunit (>=1.4,<2.0)", "twisted[dev-release]", "twistedchecker (>=0.7,<1.0)"]
|
||||
dev-release = ["pydoctor (>=23.4.0,<23.5.0)", "pydoctor (>=23.4.0,<23.5.0)", "readthedocs-sphinx-ext (>=2.2,<3.0)", "readthedocs-sphinx-ext (>=2.2,<3.0)", "sphinx (>=5,<7)", "sphinx (>=5,<7)", "sphinx-rtd-theme (>=1.2,<2.0)", "sphinx-rtd-theme (>=1.2,<2.0)", "towncrier (>=22.12,<23.0)", "towncrier (>=22.12,<23.0)", "urllib3 (<2)", "urllib3 (<2)"]
|
||||
dev-release = ["pydoctor (>=23.9.0,<23.10.0)", "pydoctor (>=23.9.0,<23.10.0)", "sphinx (>=6,<7)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "towncrier (>=23.6,<24.0)"]
|
||||
gtk-platform = ["pygobject", "pygobject", "twisted[all-non-platform]", "twisted[all-non-platform]"]
|
||||
http2 = ["h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)"]
|
||||
macos-platform = ["pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "twisted[all-non-platform]", "twisted[all-non-platform]"]
|
||||
mypy = ["mypy (==0.981)", "mypy-extensions (==0.4.3)", "mypy-zope (==0.3.11)", "twisted[all-non-platform,dev]", "types-pyopenssl", "types-setuptools"]
|
||||
mypy = ["mypy (>=1.5.1,<1.6.0)", "mypy-zope (>=1.0.1,<1.1.0)", "twisted[all-non-platform,dev]", "types-pyopenssl", "types-setuptools"]
|
||||
osx-platform = ["twisted[macos-platform]", "twisted[macos-platform]"]
|
||||
serial = ["pyserial (>=3.0)", "pywin32 (!=226)"]
|
||||
test = ["cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pyhamcrest (>=2)"]
|
||||
|
@ -3856,13 +3855,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.23.2"
|
||||
version = "0.24.0.post1"
|
||||
description = "The lightning-fast ASGI server."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "uvicorn-0.23.2-py3-none-any.whl", hash = "sha256:1f9be6558f01239d4fdf22ef8126c39cb1ad0addf76c40e760549d2c2f43ab53"},
|
||||
{file = "uvicorn-0.23.2.tar.gz", hash = "sha256:4d3cc12d7727ba72b64d12d3cc7743124074c0a69f7b201512fc50c3e3f1569a"},
|
||||
{file = "uvicorn-0.24.0.post1-py3-none-any.whl", hash = "sha256:7c84fea70c619d4a710153482c0d230929af7bcf76c7bfa6de151f0a3a80121e"},
|
||||
{file = "uvicorn-0.24.0.post1.tar.gz", hash = "sha256:09c8e5a79dc466bdf28dead50093957db184de356fcdc48697bad3bde4c2588e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -3925,13 +3924,13 @@ test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "my
|
|||
|
||||
[[package]]
|
||||
name = "vine"
|
||||
version = "5.0.0"
|
||||
description = "Promises, promises, promises."
|
||||
version = "5.1.0"
|
||||
description = "Python promises."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"},
|
||||
{file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"},
|
||||
{file = "vine-5.1.0-py3-none-any.whl", hash = "sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc"},
|
||||
{file = "vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4020,13 +4019,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "webauthn"
|
||||
version = "1.11.0"
|
||||
version = "1.11.1"
|
||||
description = "Pythonic WebAuthn"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "webauthn-1.11.0-py3-none-any.whl", hash = "sha256:9c8a81f7e310aee022a038ae2c76711bcf0a94521a471225e05c36871f83eeda"},
|
||||
{file = "webauthn-1.11.0.tar.gz", hash = "sha256:1e808de1e3625a4b361e249e1bbb254d2a3a5c6b206e6f7260c4febe51f45276"},
|
||||
{file = "webauthn-1.11.1-py3-none-any.whl", hash = "sha256:13592ee71489b571cb6e4a5d8b3c34f7b040cd3539a9d94b6b7d23fa88df5dfb"},
|
||||
{file = "webauthn-1.11.1.tar.gz", hash = "sha256:24eda57903897369797f52a377f8c470e7057e79da5525779d0720a9fcc11926"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
|
@ -15,7 +15,14 @@ COPY web .
|
|||
RUN npm run build-proxy
|
||||
|
||||
# Stage 2: Build
|
||||
FROM docker.io/golang:1.21.3-bookworm AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
|
||||
ARG GOOS=$TARGETOS
|
||||
ARG GOARCH=$TARGETARCH
|
||||
|
||||
WORKDIR /go/src/goauthentik.io
|
||||
|
||||
|
@ -29,7 +36,7 @@ ENV CGO_ENABLED=0
|
|||
COPY . .
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
go build -o /go/proxy ./cmd/proxy
|
||||
GOARM="${TARGETVARIANT#v}" go build -o /go/proxy ./cmd/proxy
|
||||
|
||||
# Stage 3: Run
|
||||
FROM gcr.io/distroless/static-debian11:debug
|
||||
|
|
|
@ -113,7 +113,7 @@ filterwarnings = [
|
|||
|
||||
[tool.poetry]
|
||||
name = "authentik"
|
||||
version = "2023.10.2"
|
||||
version = "2023.10.3"
|
||||
description = ""
|
||||
authors = ["authentik Team <hello@goauthentik.io>"]
|
||||
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# Stage 1: Build
|
||||
FROM docker.io/golang:1.21.3-bookworm AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
|
||||
ARG GOOS=$TARGETOS
|
||||
ARG GOARCH=$TARGETARCH
|
||||
|
||||
WORKDIR /go/src/goauthentik.io
|
||||
|
||||
|
@ -13,7 +20,7 @@ ENV CGO_ENABLED=0
|
|||
COPY . .
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
go build -o /go/radius ./cmd/radius
|
||||
GOARM="${TARGETVARIANT#v}" go build -o /go/radius ./cmd/radius
|
||||
|
||||
# Stage 2: Run
|
||||
FROM gcr.io/distroless/static-debian11:debug
|
||||
|
|
70
schema.yml
70
schema.yml
|
@ -1,7 +1,7 @@
|
|||
openapi: 3.0.3
|
||||
info:
|
||||
title: authentik
|
||||
version: 2023.10.2
|
||||
version: 2023.10.3
|
||||
description: Making authentication simple.
|
||||
contact:
|
||||
email: hello@goauthentik.io
|
||||
|
@ -18940,10 +18940,10 @@ paths:
|
|||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
/sources/ldap/{slug}/sync_status/:
|
||||
/sources/ldap/{slug}/sync/:
|
||||
get:
|
||||
operationId: sources_ldap_sync_status_list
|
||||
description: Get source's sync status
|
||||
operationId: sources_ldap_sync_retrieve
|
||||
description: Get source's sync status or start source sync
|
||||
parameters:
|
||||
- in: path
|
||||
name: slug
|
||||
|
@ -18960,9 +18960,40 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Task'
|
||||
$ref: '#/components/schemas/LDAPSyncStatus'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
post:
|
||||
operationId: sources_ldap_sync_create
|
||||
description: Get source's sync status or start source sync
|
||||
parameters:
|
||||
- in: path
|
||||
name: slug
|
||||
schema:
|
||||
type: string
|
||||
description: Internal source name, used in URLs.
|
||||
required: true
|
||||
tags:
|
||||
- sources
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LDAPSyncStatus'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
|
@ -32812,9 +32843,19 @@ components:
|
|||
type: string
|
||||
format: uuid
|
||||
description: Property mappings used for group creation/updating.
|
||||
connectivity:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Get cached source connectivity
|
||||
readOnly: true
|
||||
required:
|
||||
- base_dn
|
||||
- component
|
||||
- connectivity
|
||||
- icon
|
||||
- managed
|
||||
- meta_model_name
|
||||
|
@ -32948,6 +32989,21 @@ components:
|
|||
- name
|
||||
- server_uri
|
||||
- slug
|
||||
LDAPSyncStatus:
|
||||
type: object
|
||||
description: LDAP Source sync status
|
||||
properties:
|
||||
is_running:
|
||||
type: boolean
|
||||
readOnly: true
|
||||
tasks:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Task'
|
||||
readOnly: true
|
||||
required:
|
||||
- is_running
|
||||
- tasks
|
||||
LayoutEnum:
|
||||
enum:
|
||||
- stacked
|
||||
|
|
319
tests/wdio/package-lock.json
generated
319
tests/wdio/package-lock.json
generated
|
@ -6,21 +6,21 @@
|
|||
"": {
|
||||
"name": "@goauthentik/web-tests",
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
||||
"@typescript-eslint/parser": "^6.9.0",
|
||||
"@wdio/cli": "^8.20.5",
|
||||
"@wdio/local-runner": "^8.20.5",
|
||||
"@wdio/mocha-framework": "^8.20.3",
|
||||
"@wdio/spec-reporter": "^8.20.0",
|
||||
"eslint": "^8.52.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.10.0",
|
||||
"@typescript-eslint/parser": "^6.10.0",
|
||||
"@wdio/cli": "^8.22.1",
|
||||
"@wdio/local-runner": "^8.22.1",
|
||||
"@wdio/mocha-framework": "^8.22.0",
|
||||
"@wdio/spec-reporter": "^8.21.0",
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-sonarjs": "^0.21.0",
|
||||
"eslint-plugin-sonarjs": "^0.23.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.0.3",
|
||||
"prettier": "^3.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2",
|
||||
"wdio-wait-for": "^3.0.7"
|
||||
"wdio-wait-for": "^3.0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@aashutoshrathi/word-wrap": {
|
||||
|
@ -329,9 +329,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
|
||||
"integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz",
|
||||
"integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
|
@ -352,9 +352,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/globals": {
|
||||
"version": "13.22.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz",
|
||||
"integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==",
|
||||
"version": "13.23.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
|
||||
"integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"type-fest": "^0.20.2"
|
||||
|
@ -379,9 +379,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "8.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz",
|
||||
"integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==",
|
||||
"version": "8.53.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz",
|
||||
"integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -787,9 +787,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@trivago/prettier-plugin-sort-imports": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.2.1.tgz",
|
||||
"integrity": "sha512-iuy2MPVURGdxILTchHr15VAioItuYBejKfcTmQFlxIuqA7jeaT6ngr5aUIG6S6U096d6a6lJCgaOwlRrPLlOPg==",
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz",
|
||||
"integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/generator": "7.17.7",
|
||||
|
@ -940,16 +940,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.0.tgz",
|
||||
"integrity": "sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz",
|
||||
"integrity": "sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.5.1",
|
||||
"@typescript-eslint/scope-manager": "6.9.0",
|
||||
"@typescript-eslint/type-utils": "6.9.0",
|
||||
"@typescript-eslint/utils": "6.9.0",
|
||||
"@typescript-eslint/visitor-keys": "6.9.0",
|
||||
"@typescript-eslint/scope-manager": "6.10.0",
|
||||
"@typescript-eslint/type-utils": "6.10.0",
|
||||
"@typescript-eslint/utils": "6.10.0",
|
||||
"@typescript-eslint/visitor-keys": "6.10.0",
|
||||
"debug": "^4.3.4",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.2.4",
|
||||
|
@ -975,15 +975,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz",
|
||||
"integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz",
|
||||
"integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "6.9.0",
|
||||
"@typescript-eslint/types": "6.9.0",
|
||||
"@typescript-eslint/typescript-estree": "6.9.0",
|
||||
"@typescript-eslint/visitor-keys": "6.9.0",
|
||||
"@typescript-eslint/scope-manager": "6.10.0",
|
||||
"@typescript-eslint/types": "6.10.0",
|
||||
"@typescript-eslint/typescript-estree": "6.10.0",
|
||||
"@typescript-eslint/visitor-keys": "6.10.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1003,13 +1003,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz",
|
||||
"integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz",
|
||||
"integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.9.0",
|
||||
"@typescript-eslint/visitor-keys": "6.9.0"
|
||||
"@typescript-eslint/types": "6.10.0",
|
||||
"@typescript-eslint/visitor-keys": "6.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
|
@ -1020,13 +1020,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.0.tgz",
|
||||
"integrity": "sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz",
|
||||
"integrity": "sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "6.9.0",
|
||||
"@typescript-eslint/utils": "6.9.0",
|
||||
"@typescript-eslint/typescript-estree": "6.10.0",
|
||||
"@typescript-eslint/utils": "6.10.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
|
@ -1047,9 +1047,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz",
|
||||
"integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz",
|
||||
"integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
|
@ -1060,13 +1060,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz",
|
||||
"integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz",
|
||||
"integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.9.0",
|
||||
"@typescript-eslint/visitor-keys": "6.9.0",
|
||||
"@typescript-eslint/types": "6.10.0",
|
||||
"@typescript-eslint/visitor-keys": "6.10.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
|
@ -1087,17 +1087,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.0.tgz",
|
||||
"integrity": "sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.10.0.tgz",
|
||||
"integrity": "sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@types/json-schema": "^7.0.12",
|
||||
"@types/semver": "^7.5.0",
|
||||
"@typescript-eslint/scope-manager": "6.9.0",
|
||||
"@typescript-eslint/types": "6.9.0",
|
||||
"@typescript-eslint/typescript-estree": "6.9.0",
|
||||
"@typescript-eslint/scope-manager": "6.10.0",
|
||||
"@typescript-eslint/types": "6.10.0",
|
||||
"@typescript-eslint/typescript-estree": "6.10.0",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1112,12 +1112,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz",
|
||||
"integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz",
|
||||
"integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.9.0",
|
||||
"@typescript-eslint/types": "6.10.0",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1135,18 +1135,18 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@wdio/cli": {
|
||||
"version": "8.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.20.5.tgz",
|
||||
"integrity": "sha512-Z5wAf8gJMBZGK15pRVFbX8TOIEk7cOXKb9Gjs9pP3DOgx3+xpGlLmgrbLg/wB+rMXA4eu7bt5ZUItPWAWmq6IQ==",
|
||||
"version": "8.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.22.1.tgz",
|
||||
"integrity": "sha512-OgqsSFtMyfyOC9qMwS9YKjlLN/TwybQHnMIm9G3EZIGYKnAffzC6xXhgjyTqeHIyGieotH52mR0kHE0XIubw+A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.1",
|
||||
"@wdio/config": "8.20.3",
|
||||
"@wdio/globals": "8.20.5",
|
||||
"@wdio/config": "8.22.1",
|
||||
"@wdio/globals": "8.22.1",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/protocols": "8.20.4",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/utils": "8.20.3",
|
||||
"@wdio/protocols": "8.22.0",
|
||||
"@wdio/types": "8.21.0",
|
||||
"@wdio/utils": "8.22.0",
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"chalk": "^5.2.0",
|
||||
"chokidar": "^3.5.3",
|
||||
|
@ -1160,9 +1160,9 @@
|
|||
"lodash.flattendeep": "^4.4.0",
|
||||
"lodash.pickby": "^4.6.0",
|
||||
"lodash.union": "^4.6.0",
|
||||
"read-pkg-up": "10.1.0",
|
||||
"read-pkg-up": "^10.0.0",
|
||||
"recursive-readdir": "^2.2.3",
|
||||
"webdriverio": "8.20.4",
|
||||
"webdriverio": "8.22.1",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
|
@ -1185,48 +1185,47 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/config": {
|
||||
"version": "8.20.3",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.20.3.tgz",
|
||||
"integrity": "sha512-UaPjDjdXztrWgpoodSjZc1/9oXX1WpjhZSW55ZA2PKzCO7QuS/Fory5lMMpJD4v6/9fNUiRp7A4/rd+w7am1vA==",
|
||||
"version": "8.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.22.1.tgz",
|
||||
"integrity": "sha512-ttxvtKFaOB5BJ6eDl1Lcq8STLN3V+yOEEkVXIrNqOdFOrAaljqzX20vaEmNtj9pQIoTZs2WoX8K2cmXdyxw+DA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/utils": "8.20.3",
|
||||
"@wdio/types": "8.21.0",
|
||||
"@wdio/utils": "8.22.0",
|
||||
"decamelize": "^6.0.0",
|
||||
"deepmerge-ts": "^5.0.0",
|
||||
"glob": "^10.2.2",
|
||||
"import-meta-resolve": "^3.0.0",
|
||||
"read-pkg-up": "^10.0.0"
|
||||
"import-meta-resolve": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/globals": {
|
||||
"version": "8.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.20.5.tgz",
|
||||
"integrity": "sha512-79BFF/b+qQ1Td3KfoN/xEf9Bzbb3rKovjyl5BD205pIyWJCeZJDsK693vV8g6z6Q+/pvp/GPfepqSmvrKQokEw==",
|
||||
"version": "8.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.22.1.tgz",
|
||||
"integrity": "sha512-Wf9D9ejiwArsAr80y7UZB0AsGLNgCWUoIbulK4vbzUU50RAymxbXeJEQgfwQ231+eHv8wIViQ45N0FoRJsHVcA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"expect-webdriverio": "^4.2.5",
|
||||
"webdriverio": "8.20.4"
|
||||
"webdriverio": "8.22.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/local-runner": {
|
||||
"version": "8.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.20.5.tgz",
|
||||
"integrity": "sha512-lm5eyirDiSuxLkwe1fkMXjPd54Ortp5i8wfJPlAImyG9fxU5CY8D9V1bkjpDqOkd4RLmUk1z4mp9gJWghrAd0Q==",
|
||||
"version": "8.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.22.1.tgz",
|
||||
"integrity": "sha512-bEWkU/6GKS9NIgTO4OyxOlWjr4lL22P0wg8ShmDX4qY2nStu5B/2tpl3sqLcmtFiCpsjdINIYRla4lz9xOUy1Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/repl": "8.10.1",
|
||||
"@wdio/runner": "8.20.5",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/runner": "8.22.1",
|
||||
"@wdio/types": "8.21.0",
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"split2": "^4.1.0",
|
||||
"stream-buffers": "^3.0.2"
|
||||
|
@ -1263,16 +1262,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/mocha-framework": {
|
||||
"version": "8.20.3",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.20.3.tgz",
|
||||
"integrity": "sha512-AF27tW2ToQ4+fzuBwI71ABjPhmPoESj+UtJYx4ahZjHQUyCCEhkiYIeh8T6UEFFpbIQeQV1Fz12UEK/18EGbzw==",
|
||||
"version": "8.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.22.0.tgz",
|
||||
"integrity": "sha512-kkgoNNXHiR/D48dB+dEQ0nmP5u1NFiUllOLK91z5x5+mwzCh17GpyakhUXLIyVdciiU7T1grJQC5pxqdvPLBkQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/mocha": "^10.0.0",
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/utils": "8.20.3",
|
||||
"@wdio/types": "8.21.0",
|
||||
"@wdio/utils": "8.22.0",
|
||||
"mocha": "^10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1280,9 +1279,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/protocols": {
|
||||
"version": "8.20.4",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-8.20.4.tgz",
|
||||
"integrity": "sha512-9PwA2xgjsoB/9Fm8UWRhJlw61O69ckRICuBn0bzoHmMF7uMzYgDvDTekzYKn8JfjzvLm/MnWXL8raCZfQQ0P5g==",
|
||||
"version": "8.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-8.22.0.tgz",
|
||||
"integrity": "sha512-2y5lTYAAzQWvExL1FGCe6gujVpOpTxk+czT0Qx0j0iUlfdOwp9gWVLYl8ochTJHzfeM45GHvuZ/ndT52grsTtg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@wdio/repl": {
|
||||
|
@ -1298,14 +1297,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/reporter": {
|
||||
"version": "8.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.20.0.tgz",
|
||||
"integrity": "sha512-9a0cIuwDYwMgBwx/JTRITjlxef63xEt+q+nQBsEwzaPtcTMLzRIGAYO7BKxf9ejYL3tdoPJYJm3GtBKeh+2QIQ==",
|
||||
"version": "8.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.21.0.tgz",
|
||||
"integrity": "sha512-noZX04lP7WvoaEAwhOTy0C/ddyVTEHQe/AGMTzgKgoQclEM3I2nZ1PjEwe/ACfIm0880EGIDW7ssN2pf/4ZNDQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/types": "8.21.0",
|
||||
"diff": "^5.0.0",
|
||||
"object-inspect": "^1.12.0"
|
||||
},
|
||||
|
@ -1314,35 +1313,35 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/runner": {
|
||||
"version": "8.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.20.5.tgz",
|
||||
"integrity": "sha512-JmH9995lI4FB95vQ2/l4oAJ3zoo49PIhZutNcwu98o2DDFWPxSGsOPRKI/B5u5OvJ0OkK0AzcN6XdJAfAPZSfA==",
|
||||
"version": "8.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.22.1.tgz",
|
||||
"integrity": "sha512-VHX0l9q6WvDnvf89Q29xAgYBkBUo9ggzrpUA9VGntj+q7ey7Kv7CPBTzv4HVBX9Hp45xwSEl03lqFVcwn5NvTg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/config": "8.20.3",
|
||||
"@wdio/globals": "8.20.5",
|
||||
"@wdio/config": "8.22.1",
|
||||
"@wdio/globals": "8.22.1",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/utils": "8.20.3",
|
||||
"@wdio/types": "8.21.0",
|
||||
"@wdio/utils": "8.22.0",
|
||||
"deepmerge-ts": "^5.0.0",
|
||||
"expect-webdriverio": "^4.2.5",
|
||||
"gaze": "^1.1.2",
|
||||
"webdriver": "8.20.4",
|
||||
"webdriverio": "8.20.4"
|
||||
"webdriver": "8.22.1",
|
||||
"webdriverio": "8.22.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/spec-reporter": {
|
||||
"version": "8.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.20.0.tgz",
|
||||
"integrity": "sha512-HpVE/99Kg/no94ETpI4JWoJzqpcsAnJQpbg5HdSyZqXuGj9WnRF/PGXK7VDU+DZwGQgOF9A6s6H0hd+FTHDrHg==",
|
||||
"version": "8.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.21.0.tgz",
|
||||
"integrity": "sha512-Lb6MTjISlaZJx5/2kjJC/E9FM55BZUy3HPbhYbbWUSWqi9Yk8I7n6e90c8uHwDOK5zMyRof9501lUtLyIHY9Og==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@wdio/reporter": "8.20.0",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/reporter": "8.21.0",
|
||||
"@wdio/types": "8.21.0",
|
||||
"chalk": "^5.1.2",
|
||||
"easy-table": "^1.2.0",
|
||||
"pretty-ms": "^7.0.0"
|
||||
|
@ -1364,9 +1363,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/types": {
|
||||
"version": "8.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.20.0.tgz",
|
||||
"integrity": "sha512-y0En5V5PPF48IHJMetaNYQobhCr3ddsgp2aX/crLL51UccWqnFpCL8pCh6cP01gRgCchCasa2JCBMB+PucbYmA==",
|
||||
"version": "8.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.21.0.tgz",
|
||||
"integrity": "sha512-mZFOipmu541z0BXBW7mBAUjM4zZWhNnP/w321OSYx082Jy4d0UHMFXYWaOC98DIMBPahJu/yLX2WH5iCrazKSA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0"
|
||||
|
@ -1376,14 +1375,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/utils": {
|
||||
"version": "8.20.3",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.20.3.tgz",
|
||||
"integrity": "sha512-McGS9TFNfjS3cGJkF8hXyajGE5LKFJnPg/fbdXTIBzYohiAzQ1rUMyllPdxxHslnpQPkflBHI6XSYBxU7yB9Lw==",
|
||||
"version": "8.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.22.0.tgz",
|
||||
"integrity": "sha512-n09ZLfe6NADQ7XyeO45nPBtNHi8nwu1RpOI18c94SrRS7gmO0CQWpjSilJCoHvu10ekUPJE7Oh/1Nw28w7ceVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "^1.6.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/types": "8.21.0",
|
||||
"decamelize": "^6.0.0",
|
||||
"deepmerge-ts": "^5.1.0",
|
||||
"edgedriver": "^5.3.5",
|
||||
|
@ -2572,9 +2571,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/devtools-protocol": {
|
||||
"version": "0.0.1209236",
|
||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1209236.tgz",
|
||||
"integrity": "sha512-z4eehc+fhmptqhxwreLcg9iydszZGU4Q5FzaaElXVGp3KyfXbjtXeUCmo4l8FxBJbyXtCz4VRIJsGW2ekApyUQ==",
|
||||
"version": "0.0.1213968",
|
||||
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1213968.tgz",
|
||||
"integrity": "sha512-o4n/beY+3CcZwFctYapjGelKptR4AuQT5gXS1Kvgbig+ArwkxK7f8wDVuD1wsoswiJWCwV6OK+Qb7vhNzNmABQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/diff": {
|
||||
|
@ -2922,15 +2921,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.52.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz",
|
||||
"integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==",
|
||||
"version": "8.53.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz",
|
||||
"integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.6.1",
|
||||
"@eslint/eslintrc": "^2.1.2",
|
||||
"@eslint/js": "8.52.0",
|
||||
"@eslint/eslintrc": "^2.1.3",
|
||||
"@eslint/js": "8.53.0",
|
||||
"@humanwhocodes/config-array": "^0.11.13",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
|
@ -2989,9 +2988,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-sonarjs": {
|
||||
"version": "0.21.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.21.0.tgz",
|
||||
"integrity": "sha512-oezUDfFT5S6j3rQheZ4DLPrbetPmMS7zHIKWGHr0CM3g5JgyZroz1FpIKa4jV83NsGpmgIeagpokWDKIJzRQmw==",
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.23.0.tgz",
|
||||
"integrity": "sha512-z44T3PBf9W7qQ/aR+NmofOTyg6HLhSEZOPD4zhStqBpLoMp8GYhFksuUBnCxbnf1nfISpKBVkQhiBLFI/F4Wlg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
|
@ -6591,9 +6590,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
|
||||
"integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz",
|
||||
"integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
|
@ -6706,9 +6705,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
||||
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
|
@ -8572,9 +8571,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/wdio-wait-for": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/wdio-wait-for/-/wdio-wait-for-3.0.7.tgz",
|
||||
"integrity": "sha512-NLxEg57+DAQvsEgsAcuF0zM2XDAQTfbKn2mN4nw9hDzz3RfgsZbCxvp93Nm/3609QuxpikC+MxgQ5ORLSoptvA==",
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/wdio-wait-for/-/wdio-wait-for-3.0.8.tgz",
|
||||
"integrity": "sha512-Lptqzqso57sia7q6BRG2M+4S0YysXobcj9gchZxJBqYewgoH4e6Rime6i4WseIW85zmDMJu8pMSWNK4efong8A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
|
@ -8590,18 +8589,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/webdriver": {
|
||||
"version": "8.20.4",
|
||||
"resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.20.4.tgz",
|
||||
"integrity": "sha512-X/6l+zGXn1trqA1LRwYETIJgkJQTVZ/xE1SrTlSxk2BE7Tq40voxfbDKUyauaCyRyABhA0ZgK5/1UOqeCKW15w==",
|
||||
"version": "8.22.1",
|
||||
"resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.22.1.tgz",
|
||||
"integrity": "sha512-EQY2YjbOZInuvYAqEEP7w7voWSy9cPMt3UB1o1+obKhrD8dkIDZNkPocpZUI59PokqHTXk4zIclV50k1KpyyiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@types/ws": "^8.5.3",
|
||||
"@wdio/config": "8.20.3",
|
||||
"@wdio/config": "8.22.1",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/protocols": "8.20.4",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/utils": "8.20.3",
|
||||
"@wdio/protocols": "8.22.0",
|
||||
"@wdio/types": "8.21.0",
|
||||
"@wdio/utils": "8.22.0",
|
||||
"deepmerge-ts": "^5.1.0",
|
||||
"got": "^ 12.6.1",
|
||||
"ky": "^0.33.0",
|
||||
|
@ -8649,23 +8648,23 @@
|
|||
}
|
||||
},
|
||||
"node_modules/webdriverio": {
|
||||
"version": "8.20.4",
|
||||
"resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.20.4.tgz",
|
||||
"integrity": "sha512-+iyYK0NTviXv3Lyws07CaX9pLET9l0bh8aPICfCyf7f0NZLUDvUoEKvjviMCfLq4lbDu7CFIEyDZUJeuqlRwlw==",
|
||||
"version": "8.22.1",
|
||||
"resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.22.1.tgz",
|
||||
"integrity": "sha512-SFqCKM93DPZU5Vn2r9OMi5EFbJHmWnIf8KXZvdzVOkGzQxFDtJ8LDgzwH1/LZxjG9nO+D7y+4wyQl7V24b8L+Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/config": "8.20.3",
|
||||
"@wdio/config": "8.22.1",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/protocols": "8.20.4",
|
||||
"@wdio/protocols": "8.22.0",
|
||||
"@wdio/repl": "8.10.1",
|
||||
"@wdio/types": "8.20.0",
|
||||
"@wdio/utils": "8.20.3",
|
||||
"@wdio/types": "8.21.0",
|
||||
"@wdio/utils": "8.22.0",
|
||||
"archiver": "^6.0.0",
|
||||
"aria-query": "^5.0.0",
|
||||
"css-shorthand-properties": "^1.1.1",
|
||||
"css-value": "^0.0.1",
|
||||
"devtools-protocol": "^0.0.1209236",
|
||||
"devtools-protocol": "^0.0.1213968",
|
||||
"grapheme-splitter": "^1.0.2",
|
||||
"import-meta-resolve": "^3.0.0",
|
||||
"is-plain-obj": "^4.1.0",
|
||||
|
@ -8677,7 +8676,7 @@
|
|||
"resq": "^1.9.1",
|
||||
"rgb2hex": "0.2.5",
|
||||
"serialize-error": "^11.0.1",
|
||||
"webdriver": "8.20.4"
|
||||
"webdriver": "8.22.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
"private": true,
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
||||
"@typescript-eslint/parser": "^6.9.0",
|
||||
"@wdio/cli": "^8.20.5",
|
||||
"@wdio/local-runner": "^8.20.5",
|
||||
"@wdio/mocha-framework": "^8.20.3",
|
||||
"@wdio/spec-reporter": "^8.20.0",
|
||||
"eslint": "^8.52.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.10.0",
|
||||
"@typescript-eslint/parser": "^6.10.0",
|
||||
"@wdio/cli": "^8.22.1",
|
||||
"@wdio/local-runner": "^8.22.1",
|
||||
"@wdio/mocha-framework": "^8.22.0",
|
||||
"@wdio/spec-reporter": "^8.21.0",
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-sonarjs": "^0.21.0",
|
||||
"eslint-plugin-sonarjs": "^0.23.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.0.3",
|
||||
"prettier": "^3.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2",
|
||||
"wdio-wait-for": "^3.0.7"
|
||||
"wdio-wait-for": "^3.0.8"
|
||||
},
|
||||
"scripts": {
|
||||
"wdio": "wdio run ./wdio.conf.ts",
|
||||
|
|
2953
web/package-lock.json
generated
2953
web/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -36,86 +36,86 @@
|
|||
"@codemirror/lang-xml": "^6.0.2",
|
||||
"@codemirror/legacy-modes": "^6.3.3",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@formatjs/intl-listformat": "^7.5.0",
|
||||
"@formatjs/intl-listformat": "^7.5.2",
|
||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||
"@goauthentik/api": "^2023.10.1-1698348102",
|
||||
"@lit-labs/context": "^0.4.1",
|
||||
"@goauthentik/api": "^2023.10.3-1699554078",
|
||||
"@lit-labs/context": "^0.4.0",
|
||||
"@lit-labs/task": "^3.1.0",
|
||||
"@lit/localize": "^0.11.4",
|
||||
"@open-wc/lit-helpers": "^0.6.0",
|
||||
"@patternfly/elements": "^2.4.0",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@sentry/browser": "^7.75.1",
|
||||
"@sentry/tracing": "^7.75.1",
|
||||
"@sentry/browser": "^7.80.0",
|
||||
"@sentry/tracing": "^7.80.0",
|
||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"chart.js": "^4.4.0",
|
||||
"chartjs-adapter-moment": "^1.0.1",
|
||||
"codemirror": "^6.0.1",
|
||||
"construct-style-sheets-polyfill": "^3.1.0",
|
||||
"core-js": "^3.33.1",
|
||||
"core-js": "^3.33.2",
|
||||
"country-flag-icons": "^1.5.7",
|
||||
"fuse.js": "^7.0.0",
|
||||
"lit": "^2.8.0",
|
||||
"mermaid": "^10.6.0",
|
||||
"mermaid": "^10.6.1",
|
||||
"rapidoc": "^9.3.4",
|
||||
"style-mod": "^4.1.0",
|
||||
"webcomponent-qr-code": "^1.2.0",
|
||||
"yaml": "^2.3.3"
|
||||
"yaml": "^2.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.2",
|
||||
"@babel/core": "^7.23.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.23.2",
|
||||
"@babel/plugin-transform-private-methods": "^7.22.5",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.22.11",
|
||||
"@babel/plugin-transform-runtime": "^7.23.2",
|
||||
"@babel/preset-env": "^7.23.2",
|
||||
"@babel/preset-typescript": "^7.23.2",
|
||||
"@babel/plugin-proposal-decorators": "^7.23.3",
|
||||
"@babel/plugin-transform-private-methods": "^7.23.3",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.23.3",
|
||||
"@babel/plugin-transform-runtime": "^7.23.3",
|
||||
"@babel/preset-env": "^7.23.3",
|
||||
"@babel/preset-typescript": "^7.23.3",
|
||||
"@hcaptcha/types": "^1.0.3",
|
||||
"@jackfranklin/rollup-plugin-markdown": "^0.4.0",
|
||||
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
|
||||
"@lit/localize-tools": "^0.7.0",
|
||||
"@lit/localize-tools": "^0.7.1",
|
||||
"@rollup/plugin-babel": "^6.0.4",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-replace": "^5.0.4",
|
||||
"@rollup/plugin-replace": "^5.0.5",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@rollup/plugin-typescript": "^11.1.5",
|
||||
"@storybook/addon-essentials": "^7.5.1",
|
||||
"@storybook/addon-links": "^7.5.1",
|
||||
"@storybook/addon-essentials": "^7.5.3",
|
||||
"@storybook/addon-links": "^7.5.3",
|
||||
"@storybook/blocks": "^7.1.1",
|
||||
"@storybook/web-components": "^7.5.1",
|
||||
"@storybook/web-components-vite": "^7.5.1",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.2.1",
|
||||
"@types/chart.js": "^2.9.39",
|
||||
"@types/codemirror": "5.60.12",
|
||||
"@types/grecaptcha": "^3.0.6",
|
||||
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
||||
"@typescript-eslint/parser": "^6.9.0",
|
||||
"@storybook/web-components": "^7.5.3",
|
||||
"@storybook/web-components-vite": "^7.5.3",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/chart.js": "^2.9.40",
|
||||
"@types/codemirror": "5.60.13",
|
||||
"@types/grecaptcha": "^3.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.10.0",
|
||||
"@typescript-eslint/parser": "^6.10.0",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"babel-plugin-tsconfig-paths": "^1.0.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.52.0",
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.8",
|
||||
"eslint-plugin-lit": "^1.10.1",
|
||||
"eslint-plugin-sonarjs": "^0.21.0",
|
||||
"eslint-plugin-sonarjs": "^0.23.0",
|
||||
"eslint-plugin-storybook": "^0.6.15",
|
||||
"lit-analyzer": "^2.0.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.0.3",
|
||||
"prettier": "^3.1.0",
|
||||
"pseudolocale": "^2.0.0",
|
||||
"pyright": "^1.1.333",
|
||||
"pyright": "^1.1.335",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"rollup": "^4.1.4",
|
||||
"rollup": "^4.4.0",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"rollup-plugin-cssimport": "^1.0.3",
|
||||
"rollup-plugin-postcss-lit": "^2.1.0",
|
||||
"storybook": "^7.5.1",
|
||||
"storybook": "^7.5.3",
|
||||
"storybook-addon-mock": "^4.3.0",
|
||||
"ts-lit-plugin": "^2.0.0",
|
||||
"ts-lit-plugin": "^2.0.1",
|
||||
"tslib": "^2.6.2",
|
||||
"turnstile-types": "^1.1.3",
|
||||
"typescript": "^5.2.2",
|
||||
|
|
|
@ -54,6 +54,7 @@ export class DashboardUserPage extends AKElement {
|
|||
context__model__app: "authentik_core",
|
||||
context__model__model_name: "user",
|
||||
}}
|
||||
label=${msg("Users created")}
|
||||
>
|
||||
</ak-charts-admin-model-per-day>
|
||||
</ak-aggregate-card>
|
||||
|
@ -66,7 +67,10 @@ export class DashboardUserPage extends AKElement {
|
|||
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-6-col-on-2xl big-graph-container"
|
||||
>
|
||||
<ak-aggregate-card header=${msg("Logins per day in the last month")}>
|
||||
<ak-charts-admin-model-per-day action=${EventActions.Login}>
|
||||
<ak-charts-admin-model-per-day
|
||||
action=${EventActions.Login}
|
||||
label=${msg("Logins")}
|
||||
>
|
||||
</ak-charts-admin-model-per-day>
|
||||
</ak-aggregate-card>
|
||||
</div>
|
||||
|
@ -74,7 +78,10 @@ export class DashboardUserPage extends AKElement {
|
|||
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-6-col-on-2xl big-graph-container"
|
||||
>
|
||||
<ak-aggregate-card header=${msg("Failed Logins per day in the last month")}>
|
||||
<ak-charts-admin-model-per-day action=${EventActions.LoginFailed}>
|
||||
<ak-charts-admin-model-per-day
|
||||
action=${EventActions.LoginFailed}
|
||||
label=${msg("Failed logins")}
|
||||
>
|
||||
</ak-charts-admin-model-per-day>
|
||||
</ak-aggregate-card>
|
||||
</div>
|
||||
|
|
|
@ -12,6 +12,9 @@ export class AdminModelPerDay extends AKChart<Coordinate[]> {
|
|||
@property()
|
||||
action: EventActions = EventActions.ModelCreated;
|
||||
|
||||
@property()
|
||||
label?: string;
|
||||
|
||||
@property({ attribute: false })
|
||||
query?: { [key: string]: unknown } | undefined;
|
||||
|
||||
|
@ -33,7 +36,7 @@ export class AdminModelPerDay extends AKChart<Coordinate[]> {
|
|||
return {
|
||||
datasets: [
|
||||
{
|
||||
label: msg("Objects created"),
|
||||
label: this.label || msg("Objects created"),
|
||||
backgroundColor: "rgba(189, 229, 184, .5)",
|
||||
spanGaps: true,
|
||||
data:
|
||||
|
|
|
@ -44,11 +44,11 @@ export class LDAPSyncStatusChart extends AKChart<SyncStatus[]> {
|
|||
await Promise.all(
|
||||
sources.results.map(async (element) => {
|
||||
try {
|
||||
const health = await api.sourcesLdapSyncStatusList({
|
||||
const health = await api.sourcesLdapSyncStatusRetrieve({
|
||||
slug: element.slug,
|
||||
});
|
||||
|
||||
health.forEach((task) => {
|
||||
health.tasks.forEach((task) => {
|
||||
if (task.status !== TaskStatusEnum.Successful) {
|
||||
metrics.failed += 1;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ export class LDAPSyncStatusChart extends AKChart<SyncStatus[]> {
|
|||
metrics.healthy += 1;
|
||||
}
|
||||
});
|
||||
if (health.length < 1) {
|
||||
if (health.tasks.length < 1) {
|
||||
metrics.unsynced += 1;
|
||||
}
|
||||
} catch {
|
||||
|
|
|
@ -116,7 +116,7 @@ export class ApplicationForm extends ModelForm<Application, string> {
|
|||
return app;
|
||||
}
|
||||
|
||||
handleConfirmBackchannelProviders({ items }: { items: Provider[] }) {
|
||||
handleConfirmBackchannelProviders(items: Provider[]) {
|
||||
this.backchannelProviders = items;
|
||||
this.requestUpdate();
|
||||
return Promise.resolve();
|
||||
|
|
|
@ -63,7 +63,7 @@ export class AkBackchannelProvidersInput extends AKElement {
|
|||
return html`
|
||||
<ak-form-element-horizontal label=${this.label} name=${name}>
|
||||
<div class="pf-c-input-group">
|
||||
<ak-provider-select-table ?backchannelOnly=${true} .confirm=${confirm}>
|
||||
<ak-provider-select-table ?backchannelOnly=${true} .confirm=${this.confirm}>
|
||||
<button slot="trigger" class="pf-c-button pf-m-control" type="button">
|
||||
${this.tooltip ? this.tooltip : nothing}
|
||||
<i class="fas fa-plus" aria-hidden="true"></i>
|
||||
|
|
|
@ -334,13 +334,14 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
|
|||
)}
|
||||
>
|
||||
</ak-radio-input>
|
||||
<ak-switch-input name="includeClaimsInIdToken">
|
||||
<ak-switch-input
|
||||
name="includeClaimsInIdToken"
|
||||
label=${msg("Include claims in id_token")}
|
||||
?checked=${first(provider?.includeClaimsInIdToken, true)}
|
||||
help=${msg(
|
||||
"Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.",
|
||||
)}></ak-switch-input
|
||||
>
|
||||
)}
|
||||
></ak-switch-input>
|
||||
<ak-radio-input
|
||||
name="issuerMode"
|
||||
label=${msg("Issuer mode")}
|
||||
|
|
50
web/src/admin/sources/ldap/LDAPSourceConnectivity.ts
Normal file
50
web/src/admin/sources/ldap/LDAPSourceConnectivity.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { AKElement } from "@goauthentik/app/elements/Base";
|
||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import PFList from "@patternfly/patternfly/components/List/list.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
@customElement("ak-source-ldap-connectivity")
|
||||
export class LDAPSourceConnectivity extends AKElement {
|
||||
@property()
|
||||
connectivity?: {
|
||||
[key: string]: {
|
||||
[key: string]: string;
|
||||
};
|
||||
};
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFList];
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
if (!this.connectivity) {
|
||||
return html``;
|
||||
}
|
||||
return html`<ul class="pf-c-list">
|
||||
${Object.keys(this.connectivity).map((serverKey) => {
|
||||
let serverLabel = html`${serverKey}`;
|
||||
if (serverKey === "__all__") {
|
||||
serverLabel = html`<b>${msg("Global status")}</b>`;
|
||||
}
|
||||
const server = this.connectivity![serverKey];
|
||||
const content = html`${serverLabel}: ${server.status}`;
|
||||
let tooltip = html`${content}`;
|
||||
if (server.status === "ok") {
|
||||
tooltip = html`<pf-tooltip position="top">
|
||||
<ul slot="content" class="pf-c-list">
|
||||
<li>${msg("Vendor")}: ${server.vendor}</li>
|
||||
<li>${msg("Version")}: ${server.version}</li>
|
||||
</ul>
|
||||
${content}
|
||||
</pf-tooltip>`;
|
||||
}
|
||||
return html`<li>${tooltip}</li>`;
|
||||
})}
|
||||
</ul>`;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import "@goauthentik/admin/sources/ldap/LDAPSourceConnectivity";
|
||||
import "@goauthentik/admin/sources/ldap/LDAPSourceForm";
|
||||
import "@goauthentik/app/elements/rbac/ObjectPermissionsPage";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
|
@ -25,9 +26,9 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
|||
|
||||
import {
|
||||
LDAPSource,
|
||||
LDAPSyncStatus,
|
||||
RbacPermissionsAssignedByUsersListModelEnum,
|
||||
SourcesApi,
|
||||
Task,
|
||||
TaskStatusEnum,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
|
@ -48,7 +49,7 @@ export class LDAPSourceViewPage extends AKElement {
|
|||
source!: LDAPSource;
|
||||
|
||||
@state()
|
||||
syncState: Task[] = [];
|
||||
syncState?: LDAPSyncStatus;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFPage, PFButton, PFGrid, PFContent, PFCard, PFDescriptionList, PFList];
|
||||
|
@ -62,6 +63,51 @@ export class LDAPSourceViewPage extends AKElement {
|
|||
});
|
||||
}
|
||||
|
||||
renderSyncStatus(): TemplateResult {
|
||||
if (!this.syncState) {
|
||||
return html`${msg("No sync status.")}`;
|
||||
}
|
||||
if (this.syncState.isRunning) {
|
||||
return html`${msg("Sync currently running.")}`;
|
||||
}
|
||||
if (this.syncState.tasks.length < 1) {
|
||||
return html`${msg("Not synced yet.")}`;
|
||||
}
|
||||
return html`
|
||||
<ul class="pf-c-list">
|
||||
${this.syncState.tasks.map((task) => {
|
||||
let header = "";
|
||||
if (task.status === TaskStatusEnum.Warning) {
|
||||
header = msg("Task finished with warnings");
|
||||
} else if (task.status === TaskStatusEnum.Error) {
|
||||
header = msg("Task finished with errors");
|
||||
} else {
|
||||
header = msg(str`Last sync: ${task.taskFinishTimestamp.toLocaleString()}`);
|
||||
}
|
||||
return html`<li>
|
||||
<p>${task.taskName}</p>
|
||||
<ul class="pf-c-list">
|
||||
<li>${header}</li>
|
||||
${task.messages.map((m) => {
|
||||
return html`<li>${m}</li>`;
|
||||
})}
|
||||
</ul>
|
||||
</li> `;
|
||||
})}
|
||||
</ul>
|
||||
`;
|
||||
}
|
||||
|
||||
load(): void {
|
||||
new SourcesApi(DEFAULT_CONFIG)
|
||||
.sourcesLdapSyncRetrieve({
|
||||
slug: this.source.slug,
|
||||
})
|
||||
.then((state) => {
|
||||
this.syncState = state;
|
||||
});
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
if (!this.source) {
|
||||
return html``;
|
||||
|
@ -72,13 +118,7 @@ export class LDAPSourceViewPage extends AKElement {
|
|||
data-tab-title="${msg("Overview")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
@activate=${() => {
|
||||
new SourcesApi(DEFAULT_CONFIG)
|
||||
.sourcesLdapSyncStatusList({
|
||||
slug: this.source.slug,
|
||||
})
|
||||
.then((state) => {
|
||||
this.syncState = state;
|
||||
});
|
||||
this.load();
|
||||
}}
|
||||
>
|
||||
<div class="pf-l-grid pf-m-gutter">
|
||||
|
@ -137,47 +177,29 @@ export class LDAPSourceViewPage extends AKElement {
|
|||
</ak-forms-modal>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
|
||||
<div class="pf-c-card pf-l-grid__item pf-m-2-col">
|
||||
<div class="pf-c-card__title">
|
||||
<p>${msg("Connectivity")}</p>
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
<ak-source-ldap-connectivity
|
||||
.connectivity=${this.source.connectivity}
|
||||
></ak-source-ldap-connectivity>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-card pf-l-grid__item pf-m-10-col">
|
||||
<div class="pf-c-card__title">
|
||||
<p>${msg("Sync status")}</p>
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
${this.syncState.length < 1
|
||||
? html`<p>${msg("Not synced yet.")}</p>`
|
||||
: html`
|
||||
<ul class="pf-c-list">
|
||||
${this.syncState.map((task) => {
|
||||
let header = "";
|
||||
if (task.status === TaskStatusEnum.Warning) {
|
||||
header = msg("Task finished with warnings");
|
||||
} else if (task.status === TaskStatusEnum.Error) {
|
||||
header = msg("Task finished with errors");
|
||||
} else {
|
||||
header = msg(
|
||||
str`Last sync: ${task.taskFinishTimestamp.toLocaleString()}`,
|
||||
);
|
||||
}
|
||||
return html`<li>
|
||||
<p>${task.taskName}</p>
|
||||
<ul class="pf-c-list">
|
||||
<li>${header}</li>
|
||||
${task.messages.map((m) => {
|
||||
return html`<li>${m}</li>`;
|
||||
})}
|
||||
</ul>
|
||||
</li> `;
|
||||
})}
|
||||
</ul>
|
||||
`}
|
||||
</div>
|
||||
<div class="pf-c-card__body">${this.renderSyncStatus()}</div>
|
||||
<div class="pf-c-card__footer">
|
||||
<ak-action-button
|
||||
class="pf-m-secondary"
|
||||
?disabled=${this.syncState?.isRunning}
|
||||
.apiRequest=${() => {
|
||||
return new SourcesApi(DEFAULT_CONFIG)
|
||||
.sourcesLdapPartialUpdate({
|
||||
.sourcesLdapSyncCreate({
|
||||
slug: this.source?.slug || "",
|
||||
patchedLDAPSourceRequest: this.source,
|
||||
})
|
||||
.then(() => {
|
||||
this.dispatchEvent(
|
||||
|
@ -186,6 +208,7 @@ export class LDAPSourceViewPage extends AKElement {
|
|||
composed: true,
|
||||
}),
|
||||
);
|
||||
this.load();
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -386,6 +386,7 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
|
|||
class="pf-c-form-control"
|
||||
required
|
||||
/>
|
||||
<p class="pf-c-form__helper-text">${msg("Also known as Client ID.")}</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
label=${msg("Consumer secret")}
|
||||
|
@ -394,6 +395,7 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
|
|||
name="consumerSecret"
|
||||
>
|
||||
<textarea class="pf-c-form-control"></textarea>
|
||||
<p class="pf-c-form__helper-text">${msg("Also known as Client Secret.")}</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal label=${msg("Scopes")} name="additionalScopes">
|
||||
<input
|
||||
|
|
|
@ -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.10.2";
|
||||
export const VERSION = "2023.10.3";
|
||||
export const TITLE_DEFAULT = "authentik";
|
||||
export const ROUTE_SEPARATOR = ";";
|
||||
|
||||
|
|
|
@ -39,9 +39,8 @@ const container = (testItem: TemplateResult) =>
|
|||
export const NumberInput = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const displayChange = (ev: any) => {
|
||||
document.getElementById(
|
||||
"number-message-pad",
|
||||
)!.innerText = `Value selected: ${JSON.stringify(ev.target.value, null, 2)}`;
|
||||
document.getElementById("number-message-pad")!.innerText =
|
||||
`Value selected: ${JSON.stringify(ev.target.value, null, 2)}`;
|
||||
};
|
||||
|
||||
return container(
|
||||
|
|
|
@ -46,9 +46,8 @@ export const SwitchInput = () => {
|
|||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const displayChange = (ev: any) => {
|
||||
document.getElementById(
|
||||
"switch-message-pad",
|
||||
)!.innerText = `Value selected: ${JSON.stringify(ev.target.checked, null, 2)}`;
|
||||
document.getElementById("switch-message-pad")!.innerText =
|
||||
`Value selected: ${JSON.stringify(ev.target.checked, null, 2)}`;
|
||||
};
|
||||
|
||||
return container(
|
||||
|
|
|
@ -39,9 +39,8 @@ const container = (testItem: TemplateResult) =>
|
|||
export const TextareaInput = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const displayChange = (ev: any) => {
|
||||
document.getElementById(
|
||||
"textarea-message-pad",
|
||||
)!.innerText = `Value selected: ${JSON.stringify(ev.target.value, null, 2)}`;
|
||||
document.getElementById("textarea-message-pad")!.innerText =
|
||||
`Value selected: ${JSON.stringify(ev.target.value, null, 2)}`;
|
||||
};
|
||||
|
||||
return container(
|
||||
|
|
|
@ -54,9 +54,8 @@ const testOptions = [
|
|||
export const ToggleGroup = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const displayChange = (ev: any) => {
|
||||
document.getElementById(
|
||||
"toggle-message-pad",
|
||||
)!.innerText = `Value selected: ${ev.detail.value}`;
|
||||
document.getElementById("toggle-message-pad")!.innerText =
|
||||
`Value selected: ${ev.detail.value}`;
|
||||
};
|
||||
|
||||
return container(
|
||||
|
|
|
@ -5,6 +5,7 @@ import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter";
|
|||
|
||||
import { Task, TaskStatus } from "@lit-labs/task";
|
||||
import { css, html } from "lit";
|
||||
import { property } from "lit/decorators.js";
|
||||
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFSpinner from "@patternfly/patternfly/components/Spinner/spinner.css";
|
||||
|
@ -57,6 +58,9 @@ export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
|
|||
|
||||
actionTask: Task;
|
||||
|
||||
@property({ type: Boolean })
|
||||
disabled = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.onSuccess = this.onSuccess.bind(this);
|
||||
|
@ -121,6 +125,7 @@ export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
|
|||
part="spinner-button"
|
||||
class="pf-c-button pf-m-progress ${this.buttonClasses}"
|
||||
@click=${this.onClick}
|
||||
?disabled=${this.disabled}
|
||||
>
|
||||
${this.actionTask.render({ pending: () => this.spinner })}
|
||||
<slot></slot>
|
||||
|
|
|
@ -80,11 +80,12 @@ export class IdentificationStage extends BaseStage<
|
|||
}
|
||||
|
||||
createHelperForm(): void {
|
||||
const compatMode = "ShadyDOM" in window;
|
||||
this.form = document.createElement("form");
|
||||
document.documentElement.appendChild(this.form);
|
||||
// Only add the additional username input if we're in a shadow dom
|
||||
// otherwise it just confuses browsers
|
||||
if (!("ShadyDOM" in window)) {
|
||||
if (!compatMode) {
|
||||
// This is a workaround for the fact that we're in a shadow dom
|
||||
// adapted from https://github.com/home-assistant/frontend/issues/3133
|
||||
const username = document.createElement("input");
|
||||
|
@ -104,6 +105,8 @@ export class IdentificationStage extends BaseStage<
|
|||
};
|
||||
this.form.appendChild(username);
|
||||
}
|
||||
// Only add the password field when we don't already show a password field
|
||||
if (!compatMode && !this.challenge.passwordFields) {
|
||||
const password = document.createElement("input");
|
||||
password.setAttribute("type", "password");
|
||||
password.setAttribute("name", "password");
|
||||
|
@ -128,6 +131,7 @@ export class IdentificationStage extends BaseStage<
|
|||
});
|
||||
};
|
||||
this.form.appendChild(password);
|
||||
}
|
||||
const totp = document.createElement("input");
|
||||
totp.setAttribute("type", "text");
|
||||
totp.setAttribute("name", "code");
|
||||
|
|
|
@ -6037,6 +6037,12 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
</trans-unit>
|
||||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -6318,6 +6318,12 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
</trans-unit>
|
||||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -5952,6 +5952,12 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
</trans-unit>
|
||||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0"?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<?xml version="1.0" ?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file target-language="fr" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="s4caed5b7a7e5d89b">
|
||||
|
@ -613,9 +613,9 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="saa0e2675da69651b">
|
||||
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
|
||||
<target>L'URL "
|
||||
<x id="0" equiv-text="${this.url}"/>" n'a pas été trouvée.</target>
|
||||
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
|
||||
<target>L'URL "
|
||||
<x id="0" equiv-text="${this.url}"/>" n'a pas été trouvée.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s58cd9c2fe836d9c6">
|
||||
|
@ -1057,8 +1057,8 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="sa8384c9c26731f83">
|
||||
<source>To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.</source>
|
||||
<target>Pour permettre n'importe quelle URI de redirection, définissez cette valeur sur ".*". Soyez conscient des possibles implications de sécurité que cela peut avoir.</target>
|
||||
<source>To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.</source>
|
||||
<target>Pour permettre n'importe quelle URI de redirection, définissez cette valeur sur ".*". Soyez conscient des possibles implications de sécurité que cela peut avoir.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s55787f4dfcdce52b">
|
||||
|
@ -1630,7 +1630,7 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
|
|||
</trans-unit>
|
||||
<trans-unit id="s33ed903c210a6209">
|
||||
<source>Token to authenticate with. Currently only bearer authentication is supported.</source>
|
||||
<target>Jeton d'authentification à utiliser. Actuellement, seule l'authentification "bearer authentication" est prise en charge.</target>
|
||||
<target>Jeton d'authentification à utiliser. Actuellement, seule l'authentification "bearer authentication" est prise en charge.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sfc8bb104e2c05af8">
|
||||
|
@ -1798,8 +1798,8 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="sa90b7809586c35ce">
|
||||
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
|
||||
<target>Entrez une URL complète, un chemin relatif ou utilisez 'fa://fa-test' pour utiliser l'icône Font Awesome "fa-test".</target>
|
||||
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
|
||||
<target>Entrez une URL complète, un chemin relatif ou utilisez 'fa://fa-test' pour utiliser l'icône Font Awesome "fa-test".</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s0410779cb47de312">
|
||||
|
@ -2922,7 +2922,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
</trans-unit>
|
||||
<trans-unit id="s33683c3b1dbaf264">
|
||||
<source>To use SSL instead, use 'ldaps://' and disable this option.</source>
|
||||
<target>Pour utiliser SSL à la base, utilisez "ldaps://" et désactviez cette option.</target>
|
||||
<target>Pour utiliser SSL à la base, utilisez "ldaps://" et désactviez cette option.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s2221fef80f4753a2">
|
||||
|
@ -3011,8 +3011,8 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s76768bebabb7d543">
|
||||
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
|
||||
<target>Champ qui contient les membres d'un groupe. Si vous utilisez le champ "memberUid", la valeur est censée contenir un nom distinctif relatif, par exemple 'memberUid=un-utilisateur' au lieu de 'memberUid=cn=un-utilisateur,ou=groups,...'</target>
|
||||
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
|
||||
<target>Champ qui contient les membres d'un groupe. Si vous utilisez le champ "memberUid", la valeur est censée contenir un nom distinctif relatif, par exemple 'memberUid=un-utilisateur' au lieu de 'memberUid=cn=un-utilisateur,ou=groups,...'</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s026555347e589f0e">
|
||||
|
@ -3307,7 +3307,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
</trans-unit>
|
||||
<trans-unit id="s3198c384c2f68b08">
|
||||
<source>Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually.</source>
|
||||
<target>Moment où les utilisateurs temporaires doivent être supprimés. Cela ne s'applique que si votre IDP utilise le format NameID "transient" et que l'utilisateur ne se déconnecte pas manuellement.</target>
|
||||
<target>Moment où les utilisateurs temporaires doivent être supprimés. Cela ne s'applique que si votre IDP utilise le format NameID "transient" et que l'utilisateur ne se déconnecte pas manuellement.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sb32e9c1faa0b8673">
|
||||
|
@ -3475,7 +3475,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
</trans-unit>
|
||||
<trans-unit id="s9f8aac89fe318acc">
|
||||
<source>Optionally set the 'FriendlyName' value of the Assertion attribute.</source>
|
||||
<target>Indiquer la valeur "FriendlyName" de l'attribut d'assertion (optionnel)</target>
|
||||
<target>Indiquer la valeur "FriendlyName" de l'attribut d'assertion (optionnel)</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s851c108679653d2a">
|
||||
|
@ -3804,8 +3804,8 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s7b1fba26d245cb1c">
|
||||
<source>When using an external logging solution for archiving, this can be set to "minutes=5".</source>
|
||||
<target>En cas d'utilisation d'une solution de journalisation externe pour l'archivage, cette valeur peut être fixée à "minutes=5".</target>
|
||||
<source>When using an external logging solution for archiving, this can be set to "minutes=5".</source>
|
||||
<target>En cas d'utilisation d'une solution de journalisation externe pour l'archivage, cette valeur peut être fixée à "minutes=5".</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s44536d20bb5c8257">
|
||||
|
@ -3814,8 +3814,8 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s3bb51cabb02b997e">
|
||||
<source>Format: "weeks=3;days=2;hours=3,seconds=2".</source>
|
||||
<target>Format : "weeks=3;days=2;hours=3,seconds=2".</target>
|
||||
<source>Format: "weeks=3;days=2;hours=3,seconds=2".</source>
|
||||
<target>Format : "weeks=3;days=2;hours=3,seconds=2".</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s04bfd02201db5ab8">
|
||||
|
@ -4011,10 +4011,10 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="sa95a538bfbb86111">
|
||||
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source>
|
||||
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source>
|
||||
<target>Êtes-vous sûr de vouloir mettre à jour
|
||||
<x id="0" equiv-text="${this.objectLabel}"/>"
|
||||
<x id="1" equiv-text="${this.obj?.name}"/>" ?</target>
|
||||
<x id="0" equiv-text="${this.objectLabel}"/>"
|
||||
<x id="1" equiv-text="${this.obj?.name}"/>" ?</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sc92d7cfb6ee1fec6">
|
||||
|
@ -5100,8 +5100,8 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="sdf1d8edef27236f0">
|
||||
<source>A "roaming" authenticator, like a YubiKey</source>
|
||||
<target>Un authentificateur "itinérant", comme une YubiKey</target>
|
||||
<source>A "roaming" authenticator, like a YubiKey</source>
|
||||
<target>Un authentificateur "itinérant", comme une YubiKey</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sfffba7b23d8fb40c">
|
||||
|
@ -5426,7 +5426,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
</trans-unit>
|
||||
<trans-unit id="s5170f9ef331949c0">
|
||||
<source>Show arbitrary input fields to the user, for example during enrollment. Data is saved in the flow context under the 'prompt_data' variable.</source>
|
||||
<target>Afficher des champs de saisie arbitraires à l'utilisateur, par exemple pendant l'inscription. Les données sont enregistrées dans le contexte du flux sous la variable "prompt_data".</target>
|
||||
<target>Afficher des champs de saisie arbitraires à l'utilisateur, par exemple pendant l'inscription. Les données sont enregistrées dans le contexte du flux sous la variable "prompt_data".</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s36cb242ac90353bc">
|
||||
|
@ -5435,10 +5435,10 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d5f69929bb7221d">
|
||||
<source><x id="0" equiv-text="${prompt.name}"/> ("<x id="1" equiv-text="${prompt.fieldKey}"/>", of type <x id="2" equiv-text="${prompt.type}"/>)</source>
|
||||
<source><x id="0" equiv-text="${prompt.name}"/> ("<x id="1" equiv-text="${prompt.fieldKey}"/>", of type <x id="2" equiv-text="${prompt.type}"/>)</source>
|
||||
<target>
|
||||
<x id="0" equiv-text="${prompt.name}"/>("
|
||||
<x id="1" equiv-text="${prompt.fieldKey}"/>", de type
|
||||
<x id="0" equiv-text="${prompt.name}"/>("
|
||||
<x id="1" equiv-text="${prompt.fieldKey}"/>", de type
|
||||
<x id="2" equiv-text="${prompt.type}"/>)</target>
|
||||
|
||||
</trans-unit>
|
||||
|
@ -5487,8 +5487,8 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s1608b2f94fa0dbd4">
|
||||
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source>
|
||||
<target>Si défini à une durée supérieure à 0, l'utilisateur aura la possibilité de choisir de "rester connecté", ce qui prolongera sa session jusqu'à la durée spécifiée ici.</target>
|
||||
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source>
|
||||
<target>Si défini à une durée supérieure à 0, l'utilisateur aura la possibilité de choisir de "rester connecté", ce qui prolongera sa session jusqu'à la durée spécifiée ici.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s542a71bb8f41e057">
|
||||
|
@ -6272,7 +6272,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
|
|||
</trans-unit>
|
||||
<trans-unit id="sa7fcf026bd25f231">
|
||||
<source>Can be in the format of 'unix://' when connecting to a local docker daemon, using 'ssh://' to connect via SSH, or 'https://:2376' when connecting to a remote system.</source>
|
||||
<target>Peut être au format "unix://" pour une connexion à un service docker local, "ssh://" pour une connexion via SSH, ou "https://:2376" pour une connexion à un système distant.</target>
|
||||
<target>Peut être au format "unix://" pour une connexion à un service docker local, "ssh://" pour une connexion via SSH, ou "https://:2376" pour une connexion à un système distant.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="saf1d289e3137c2ea">
|
||||
|
@ -7579,7 +7579,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
|
|||
</trans-unit>
|
||||
<trans-unit id="sff0ac1ace2d90709">
|
||||
<source>Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a managed outpost, this is done for you).</source>
|
||||
<target>Utilisez ce fournisseur avec l'option "auth_request" de Nginx ou "forwardAuth" de Traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, "/outpost.goauthentik.io" doit être routé vers le poste avancé (lorsque vous utilisez un poste avancé géré, cela est fait pour vous).</target>
|
||||
<target>Utilisez ce fournisseur avec l'option "auth_request" de Nginx ou "forwardAuth" de Traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, "/outpost.goauthentik.io" doit être routé vers le poste avancé (lorsque vous utilisez un poste avancé géré, cela est fait pour vous).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="scb58b8a60cad8762">
|
||||
<source>Default relay state</source>
|
||||
|
@ -7597,6 +7597,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
|
|||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Étape de configuration d'un authentificateur WebAuthn (Yubikey, FaceID/Windows Hello).</target>
|
||||
</trans-unit>
|
||||
<<<<<<< HEAD
|
||||
<trans-unit id="s1cffe58249b04669">
|
||||
<source>Internal application name used in URLs.</source>
|
||||
<target>Nom de l'application interne utilisé dans les URLs.</target>
|
||||
|
@ -7923,17 +7924,29 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
|
|||
<source><No name set></source>
|
||||
<target><No name set></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc9a6ad1af30572c">
|
||||
<source>For nginx's auth_request or traefik's forwardAuth</source>
|
||||
<target>Pour nginx auth_request ou traefik forwardAuth</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfc31264ef7ff86ef">
|
||||
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
|
||||
<target>Pour nginx auth_request ou traefik forwardAuth par domaine racine</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc615309d10a9228c">
|
||||
<source>RBAC is in preview.</source>
|
||||
<target>RBAC est en aperçu,</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
<target>Type d'utilisateur pour les utilisateurs nouvellement créés.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
<target>Utilisateurs créés</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
<target>Connexions échouées</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -6160,6 +6160,12 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
</trans-unit>
|
||||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -7848,4 +7848,10 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
</trans-unit>
|
||||
</body></file></xliff>
|
||||
|
|
|
@ -5945,6 +5945,12 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
</trans-unit>
|
||||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -7941,6 +7941,14 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
<target>新创建用户使用的用户类型。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
<target>已创建用户</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
<target>失败登录</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -5993,6 +5993,12 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
</trans-unit>
|
||||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -7941,6 +7941,14 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
<trans-unit id="s32babfed740fd3c1">
|
||||
<source>User type used for newly created users.</source>
|
||||
<target>新创建用户使用的用户类型。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4a34a6be4c68ec87">
|
||||
<source>Users created</source>
|
||||
<target>已创建用户</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s275c956687e2e656">
|
||||
<source>Failed logins</source>
|
||||
<target>失败登录</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue