Compare commits
	
		
			91 Commits
		
	
	
		
			version/20
			...
			version/20
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 49dfb4756e | |||
| 814758e2aa | |||
| 5c42dac5e2 | |||
| 88603fa4f7 | |||
| 0232c4e162 | |||
| 11753c1fe1 | |||
| f5cc6c67ec | |||
| 8b8ed3527a | |||
| 1aa0274e7c | |||
| ecd33ca0c1 | |||
| e93be0de9a | |||
| a5adc4f8ed | |||
| a6baed9753 | |||
| ceaf832e63 | |||
| a6b0b14685 | |||
| f679250edd | |||
| acc4de2235 | |||
| 56a8276dbf | |||
| 6dfe6edbef | |||
| 6af4bd0d9a | |||
| 7ee7f6bd6a | |||
| f8b8334010 | |||
| d4b65dc4b4 | |||
| e4bbd3b1c0 | |||
| 87de5e625d | |||
| efbe51673e | |||
| a95bea53ea | |||
| 6021fc0f52 | |||
| 1415b68ff4 | |||
| be6853ac52 | |||
| 7fd6be5abb | |||
| 91d6f572a5 | |||
| 016a9ce34e | |||
| 8adb95af7f | |||
| 1dc54775d8 | |||
| 370ef716b5 | |||
| 16e56ad9ca | |||
| b5b5a9eed3 | |||
| 8b22e7bcc3 | |||
| d48b5b9511 | |||
| 0eccaa3f1e | |||
| 67d550a80d | |||
| ebb5711c32 | |||
| 79ec872232 | |||
| 4284e14ff7 | |||
| 92a09779d0 | |||
| 14c621631d | |||
| c55f503b9b | |||
| a908cad976 | |||
| c2586557d8 | |||
| 01c80a82e2 | |||
| 0d47654651 | |||
| 1183095833 | |||
| c281b11bdc | |||
| 61fe45a58c | |||
| d43aab479c | |||
| 7f8383427a | |||
| a06d6cf33d | |||
| 5b7cb205c9 | |||
| 293a932d20 | |||
| fff901ff03 | |||
| f47c936295 | |||
| 88d5aec618 | |||
| 96ae68cf09 | |||
| 63b3434b6f | |||
| 947ecec02b | |||
| 1c2b452406 | |||
| 47777529ac | |||
| 949095c376 | |||
| 4b112c2799 | |||
| 291a2516b1 | |||
| 4dcfd021e2 | |||
| ca50848db3 | |||
| 0bb3e3c558 | |||
| e4b25809ab | |||
| 7bf932f8e2 | |||
| 99d04528b0 | |||
| e48d172036 | |||
| c2388137a8 | |||
| 650e2cbc38 | |||
| b32800ea71 | |||
| e1c0c0b20c | |||
| fe39e39dcd | |||
| 883f213b03 | |||
| 538996f617 | |||
| 2f4c92deb9 | |||
| ef335ec083 | |||
| 07b09df3fe | |||
| e70e031a1f | |||
| c7ba183dc0 | |||
| 3ed23a37ea | 
| @ -1,5 +1,5 @@ | |||||||
| [bumpversion] | [bumpversion] | ||||||
| current_version = 2022.1.2 | current_version = 2022.1.4 | ||||||
| tag = True | tag = True | ||||||
| commit = True | commit = True | ||||||
| parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*) | parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*) | ||||||
|  | |||||||
							
								
								
									
										16
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							| @ -30,9 +30,25 @@ jobs: | |||||||
|             -w /app \ |             -w /app \ | ||||||
|             golangci/golangci-lint:v1.43 \ |             golangci/golangci-lint:v1.43 \ | ||||||
|             golangci-lint run -v --timeout 200s |             golangci-lint run -v --timeout 200s | ||||||
|  |   test-unittest: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@v2 | ||||||
|  |       - uses: actions/setup-go@v2 | ||||||
|  |         with: | ||||||
|  |           go-version: "^1.17" | ||||||
|  |       - name: Get dependencies | ||||||
|  |         run: | | ||||||
|  |           go get github.com/axw/gocov/gocov | ||||||
|  |           go get github.com/AlekSi/gocov-xml | ||||||
|  |           go get github.com/jstemmer/go-junit-report | ||||||
|  |       - name: Go unittests | ||||||
|  |         run: | | ||||||
|  |           go test -timeout 0 -v -race -coverprofile=coverage.out -covermode=atomic -cover ./... | go-junit-report > junit.xml | ||||||
|   ci-outpost-mark: |   ci-outpost-mark: | ||||||
|     needs: |     needs: | ||||||
|       - lint-golint |       - lint-golint | ||||||
|  |       - test-unittest | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - run: echo mark |       - run: echo mark | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								.github/workflows/release-publish.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.github/workflows/release-publish.yml
									
									
									
									
										vendored
									
									
								
							| @ -30,14 +30,14 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           push: ${{ github.event_name == 'release' }} |           push: ${{ github.event_name == 'release' }} | ||||||
|           tags: | |           tags: | | ||||||
|             beryju/authentik:2022.1.2, |             beryju/authentik:2022.1.4, | ||||||
|             beryju/authentik:latest, |             beryju/authentik:latest, | ||||||
|             ghcr.io/goauthentik/server:2022.1.2, |             ghcr.io/goauthentik/server:2022.1.4, | ||||||
|             ghcr.io/goauthentik/server:latest |             ghcr.io/goauthentik/server:latest | ||||||
|           platforms: linux/amd64,linux/arm64 |           platforms: linux/amd64,linux/arm64 | ||||||
|           context: . |           context: . | ||||||
|       - name: Building Docker Image (stable) |       - name: Building Docker Image (stable) | ||||||
|         if: ${{ github.event_name == 'release' && !contains('2022.1.2', 'rc') }} |         if: ${{ github.event_name == 'release' && !contains('2022.1.4', 'rc') }} | ||||||
|         run: | |         run: | | ||||||
|           docker pull beryju/authentik:latest |           docker pull beryju/authentik:latest | ||||||
|           docker tag beryju/authentik:latest beryju/authentik:stable |           docker tag beryju/authentik:latest beryju/authentik:stable | ||||||
| @ -78,14 +78,14 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           push: ${{ github.event_name == 'release' }} |           push: ${{ github.event_name == 'release' }} | ||||||
|           tags: | |           tags: | | ||||||
|             beryju/authentik-${{ matrix.type }}:2022.1.2, |             beryju/authentik-${{ matrix.type }}:2022.1.4, | ||||||
|             beryju/authentik-${{ matrix.type }}:latest, |             beryju/authentik-${{ matrix.type }}:latest, | ||||||
|             ghcr.io/goauthentik/${{ matrix.type }}:2022.1.2, |             ghcr.io/goauthentik/${{ matrix.type }}:2022.1.4, | ||||||
|             ghcr.io/goauthentik/${{ matrix.type }}:latest |             ghcr.io/goauthentik/${{ matrix.type }}:latest | ||||||
|           file: ${{ matrix.type }}.Dockerfile |           file: ${{ matrix.type }}.Dockerfile | ||||||
|           platforms: linux/amd64,linux/arm64 |           platforms: linux/amd64,linux/arm64 | ||||||
|       - name: Building Docker Image (stable) |       - name: Building Docker Image (stable) | ||||||
|         if: ${{ github.event_name == 'release' && !contains('2022.1.2', 'rc') }} |         if: ${{ github.event_name == 'release' && !contains('2022.1.4', 'rc') }} | ||||||
|         run: | |         run: | | ||||||
|           docker pull beryju/authentik-${{ matrix.type }}:latest |           docker pull beryju/authentik-${{ matrix.type }}:latest | ||||||
|           docker tag beryju/authentik-${{ matrix.type }}:latest beryju/authentik-${{ matrix.type }}:stable |           docker tag beryju/authentik-${{ matrix.type }}:latest beryju/authentik-${{ matrix.type }}:stable | ||||||
| @ -170,7 +170,7 @@ jobs: | |||||||
|           SENTRY_PROJECT: authentik |           SENTRY_PROJECT: authentik | ||||||
|           SENTRY_URL: https://sentry.beryju.org |           SENTRY_URL: https://sentry.beryju.org | ||||||
|         with: |         with: | ||||||
|           version: authentik@2022.1.2 |           version: authentik@2022.1.4 | ||||||
|           environment: beryjuorg-prod |           environment: beryjuorg-prod | ||||||
|           sourcemaps: './web/dist' |           sourcemaps: './web/dist' | ||||||
|           url_prefix: '~/static/dist' |           url_prefix: '~/static/dist' | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
									
									
									
									
								
							| @ -15,6 +15,9 @@ test-e2e-provider: | |||||||
| test-e2e-rest: | test-e2e-rest: | ||||||
| 	coverage run manage.py test tests/e2e/test_flows* tests/e2e/test_source* | 	coverage run manage.py test tests/e2e/test_flows* tests/e2e/test_source* | ||||||
|  |  | ||||||
|  | test-go: | ||||||
|  | 	go test -timeout 0 -v -race -cover ./... | ||||||
|  |  | ||||||
| test: | test: | ||||||
| 	coverage run manage.py test authentik | 	coverage run manage.py test authentik | ||||||
| 	coverage html | 	coverage html | ||||||
|  | |||||||
| @ -57,4 +57,4 @@ DigitalOcean provides development and testing resources for authentik. | |||||||
|     </a> |     </a> | ||||||
| </p> | </p> | ||||||
|  |  | ||||||
| Netlify hosts the [goauthentik.io](goauthentik.io) site. | Netlify hosts the [goauthentik.io](https://goauthentik.io) site. | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
| from os import environ | from os import environ | ||||||
| from typing import Optional | from typing import Optional | ||||||
|  |  | ||||||
| __version__ = "2022.1.2" | __version__ = "2022.1.4" | ||||||
| ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" | ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ from typing import Any | |||||||
|  |  | ||||||
| from django_filters.rest_framework import DjangoFilterBackend | from django_filters.rest_framework import DjangoFilterBackend | ||||||
| from drf_spectacular.utils import OpenApiResponse, extend_schema | from drf_spectacular.utils import OpenApiResponse, extend_schema | ||||||
| from guardian.shortcuts import get_anonymous_user | from guardian.shortcuts import assign_perm, get_anonymous_user | ||||||
| from rest_framework.decorators import action | from rest_framework.decorators import action | ||||||
| from rest_framework.exceptions import ValidationError | from rest_framework.exceptions import ValidationError | ||||||
| from rest_framework.fields import CharField | from rest_framework.fields import CharField | ||||||
| @ -95,10 +95,12 @@ class TokenViewSet(UsedByMixin, ModelViewSet): | |||||||
|  |  | ||||||
|     def perform_create(self, serializer: TokenSerializer): |     def perform_create(self, serializer: TokenSerializer): | ||||||
|         if not self.request.user.is_superuser: |         if not self.request.user.is_superuser: | ||||||
|             return serializer.save( |             instance = serializer.save( | ||||||
|                 user=self.request.user, |                 user=self.request.user, | ||||||
|                 expiring=self.request.user.attributes.get(USER_ATTRIBUTE_TOKEN_EXPIRING, True), |                 expiring=self.request.user.attributes.get(USER_ATTRIBUTE_TOKEN_EXPIRING, True), | ||||||
|             ) |             ) | ||||||
|  |             assign_perm("authentik_core.view_token_key", self.request.user, instance) | ||||||
|  |             return instance | ||||||
|         return super().perform_create(serializer) |         return super().perform_create(serializer) | ||||||
|  |  | ||||||
|     @permission_required("authentik_core.view_token_key") |     @permission_required("authentik_core.view_token_key") | ||||||
|  | |||||||
| @ -30,6 +30,7 @@ class TestTokenAPI(APITestCase): | |||||||
|         self.assertEqual(token.user, self.user) |         self.assertEqual(token.user, self.user) | ||||||
|         self.assertEqual(token.intent, TokenIntents.INTENT_API) |         self.assertEqual(token.intent, TokenIntents.INTENT_API) | ||||||
|         self.assertEqual(token.expiring, True) |         self.assertEqual(token.expiring, True) | ||||||
|  |         self.assertTrue(self.user.has_perm("authentik_core.view_token_key", token)) | ||||||
|  |  | ||||||
|     def test_token_create_invalid(self): |     def test_token_create_invalid(self): | ||||||
|         """Test token creation endpoint (invalid data)""" |         """Test token creation endpoint (invalid data)""" | ||||||
|  | |||||||
| @ -32,6 +32,7 @@ class BaseEvaluator: | |||||||
|         self._globals = { |         self._globals = { | ||||||
|             "regex_match": BaseEvaluator.expr_regex_match, |             "regex_match": BaseEvaluator.expr_regex_match, | ||||||
|             "regex_replace": BaseEvaluator.expr_regex_replace, |             "regex_replace": BaseEvaluator.expr_regex_replace, | ||||||
|  |             "list_flatten": BaseEvaluator.expr_flatten, | ||||||
|             "ak_is_group_member": BaseEvaluator.expr_is_group_member, |             "ak_is_group_member": BaseEvaluator.expr_is_group_member, | ||||||
|             "ak_user_by": BaseEvaluator.expr_user_by, |             "ak_user_by": BaseEvaluator.expr_user_by, | ||||||
|             "ak_logger": get_logger(), |             "ak_logger": get_logger(), | ||||||
| @ -40,6 +41,15 @@ class BaseEvaluator: | |||||||
|         self._context = {} |         self._context = {} | ||||||
|         self._filename = "BaseEvalautor" |         self._filename = "BaseEvalautor" | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def expr_flatten(value: list[Any] | Any) -> Optional[Any]: | ||||||
|  |         """Flatten `value` if its a list""" | ||||||
|  |         if isinstance(value, list): | ||||||
|  |             if len(value) < 1: | ||||||
|  |                 return None | ||||||
|  |             return value[0] | ||||||
|  |         return value | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def expr_regex_match(value: Any, regex: str) -> bool: |     def expr_regex_match(value: Any, regex: str) -> bool: | ||||||
|         """Expression Filter to run re.search""" |         """Expression Filter to run re.search""" | ||||||
|  | |||||||
| @ -23,12 +23,12 @@ class ProxyDockerController(DockerController): | |||||||
|             proxy_provider: ProxyProvider |             proxy_provider: ProxyProvider | ||||||
|             external_host_name = urlparse(proxy_provider.external_host) |             external_host_name = urlparse(proxy_provider.external_host) | ||||||
|             hosts.append(f"`{external_host_name.netloc}`") |             hosts.append(f"`{external_host_name.netloc}`") | ||||||
|         traefik_name = f"ak-outpost-{self.outpost.pk.hex}" |         traefik_name = self.name | ||||||
|         labels = super()._get_labels() |         labels = super()._get_labels() | ||||||
|         labels["traefik.enable"] = "true" |         labels["traefik.enable"] = "true" | ||||||
|         labels[ |         labels[ | ||||||
|             f"traefik.http.routers.{traefik_name}-router.rule" |             f"traefik.http.routers.{traefik_name}-router.rule" | ||||||
|         ] = f"Host({','.join(hosts)}) && PathPrefix('/akprox')" |         ] = f"Host({','.join(hosts)}) && PathPrefix(`/akprox`)" | ||||||
|         labels[f"traefik.http.routers.{traefik_name}-router.tls"] = "true" |         labels[f"traefik.http.routers.{traefik_name}-router.tls"] = "true" | ||||||
|         labels[f"traefik.http.routers.{traefik_name}-router.service"] = f"{traefik_name}-service" |         labels[f"traefik.http.routers.{traefik_name}-router.service"] = f"{traefik_name}-service" | ||||||
|         labels[ |         labels[ | ||||||
|  | |||||||
| @ -1,14 +1,4 @@ | |||||||
| """ | """root settings for authentik""" | ||||||
| Django settings for authentik project. |  | ||||||
|  |  | ||||||
| Generated by 'django-admin startproject' using Django 2.1.3. |  | ||||||
|  |  | ||||||
| For more information on this file, see |  | ||||||
| https://docs.djangoproject.com/en/2.1/topics/settings/ |  | ||||||
|  |  | ||||||
| For the full list of settings and their values, see |  | ||||||
| https://docs.djangoproject.com/en/2.1/ref/settings/ |  | ||||||
| """ |  | ||||||
|  |  | ||||||
| import importlib | import importlib | ||||||
| import logging | import logging | ||||||
| @ -18,24 +8,22 @@ from hashlib import sha512 | |||||||
| from json import dumps | from json import dumps | ||||||
| from tempfile import gettempdir | from tempfile import gettempdir | ||||||
| from time import time | from time import time | ||||||
| from urllib.parse import quote | from urllib.parse import quote_plus | ||||||
|  |  | ||||||
| import structlog | import structlog | ||||||
| from celery.schedules import crontab | from celery.schedules import crontab | ||||||
| from sentry_sdk import init as sentry_init | from sentry_sdk import init as sentry_init | ||||||
| from sentry_sdk.api import set_tag | from sentry_sdk.api import set_tag | ||||||
| from sentry_sdk.integrations.boto3 import Boto3Integration |  | ||||||
| from sentry_sdk.integrations.celery import CeleryIntegration | from sentry_sdk.integrations.celery import CeleryIntegration | ||||||
| from sentry_sdk.integrations.django import DjangoIntegration | from sentry_sdk.integrations.django import DjangoIntegration | ||||||
| from sentry_sdk.integrations.redis import RedisIntegration | from sentry_sdk.integrations.redis import RedisIntegration | ||||||
| from sentry_sdk.integrations.threading import ThreadingIntegration | from sentry_sdk.integrations.threading import ThreadingIntegration | ||||||
|  |  | ||||||
| from authentik import ENV_GIT_HASH_KEY, __version__, get_build_hash, get_full_version | from authentik import ENV_GIT_HASH_KEY, __version__, get_build_hash | ||||||
| from authentik.core.middleware import structlog_add_request_id | from authentik.core.middleware import structlog_add_request_id | ||||||
| from authentik.lib.config import CONFIG | from authentik.lib.config import CONFIG | ||||||
| from authentik.lib.logging import add_process_id | from authentik.lib.logging import add_process_id | ||||||
| from authentik.lib.sentry import before_send | from authentik.lib.sentry import before_send | ||||||
| from authentik.lib.utils.http import get_http_session |  | ||||||
| from authentik.lib.utils.reflection import get_env | from authentik.lib.utils.reflection import get_env | ||||||
| from authentik.stages.password import BACKEND_APP_PASSWORD, BACKEND_INBUILT, BACKEND_LDAP | from authentik.stages.password import BACKEND_APP_PASSWORD, BACKEND_INBUILT, BACKEND_LDAP | ||||||
|  |  | ||||||
| @ -220,7 +208,7 @@ if CONFIG.y_bool("redis.tls", False): | |||||||
|     REDIS_CELERY_TLS_REQUIREMENTS = f"?ssl_cert_reqs={CONFIG.y('redis.tls_reqs')}" |     REDIS_CELERY_TLS_REQUIREMENTS = f"?ssl_cert_reqs={CONFIG.y('redis.tls_reqs')}" | ||||||
| _redis_url = ( | _redis_url = ( | ||||||
|     f"{REDIS_PROTOCOL_PREFIX}:" |     f"{REDIS_PROTOCOL_PREFIX}:" | ||||||
|     f"{quote(CONFIG.y('redis.password'))}@{quote(CONFIG.y('redis.host'))}:" |     f"{quote_plus(CONFIG.y('redis.password'))}@{quote_plus(CONFIG.y('redis.host'))}:" | ||||||
|     f"{int(CONFIG.y('redis.port'))}" |     f"{int(CONFIG.y('redis.port'))}" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @ -347,6 +335,7 @@ LOCALE_PATHS = ["./locale"] | |||||||
| # Celery settings | # Celery settings | ||||||
| # Add a 10 minute timeout to all Celery tasks. | # Add a 10 minute timeout to all Celery tasks. | ||||||
| CELERY_TASK_SOFT_TIME_LIMIT = 600 | CELERY_TASK_SOFT_TIME_LIMIT = 600 | ||||||
|  | CELERY_WORKER_MAX_TASKS_PER_CHILD = 50 | ||||||
| CELERY_BEAT_SCHEDULE = { | CELERY_BEAT_SCHEDULE = { | ||||||
|     "clean_expired_models": { |     "clean_expired_models": { | ||||||
|         "task": "authentik.core.tasks.clean_expired_models", |         "task": "authentik.core.tasks.clean_expired_models", | ||||||
| @ -407,7 +396,6 @@ if _ERROR_REPORTING: | |||||||
|             DjangoIntegration(transaction_style="function_name"), |             DjangoIntegration(transaction_style="function_name"), | ||||||
|             CeleryIntegration(), |             CeleryIntegration(), | ||||||
|             RedisIntegration(), |             RedisIntegration(), | ||||||
|             Boto3Integration(), |  | ||||||
|             ThreadingIntegration(propagate_hub=True), |             ThreadingIntegration(propagate_hub=True), | ||||||
|         ], |         ], | ||||||
|         before_send=before_send, |         before_send=before_send, | ||||||
| @ -424,29 +412,6 @@ if _ERROR_REPORTING: | |||||||
|         "Error reporting is enabled", |         "Error reporting is enabled", | ||||||
|         env=CONFIG.y("error_reporting.environment", "customer"), |         env=CONFIG.y("error_reporting.environment", "customer"), | ||||||
|     ) |     ) | ||||||
| if not CONFIG.y_bool("disable_startup_analytics", False): |  | ||||||
|     should_send = env not in ["dev", "ci"] |  | ||||||
|     if should_send: |  | ||||||
|         try: |  | ||||||
|             get_http_session().post( |  | ||||||
|                 "https://goauthentik.io/api/event", |  | ||||||
|                 json={ |  | ||||||
|                     "domain": "authentik", |  | ||||||
|                     "name": "pageview", |  | ||||||
|                     "referrer": get_full_version(), |  | ||||||
|                     "url": ( |  | ||||||
|                         f"http://localhost/{env}?utm_source={get_full_version()}&utm_medium={env}" |  | ||||||
|                     ), |  | ||||||
|                 }, |  | ||||||
|                 headers={ |  | ||||||
|                     "User-Agent": sha512(str(SECRET_KEY).encode("ascii")).hexdigest()[:16], |  | ||||||
|                     "Content-Type": "application/json", |  | ||||||
|                 }, |  | ||||||
|                 timeout=5, |  | ||||||
|             ) |  | ||||||
|         # pylint: disable=bare-except |  | ||||||
|         except:  # nosec |  | ||||||
|             pass |  | ||||||
|  |  | ||||||
| # Static files (CSS, JavaScript, Images) | # Static files (CSS, JavaScript, Images) | ||||||
| # https://docs.djangoproject.com/en/2.1/howto/static-files/ | # https://docs.djangoproject.com/en/2.1/howto/static-files/ | ||||||
|  | |||||||
| @ -35,21 +35,21 @@ class LDAPProviderManager(ObjectManager): | |||||||
|                 "goauthentik.io/sources/ldap/ms-userprincipalname", |                 "goauthentik.io/sources/ldap/ms-userprincipalname", | ||||||
|                 name="authentik default Active Directory Mapping: userPrincipalName", |                 name="authentik default Active Directory Mapping: userPrincipalName", | ||||||
|                 object_field="attributes.upn", |                 object_field="attributes.upn", | ||||||
|                 expression="return ldap.get('userPrincipalName')", |                 expression="return list_flatten(ldap.get('userPrincipalName'))", | ||||||
|             ), |             ), | ||||||
|             EnsureExists( |             EnsureExists( | ||||||
|                 LDAPPropertyMapping, |                 LDAPPropertyMapping, | ||||||
|                 "goauthentik.io/sources/ldap/ms-givenName", |                 "goauthentik.io/sources/ldap/ms-givenName", | ||||||
|                 name="authentik default Active Directory Mapping: givenName", |                 name="authentik default Active Directory Mapping: givenName", | ||||||
|                 object_field="attributes.givenName", |                 object_field="attributes.givenName", | ||||||
|                 expression="return ldap.get('givenName')", |                 expression="return list_flatten(ldap.get('givenName'))", | ||||||
|             ), |             ), | ||||||
|             EnsureExists( |             EnsureExists( | ||||||
|                 LDAPPropertyMapping, |                 LDAPPropertyMapping, | ||||||
|                 "goauthentik.io/sources/ldap/ms-sn", |                 "goauthentik.io/sources/ldap/ms-sn", | ||||||
|                 name="authentik default Active Directory Mapping: sn", |                 name="authentik default Active Directory Mapping: sn", | ||||||
|                 object_field="attributes.sn", |                 object_field="attributes.sn", | ||||||
|                 expression="return ldap.get('sn')", |                 expression="return list_flatten(ldap.get('sn'))", | ||||||
|             ), |             ), | ||||||
|             # OpenLDAP specific mappings |             # OpenLDAP specific mappings | ||||||
|             EnsureExists( |             EnsureExists( | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ import ( | |||||||
| 	log "github.com/sirupsen/logrus" | 	log "github.com/sirupsen/logrus" | ||||||
|  |  | ||||||
| 	"goauthentik.io/internal/common" | 	"goauthentik.io/internal/common" | ||||||
|  | 	"goauthentik.io/internal/debug" | ||||||
| 	"goauthentik.io/internal/outpost/ak" | 	"goauthentik.io/internal/outpost/ak" | ||||||
| 	"goauthentik.io/internal/outpost/ldap" | 	"goauthentik.io/internal/outpost/ldap" | ||||||
| ) | ) | ||||||
| @ -27,6 +28,7 @@ func main() { | |||||||
| 			log.FieldKeyTime: "timestamp", | 			log.FieldKeyTime: "timestamp", | ||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
|  | 	go debug.EnableDebugServer() | ||||||
| 	akURL, found := os.LookupEnv("AUTHENTIK_HOST") | 	akURL, found := os.LookupEnv("AUTHENTIK_HOST") | ||||||
| 	if !found { | 	if !found { | ||||||
| 		fmt.Println("env AUTHENTIK_HOST not set!") | 		fmt.Println("env AUTHENTIK_HOST not set!") | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ import ( | |||||||
| 	log "github.com/sirupsen/logrus" | 	log "github.com/sirupsen/logrus" | ||||||
|  |  | ||||||
| 	"goauthentik.io/internal/common" | 	"goauthentik.io/internal/common" | ||||||
|  | 	"goauthentik.io/internal/debug" | ||||||
| 	"goauthentik.io/internal/outpost/ak" | 	"goauthentik.io/internal/outpost/ak" | ||||||
| 	"goauthentik.io/internal/outpost/proxyv2" | 	"goauthentik.io/internal/outpost/proxyv2" | ||||||
| ) | ) | ||||||
| @ -32,6 +33,7 @@ func main() { | |||||||
| 			log.FieldKeyTime: "timestamp", | 			log.FieldKeyTime: "timestamp", | ||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
|  | 	go debug.EnableDebugServer() | ||||||
| 	akURL, found := os.LookupEnv("AUTHENTIK_HOST") | 	akURL, found := os.LookupEnv("AUTHENTIK_HOST") | ||||||
| 	if !found { | 	if !found { | ||||||
| 		fmt.Println("env AUTHENTIK_HOST not set!") | 		fmt.Println("env AUTHENTIK_HOST not set!") | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ import ( | |||||||
| 	"goauthentik.io/internal/common" | 	"goauthentik.io/internal/common" | ||||||
| 	"goauthentik.io/internal/config" | 	"goauthentik.io/internal/config" | ||||||
| 	"goauthentik.io/internal/constants" | 	"goauthentik.io/internal/constants" | ||||||
|  | 	"goauthentik.io/internal/debug" | ||||||
| 	"goauthentik.io/internal/gounicorn" | 	"goauthentik.io/internal/gounicorn" | ||||||
| 	"goauthentik.io/internal/outpost/ak" | 	"goauthentik.io/internal/outpost/ak" | ||||||
| 	"goauthentik.io/internal/outpost/proxyv2" | 	"goauthentik.io/internal/outpost/proxyv2" | ||||||
| @ -28,6 +29,7 @@ func main() { | |||||||
| 			log.FieldKeyTime: "timestamp", | 			log.FieldKeyTime: "timestamp", | ||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
|  | 	go debug.EnableDebugServer() | ||||||
| 	l := log.WithField("logger", "authentik.root") | 	l := log.WithField("logger", "authentik.root") | ||||||
| 	config.DefaultConfig() | 	config.DefaultConfig() | ||||||
| 	err := config.LoadConfig("./authentik/lib/default.yml") | 	err := config.LoadConfig("./authentik/lib/default.yml") | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ services: | |||||||
|     image: redis:alpine |     image: redis:alpine | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|   server: |   server: | ||||||
|     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.1.2} |     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.1.4} | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     command: server |     command: server | ||||||
|     environment: |     environment: | ||||||
| @ -38,7 +38,7 @@ services: | |||||||
|       - "0.0.0.0:${AUTHENTIK_PORT_HTTP:-9000}:9000" |       - "0.0.0.0:${AUTHENTIK_PORT_HTTP:-9000}:9000" | ||||||
|       - "0.0.0.0:${AUTHENTIK_PORT_HTTPS:-9443}:9443" |       - "0.0.0.0:${AUTHENTIK_PORT_HTTPS:-9443}:9443" | ||||||
|   worker: |   worker: | ||||||
|     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.1.2} |     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.1.4} | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     command: worker |     command: worker | ||||||
|     environment: |     environment: | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.mod
									
									
									
									
									
								
							| @ -9,7 +9,7 @@ require ( | |||||||
| 	github.com/garyburd/redigo v1.6.2 // indirect | 	github.com/garyburd/redigo v1.6.2 // indirect | ||||||
| 	github.com/getsentry/sentry-go v0.12.0 | 	github.com/getsentry/sentry-go v0.12.0 | ||||||
| 	github.com/go-ldap/ldap/v3 v3.4.1 | 	github.com/go-ldap/ldap/v3 v3.4.1 | ||||||
| 	github.com/go-openapi/runtime v0.21.1 | 	github.com/go-openapi/runtime v0.22.0 | ||||||
| 	github.com/go-openapi/strfmt v0.21.1 | 	github.com/go-openapi/strfmt v0.21.1 | ||||||
| 	github.com/golang-jwt/jwt v3.2.2+incompatible | 	github.com/golang-jwt/jwt v3.2.2+incompatible | ||||||
| 	github.com/google/uuid v1.3.0 | 	github.com/google/uuid v1.3.0 | ||||||
| @ -25,8 +25,10 @@ require ( | |||||||
| 	github.com/pires/go-proxyproto v0.6.1 | 	github.com/pires/go-proxyproto v0.6.1 | ||||||
| 	github.com/pkg/errors v0.9.1 | 	github.com/pkg/errors v0.9.1 | ||||||
| 	github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac // indirect | 	github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac // indirect | ||||||
| 	github.com/prometheus/client_golang v1.12.0 | 	github.com/prometheus/client_golang v1.12.1 | ||||||
|  | 	github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b | ||||||
| 	github.com/sirupsen/logrus v1.8.1 | 	github.com/sirupsen/logrus v1.8.1 | ||||||
|  | 	github.com/stretchr/testify v1.7.0 | ||||||
| 	goauthentik.io/api v0.2021125.1 | 	goauthentik.io/api v0.2021125.1 | ||||||
| 	golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c | 	golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c | ||||||
| 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c | 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								go.sum
									
									
									
									
									
								
							| @ -183,8 +183,8 @@ github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29g | |||||||
| github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= | github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= | ||||||
| github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= | github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= | ||||||
| github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= | github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= | ||||||
| github.com/go-openapi/runtime v0.21.1 h1:/KIG00BzA2x2HRStX2tnhbqbQdPcFlkgsYCiNY20FZs= | github.com/go-openapi/runtime v0.22.0 h1:vY2D0u807kkcwidaj0YJuq4zyAWQnjLNDpJcVBrUFNs= | ||||||
| github.com/go-openapi/runtime v0.21.1/go.mod h1:aQg+kaIQEn+A2CRSY1TxbM8+sT9g2V3aLc1FbIAnbbs= | github.com/go-openapi/runtime v0.22.0/go.mod h1:aQg+kaIQEn+A2CRSY1TxbM8+sT9g2V3aLc1FbIAnbbs= | ||||||
| github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= | github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= | ||||||
| github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= | github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= | ||||||
| github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= | github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= | ||||||
| @ -471,8 +471,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP | |||||||
| github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= | ||||||
| github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= | github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= | ||||||
| github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= | github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= | ||||||
| github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= | github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= | ||||||
| github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= | github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= | ||||||
| github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | ||||||
| github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | ||||||
| github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | ||||||
| @ -489,6 +489,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O | |||||||
| github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= | github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= | ||||||
| github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= | github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= | ||||||
| github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= | github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= | ||||||
|  | github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b h1:aUNXCGgukb4gtY99imuIeoh8Vr0GSwAlYxPAhqZrpFc= | ||||||
|  | github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg= | ||||||
| github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | 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.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | ||||||
| github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | ||||||
|  | |||||||
| @ -25,4 +25,4 @@ func OutpostUserAgent() string { | |||||||
| 	return fmt.Sprintf("authentik-outpost@%s", FullVersion()) | 	return fmt.Sprintf("authentik-outpost@%s", FullVersion()) | ||||||
| } | } | ||||||
|  |  | ||||||
| const VERSION = "2022.1.2" | const VERSION = "2022.1.4" | ||||||
|  | |||||||
							
								
								
									
										24
									
								
								internal/debug/debug.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								internal/debug/debug.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | package debug | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"net/http/pprof" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  |  | ||||||
|  | 	log "github.com/sirupsen/logrus" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func EnableDebugServer() { | ||||||
|  | 	l := log.WithField("logger", "authentik.go_debugger") | ||||||
|  | 	if deb := os.Getenv("AUTHENTIK_DEBUG"); strings.ToLower(deb) != "true" { | ||||||
|  | 		l.Info("not enabling debug server, set `AUTHENTIK_DEBUG` to `true` to enable it.") | ||||||
|  | 	} | ||||||
|  | 	h := http.NewServeMux() | ||||||
|  | 	h.HandleFunc("/debug/pprof/", pprof.Index) | ||||||
|  | 	h.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) | ||||||
|  | 	h.HandleFunc("/debug/pprof/profile", pprof.Profile) | ||||||
|  | 	h.HandleFunc("/debug/pprof/symbol", pprof.Symbol) | ||||||
|  | 	h.HandleFunc("/debug/pprof/trace", pprof.Trace) | ||||||
|  | 	l.Println(http.ListenAndServe("0.0.0.0:9900", nil)) | ||||||
|  | } | ||||||
							
								
								
									
										66
									
								
								internal/outpost/ak/test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								internal/outpost/ak/test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | |||||||
|  | package ak | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"fmt" | ||||||
|  | 	"math/rand" | ||||||
|  | 	"net/http" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/google/uuid" | ||||||
|  | 	"github.com/gorilla/securecookie" | ||||||
|  | 	log "github.com/sirupsen/logrus" | ||||||
|  | 	"goauthentik.io/api" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestSecret() string { | ||||||
|  | 	return base64.RawURLEncoding.EncodeToString(securecookie.GenerateRandomKey(32)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MockConfig() api.Config { | ||||||
|  | 	return *api.NewConfig( | ||||||
|  | 		*api.NewErrorReportingConfig(false, "test", false, 0.0), | ||||||
|  | 		[]api.CapabilitiesEnum{}, | ||||||
|  | 		100, | ||||||
|  | 		100, | ||||||
|  | 		100, | ||||||
|  | 		100, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func MockAK(outpost api.Outpost, globalConfig api.Config) *APIController { | ||||||
|  | 	config := api.NewConfiguration() | ||||||
|  | 	config.HTTPClient = &http.Client{ | ||||||
|  | 		Transport: GetTLSTransport(), | ||||||
|  | 	} | ||||||
|  | 	token := TestSecret() | ||||||
|  | 	config.AddDefaultHeader("Authorization", fmt.Sprintf("Bearer %s", token)) | ||||||
|  |  | ||||||
|  | 	// create the API client, with the transport | ||||||
|  | 	apiClient := api.NewAPIClient(config) | ||||||
|  |  | ||||||
|  | 	log := log.WithField("logger", "authentik.outpost.ak-api-controller") | ||||||
|  |  | ||||||
|  | 	log.WithField("name", outpost.Name).Debug("Fetched outpost configuration") | ||||||
|  |  | ||||||
|  | 	log.Debug("Fetched global configuration") | ||||||
|  |  | ||||||
|  | 	// doGlobalSetup is called by the OnRefresh handler, which ticks on start | ||||||
|  | 	// doGlobalSetup(outpost, akConfig) | ||||||
|  |  | ||||||
|  | 	ac := &APIController{ | ||||||
|  | 		Client:       apiClient, | ||||||
|  | 		GlobalConfig: globalConfig, | ||||||
|  |  | ||||||
|  | 		token:  token, | ||||||
|  | 		logger: log, | ||||||
|  |  | ||||||
|  | 		reloadOffset:        time.Duration(rand.Intn(10)) * time.Second, | ||||||
|  | 		instanceUUID:        uuid.New(), | ||||||
|  | 		Outpost:             outpost, | ||||||
|  | 		wsBackoffMultiplier: 1, | ||||||
|  | 		refreshHandlers:     make([]func(), 0), | ||||||
|  | 	} | ||||||
|  | 	ac.logger.WithField("offset", ac.reloadOffset.String()).Debug("HA Reload offset") | ||||||
|  | 	return ac | ||||||
|  | } | ||||||
| @ -16,6 +16,7 @@ import ( | |||||||
| 	"goauthentik.io/internal/outpost/ldap/flags" | 	"goauthentik.io/internal/outpost/ldap/flags" | ||||||
| 	"goauthentik.io/internal/outpost/ldap/metrics" | 	"goauthentik.io/internal/outpost/ldap/metrics" | ||||||
| 	"goauthentik.io/internal/outpost/ldap/server" | 	"goauthentik.io/internal/outpost/ldap/server" | ||||||
|  | 	"goauthentik.io/internal/outpost/ldap/utils" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ContextUserKey = "ak_user" | const ContextUserKey = "ak_user" | ||||||
| @ -35,7 +36,7 @@ func NewDirectBinder(si server.LDAPServerInstance) *DirectBinder { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (db *DirectBinder) GetUsername(dn string) (string, error) { | func (db *DirectBinder) GetUsername(dn string) (string, error) { | ||||||
| 	if !strings.HasSuffix(strings.ToLower(dn), strings.ToLower(db.si.GetBaseDN())) { | 	if !utils.HasSuffixNoCase(dn, db.si.GetBaseDN()) { | ||||||
| 		return "", errors.New("invalid base DN") | 		return "", errors.New("invalid base DN") | ||||||
| 	} | 	} | ||||||
| 	dns, err := goldap.ParseDN(dn) | 	dns, err := goldap.ParseDN(dn) | ||||||
|  | |||||||
| @ -140,26 +140,26 @@ func (pi *ProviderInstance) GetNeededObjects(scope int, baseDN string, filterOC | |||||||
| 	// If our requested base DN doesn't match any of the container DNs, then | 	// If our requested base DN doesn't match any of the container DNs, then | ||||||
| 	// we're probably loading a user or group. If it does, then make sure our | 	// we're probably loading a user or group. If it does, then make sure our | ||||||
| 	// scope will eventually take us to users or groups. | 	// scope will eventually take us to users or groups. | ||||||
| 	if (baseDN == pi.BaseDN || strings.HasSuffix(baseDN, pi.UserDN)) && utils.IncludeObjectClass(filterOC, ldapConstants.GetUserOCs()) { | 	if (strings.EqualFold(baseDN, pi.BaseDN) || utils.HasSuffixNoCase(baseDN, pi.UserDN)) && utils.IncludeObjectClass(filterOC, ldapConstants.GetUserOCs()) { | ||||||
| 		if baseDN != pi.UserDN && baseDN != pi.BaseDN || | 		if baseDN != pi.UserDN && baseDN != pi.BaseDN || | ||||||
| 			baseDN == pi.BaseDN && scope > 1 || | 			strings.EqualFold(baseDN, pi.BaseDN) && scope > 1 || | ||||||
| 			baseDN == pi.UserDN && scope > 0 { | 			strings.EqualFold(baseDN, pi.UserDN) && scope > 0 { | ||||||
| 			needUsers = true | 			needUsers = true | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (baseDN == pi.BaseDN || strings.HasSuffix(baseDN, pi.GroupDN)) && utils.IncludeObjectClass(filterOC, ldapConstants.GetGroupOCs()) { | 	if (strings.EqualFold(baseDN, pi.BaseDN) || utils.HasSuffixNoCase(baseDN, pi.GroupDN)) && utils.IncludeObjectClass(filterOC, ldapConstants.GetGroupOCs()) { | ||||||
| 		if baseDN != pi.GroupDN && baseDN != pi.BaseDN || | 		if baseDN != pi.GroupDN && baseDN != pi.BaseDN || | ||||||
| 			baseDN == pi.BaseDN && scope > 1 || | 			strings.EqualFold(baseDN, pi.BaseDN) && scope > 1 || | ||||||
| 			baseDN == pi.GroupDN && scope > 0 { | 			strings.EqualFold(baseDN, pi.GroupDN) && scope > 0 { | ||||||
| 			needGroups = true | 			needGroups = true | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (baseDN == pi.BaseDN || strings.HasSuffix(baseDN, pi.VirtualGroupDN)) && utils.IncludeObjectClass(filterOC, ldapConstants.GetVirtualGroupOCs()) { | 	if (strings.EqualFold(baseDN, pi.BaseDN) || utils.HasSuffixNoCase(baseDN, pi.VirtualGroupDN)) && utils.IncludeObjectClass(filterOC, ldapConstants.GetVirtualGroupOCs()) { | ||||||
| 		if baseDN != pi.VirtualGroupDN && baseDN != pi.BaseDN || | 		if baseDN != pi.VirtualGroupDN && baseDN != pi.BaseDN || | ||||||
| 			baseDN == pi.BaseDN && scope > 1 || | 			strings.EqualFold(baseDN, pi.BaseDN) && scope > 1 || | ||||||
| 			baseDN == pi.VirtualGroupDN && scope > 0 { | 			strings.EqualFold(baseDN, pi.VirtualGroupDN) && scope > 0 { | ||||||
| 			needUsers = true | 			needUsers = true | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -36,7 +36,7 @@ func NewDirectSearcher(si server.LDAPServerInstance) *DirectSearcher { | |||||||
|  |  | ||||||
| func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, error) { | func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, error) { | ||||||
| 	accsp := sentry.StartSpan(req.Context(), "authentik.providers.ldap.search.check_access") | 	accsp := sentry.StartSpan(req.Context(), "authentik.providers.ldap.search.check_access") | ||||||
| 	baseDN := strings.ToLower(ds.si.GetBaseDN()) | 	baseDN := ds.si.GetBaseDN() | ||||||
|  |  | ||||||
| 	filterOC, err := ldap.GetFilterObjectClass(req.Filter) | 	filterOC, err := ldap.GetFilterObjectClass(req.Filter) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -59,7 +59,7 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		}).Inc() | 		}).Inc() | ||||||
| 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN) | 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN) | ||||||
| 	} | 	} | ||||||
| 	if !strings.HasSuffix(req.BindDN, ","+baseDN) { | 	if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) { | ||||||
| 		metrics.RequestsRejected.With(prometheus.Labels{ | 		metrics.RequestsRejected.With(prometheus.Labels{ | ||||||
| 			"outpost_name": ds.si.GetOutpostName(), | 			"outpost_name": ds.si.GetOutpostName(), | ||||||
| 			"type":         "search", | 			"type":         "search", | ||||||
| @ -105,7 +105,7 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 	scope := req.SearchRequest.Scope | 	scope := req.SearchRequest.Scope | ||||||
| 	needUsers, needGroups := ds.si.GetNeededObjects(scope, req.BaseDN, filterOC) | 	needUsers, needGroups := ds.si.GetNeededObjects(scope, req.BaseDN, filterOC) | ||||||
|  |  | ||||||
| 	if scope >= 0 && req.BaseDN == baseDN { | 	if scope >= 0 && strings.EqualFold(req.BaseDN, baseDN) { | ||||||
| 		if utils.IncludeObjectClass(filterOC, constants.GetDomainOCs()) { | 		if utils.IncludeObjectClass(filterOC, constants.GetDomainOCs()) { | ||||||
| 			entries = append(entries, ds.si.GetBaseEntry()) | 			entries = append(entries, ds.si.GetBaseEntry()) | ||||||
| 		} | 		} | ||||||
| @ -209,8 +209,8 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, err | 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if scope >= 0 && (req.BaseDN == ds.si.GetBaseDN() || strings.HasSuffix(req.BaseDN, ds.si.GetBaseUserDN())) { | 	if scope >= 0 && (strings.EqualFold(req.BaseDN, ds.si.GetBaseDN()) || utils.HasSuffixNoCase(req.BaseDN, ds.si.GetBaseUserDN())) { | ||||||
| 		singleu := strings.HasSuffix(req.BaseDN, ","+ds.si.GetBaseUserDN()) | 		singleu := utils.HasSuffixNoCase(req.BaseDN, ","+ds.si.GetBaseUserDN()) | ||||||
|  |  | ||||||
| 		if !singleu && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | 		if !singleu && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | ||||||
| 			entries = append(entries, utils.GetContainerEntry(filterOC, ds.si.GetBaseUserDN(), constants.OUUsers)) | 			entries = append(entries, utils.GetContainerEntry(filterOC, ds.si.GetBaseUserDN(), constants.OUUsers)) | ||||||
| @ -220,7 +220,7 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		if scope >= 0 && users != nil && utils.IncludeObjectClass(filterOC, constants.GetUserOCs()) { | 		if scope >= 0 && users != nil && utils.IncludeObjectClass(filterOC, constants.GetUserOCs()) { | ||||||
| 			for _, u := range *users { | 			for _, u := range *users { | ||||||
| 				entry := ds.si.UserEntry(u) | 				entry := ds.si.UserEntry(u) | ||||||
| 				if req.BaseDN == entry.DN || !singleu { | 				if strings.EqualFold(req.BaseDN, entry.DN) || !singleu { | ||||||
| 					entries = append(entries, entry) | 					entries = append(entries, entry) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -229,8 +229,8 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		scope += 1 // Return the scope to what it was before we descended | 		scope += 1 // Return the scope to what it was before we descended | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if scope >= 0 && (req.BaseDN == ds.si.GetBaseDN() || strings.HasSuffix(req.BaseDN, ds.si.GetBaseGroupDN())) { | 	if scope >= 0 && (strings.EqualFold(req.BaseDN, ds.si.GetBaseDN()) || utils.HasSuffixNoCase(req.BaseDN, ds.si.GetBaseGroupDN())) { | ||||||
| 		singleg := strings.HasSuffix(req.BaseDN, ","+ds.si.GetBaseGroupDN()) | 		singleg := utils.HasSuffixNoCase(req.BaseDN, ","+ds.si.GetBaseGroupDN()) | ||||||
|  |  | ||||||
| 		if !singleg && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | 		if !singleg && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | ||||||
| 			entries = append(entries, utils.GetContainerEntry(filterOC, ds.si.GetBaseGroupDN(), constants.OUGroups)) | 			entries = append(entries, utils.GetContainerEntry(filterOC, ds.si.GetBaseGroupDN(), constants.OUGroups)) | ||||||
| @ -240,7 +240,7 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		if scope >= 0 && groups != nil && utils.IncludeObjectClass(filterOC, constants.GetGroupOCs()) { | 		if scope >= 0 && groups != nil && utils.IncludeObjectClass(filterOC, constants.GetGroupOCs()) { | ||||||
| 			for _, g := range *groups { | 			for _, g := range *groups { | ||||||
| 				entry := group.FromAPIGroup(g, ds.si).Entry() | 				entry := group.FromAPIGroup(g, ds.si).Entry() | ||||||
| 				if req.BaseDN == entry.DN || !singleg { | 				if strings.EqualFold(req.BaseDN, entry.DN) || !singleg { | ||||||
| 					entries = append(entries, entry) | 					entries = append(entries, entry) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -249,8 +249,8 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		scope += 1 // Return the scope to what it was before we descended | 		scope += 1 // Return the scope to what it was before we descended | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if scope >= 0 && (req.BaseDN == ds.si.GetBaseDN() || strings.HasSuffix(req.BaseDN, ds.si.GetBaseVirtualGroupDN())) { | 	if scope >= 0 && (strings.EqualFold(req.BaseDN, ds.si.GetBaseDN()) || utils.HasSuffixNoCase(req.BaseDN, ds.si.GetBaseVirtualGroupDN())) { | ||||||
| 		singlevg := strings.HasSuffix(req.BaseDN, ","+ds.si.GetBaseVirtualGroupDN()) | 		singlevg := utils.HasSuffixNoCase(req.BaseDN, ","+ds.si.GetBaseVirtualGroupDN()) | ||||||
|  |  | ||||||
| 		if !singlevg || utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | 		if !singlevg || utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | ||||||
| 			entries = append(entries, utils.GetContainerEntry(filterOC, ds.si.GetBaseVirtualGroupDN(), constants.OUVirtualGroups)) | 			entries = append(entries, utils.GetContainerEntry(filterOC, ds.si.GetBaseVirtualGroupDN(), constants.OUVirtualGroups)) | ||||||
| @ -260,7 +260,7 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		if scope >= 0 && users != nil && utils.IncludeObjectClass(filterOC, constants.GetVirtualGroupOCs()) { | 		if scope >= 0 && users != nil && utils.IncludeObjectClass(filterOC, constants.GetVirtualGroupOCs()) { | ||||||
| 			for _, u := range *users { | 			for _, u := range *users { | ||||||
| 				entry := group.FromAPIUser(u, ds.si).Entry() | 				entry := group.FromAPIUser(u, ds.si).Entry() | ||||||
| 				if req.BaseDN == entry.DN || !singlevg { | 				if strings.EqualFold(req.BaseDN, entry.DN) || !singlevg { | ||||||
| 					entries = append(entries, entry) | 					entries = append(entries, entry) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ func NewMemorySearcher(si server.LDAPServerInstance) *MemorySearcher { | |||||||
|  |  | ||||||
| func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, error) { | func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, error) { | ||||||
| 	accsp := sentry.StartSpan(req.Context(), "authentik.providers.ldap.search.check_access") | 	accsp := sentry.StartSpan(req.Context(), "authentik.providers.ldap.search.check_access") | ||||||
| 	baseDN := strings.ToLower(ms.si.GetBaseDN()) | 	baseDN := ms.si.GetBaseDN() | ||||||
|  |  | ||||||
| 	filterOC, err := ldap.GetFilterObjectClass(req.Filter) | 	filterOC, err := ldap.GetFilterObjectClass(req.Filter) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -62,7 +62,7 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		}).Inc() | 		}).Inc() | ||||||
| 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN) | 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN) | ||||||
| 	} | 	} | ||||||
| 	if !strings.HasSuffix(req.BindDN, ","+baseDN) { | 	if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) { | ||||||
| 		metrics.RequestsRejected.With(prometheus.Labels{ | 		metrics.RequestsRejected.With(prometheus.Labels{ | ||||||
| 			"outpost_name": ms.si.GetOutpostName(), | 			"outpost_name": ms.si.GetOutpostName(), | ||||||
| 			"type":         "search", | 			"type":         "search", | ||||||
| @ -92,7 +92,7 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 	scope := req.SearchRequest.Scope | 	scope := req.SearchRequest.Scope | ||||||
| 	needUsers, needGroups := ms.si.GetNeededObjects(scope, req.BaseDN, filterOC) | 	needUsers, needGroups := ms.si.GetNeededObjects(scope, req.BaseDN, filterOC) | ||||||
|  |  | ||||||
| 	if scope >= 0 && req.BaseDN == baseDN { | 	if scope >= 0 && strings.EqualFold(req.BaseDN, baseDN) { | ||||||
| 		if utils.IncludeObjectClass(filterOC, constants.GetDomainOCs()) { | 		if utils.IncludeObjectClass(filterOC, constants.GetDomainOCs()) { | ||||||
| 			entries = append(entries, ms.si.GetBaseEntry()) | 			entries = append(entries, ms.si.GetBaseEntry()) | ||||||
| 		} | 		} | ||||||
| @ -155,8 +155,8 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, err | 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if scope >= 0 && (req.BaseDN == ms.si.GetBaseDN() || strings.HasSuffix(req.BaseDN, ms.si.GetBaseUserDN())) { | 	if scope >= 0 && (strings.EqualFold(req.BaseDN, ms.si.GetBaseDN()) || utils.HasSuffixNoCase(req.BaseDN, ms.si.GetBaseUserDN())) { | ||||||
| 		singleu := strings.HasSuffix(req.BaseDN, ","+ms.si.GetBaseUserDN()) | 		singleu := utils.HasSuffixNoCase(req.BaseDN, ","+ms.si.GetBaseUserDN()) | ||||||
|  |  | ||||||
| 		if !singleu && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | 		if !singleu && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | ||||||
| 			entries = append(entries, utils.GetContainerEntry(filterOC, ms.si.GetBaseUserDN(), constants.OUUsers)) | 			entries = append(entries, utils.GetContainerEntry(filterOC, ms.si.GetBaseUserDN(), constants.OUUsers)) | ||||||
| @ -166,7 +166,7 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		if scope >= 0 && users != nil && utils.IncludeObjectClass(filterOC, constants.GetUserOCs()) { | 		if scope >= 0 && users != nil && utils.IncludeObjectClass(filterOC, constants.GetUserOCs()) { | ||||||
| 			for _, u := range *users { | 			for _, u := range *users { | ||||||
| 				entry := ms.si.UserEntry(u) | 				entry := ms.si.UserEntry(u) | ||||||
| 				if req.BaseDN == entry.DN || !singleu { | 				if strings.EqualFold(req.BaseDN, entry.DN) || !singleu { | ||||||
| 					entries = append(entries, entry) | 					entries = append(entries, entry) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -175,8 +175,8 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		scope += 1 // Return the scope to what it was before we descended | 		scope += 1 // Return the scope to what it was before we descended | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if scope >= 0 && (req.BaseDN == ms.si.GetBaseDN() || strings.HasSuffix(req.BaseDN, ms.si.GetBaseGroupDN())) { | 	if scope >= 0 && (strings.EqualFold(req.BaseDN, ms.si.GetBaseDN()) || utils.HasSuffixNoCase(req.BaseDN, ms.si.GetBaseGroupDN())) { | ||||||
| 		singleg := strings.HasSuffix(req.BaseDN, ","+ms.si.GetBaseGroupDN()) | 		singleg := utils.HasSuffixNoCase(req.BaseDN, ","+ms.si.GetBaseGroupDN()) | ||||||
|  |  | ||||||
| 		if !singleg && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | 		if !singleg && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | ||||||
| 			entries = append(entries, utils.GetContainerEntry(filterOC, ms.si.GetBaseGroupDN(), constants.OUGroups)) | 			entries = append(entries, utils.GetContainerEntry(filterOC, ms.si.GetBaseGroupDN(), constants.OUGroups)) | ||||||
| @ -185,7 +185,7 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
|  |  | ||||||
| 		if scope >= 0 && groups != nil && utils.IncludeObjectClass(filterOC, constants.GetGroupOCs()) { | 		if scope >= 0 && groups != nil && utils.IncludeObjectClass(filterOC, constants.GetGroupOCs()) { | ||||||
| 			for _, g := range groups { | 			for _, g := range groups { | ||||||
| 				if req.BaseDN == g.DN || !singleg { | 				if strings.EqualFold(req.BaseDN, g.DN) || !singleg { | ||||||
| 					entries = append(entries, g.Entry()) | 					entries = append(entries, g.Entry()) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -194,8 +194,8 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		scope += 1 // Return the scope to what it was before we descended | 		scope += 1 // Return the scope to what it was before we descended | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if scope >= 0 && (req.BaseDN == ms.si.GetBaseDN() || strings.HasSuffix(req.BaseDN, ms.si.GetBaseVirtualGroupDN())) { | 	if scope >= 0 && (strings.EqualFold(req.BaseDN, ms.si.GetBaseDN()) || utils.HasSuffixNoCase(req.BaseDN, ms.si.GetBaseVirtualGroupDN())) { | ||||||
| 		singlevg := strings.HasSuffix(req.BaseDN, ","+ms.si.GetBaseVirtualGroupDN()) | 		singlevg := utils.HasSuffixNoCase(req.BaseDN, ","+ms.si.GetBaseVirtualGroupDN()) | ||||||
|  |  | ||||||
| 		if !singlevg && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | 		if !singlevg && utils.IncludeObjectClass(filterOC, constants.GetContainerOCs()) { | ||||||
| 			entries = append(entries, utils.GetContainerEntry(filterOC, ms.si.GetBaseVirtualGroupDN(), constants.OUVirtualGroups)) | 			entries = append(entries, utils.GetContainerEntry(filterOC, ms.si.GetBaseVirtualGroupDN(), constants.OUVirtualGroups)) | ||||||
| @ -205,7 +205,7 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, | |||||||
| 		if scope >= 0 && users != nil && utils.IncludeObjectClass(filterOC, constants.GetVirtualGroupOCs()) { | 		if scope >= 0 && users != nil && utils.IncludeObjectClass(filterOC, constants.GetVirtualGroupOCs()) { | ||||||
| 			for _, u := range *users { | 			for _, u := range *users { | ||||||
| 				entry := group.FromAPIUser(u, ms.si).Entry() | 				entry := group.FromAPIUser(u, ms.si).Entry() | ||||||
| 				if req.BaseDN == entry.DN || !singlevg { | 				if strings.EqualFold(req.BaseDN, entry.DN) || !singlevg { | ||||||
| 					entries = append(entries, entry) | 					entries = append(entries, entry) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -26,7 +26,6 @@ type Request struct { | |||||||
| func NewRequest(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (*Request, *sentry.Span) { | func NewRequest(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (*Request, *sentry.Span) { | ||||||
| 	rid := uuid.New().String() | 	rid := uuid.New().String() | ||||||
| 	bindDN = strings.ToLower(bindDN) | 	bindDN = strings.ToLower(bindDN) | ||||||
| 	searchReq.BaseDN = strings.ToLower(searchReq.BaseDN) |  | ||||||
| 	span := sentry.StartSpan(context.TODO(), "authentik.providers.ldap.search", sentry.TransactionName("authentik.providers.ldap.search")) | 	span := sentry.StartSpan(context.TODO(), "authentik.providers.ldap.search", sentry.TransactionName("authentik.providers.ldap.search")) | ||||||
| 	span.Description = fmt.Sprintf("%s (%s)", searchReq.BaseDN, ldap.ScopeMap[searchReq.Scope]) | 	span.Description = fmt.Sprintf("%s (%s)", searchReq.BaseDN, ldap.ScopeMap[searchReq.Scope]) | ||||||
| 	span.SetTag("request_uid", rid) | 	span.SetTag("request_uid", rid) | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ package utils | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"reflect" | 	"reflect" | ||||||
|  | 	"strings" | ||||||
|  |  | ||||||
| 	"github.com/nmcclain/ldap" | 	"github.com/nmcclain/ldap" | ||||||
| 	log "github.com/sirupsen/logrus" | 	log "github.com/sirupsen/logrus" | ||||||
| @ -117,3 +118,7 @@ func GetContainerEntry(filterOC string, dn string, ou string) *ldap.Entry { | |||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func HasSuffixNoCase(s1 string, s2 string) bool { | ||||||
|  | 	return strings.HasSuffix(strings.ToLower(s1), strings.ToLower(s2)) | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,6 +1,8 @@ | |||||||
| package utils | package utils | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"strings" | ||||||
|  |  | ||||||
| 	goldap "github.com/go-ldap/ldap/v3" | 	goldap "github.com/go-ldap/ldap/v3" | ||||||
| 	ber "github.com/nmcclain/asn1-ber" | 	ber "github.com/nmcclain/asn1-ber" | ||||||
| 	"github.com/nmcclain/ldap" | 	"github.com/nmcclain/ldap" | ||||||
| @ -41,7 +43,7 @@ func parseFilterForGroupSingle(req api.ApiCoreGroupsListRequest, f *ber.Packet) | |||||||
| 	// Switch on type of the value, then check the key | 	// Switch on type of the value, then check the key | ||||||
| 	switch vv := v.(type) { | 	switch vv := v.(type) { | ||||||
| 	case string: | 	case string: | ||||||
| 		switch k { | 		switch strings.ToLower(k.(string)) { | ||||||
| 		case "cn": | 		case "cn": | ||||||
| 			return req.Name(vv), false | 			return req.Name(vv), false | ||||||
| 		case "member": | 		case "member": | ||||||
| @ -54,7 +56,7 @@ func parseFilterForGroupSingle(req api.ApiCoreGroupsListRequest, f *ber.Packet) | |||||||
| 			username := userDN.RDNs[0].Attributes[0].Value | 			username := userDN.RDNs[0].Attributes[0].Value | ||||||
| 			// If the DN's first ou is virtual-groups, ignore this filter | 			// If the DN's first ou is virtual-groups, ignore this filter | ||||||
| 			if len(userDN.RDNs) > 1 { | 			if len(userDN.RDNs) > 1 { | ||||||
| 				if userDN.RDNs[1].Attributes[0].Value == constants.OUVirtualGroups || userDN.RDNs[1].Attributes[0].Value == constants.OUGroups { | 				if strings.EqualFold(userDN.RDNs[1].Attributes[0].Value, constants.OUVirtualGroups) || strings.EqualFold(userDN.RDNs[1].Attributes[0].Value, constants.OUGroups) { | ||||||
| 					// Since we know we're not filtering anything, skip this request | 					// Since we know we're not filtering anything, skip this request | ||||||
| 					return req, true | 					return req, true | ||||||
| 				} | 				} | ||||||
|  | |||||||
| @ -46,6 +46,7 @@ type Application struct { | |||||||
|  |  | ||||||
| 	log *log.Entry | 	log *log.Entry | ||||||
| 	mux *mux.Router | 	mux *mux.Router | ||||||
|  | 	ak  *ak.APIController | ||||||
|  |  | ||||||
| 	errorTemplates *template.Template | 	errorTemplates *template.Template | ||||||
| } | } | ||||||
| @ -93,6 +94,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, cs *ak.CryptoStore | |||||||
| 		httpClient:     c, | 		httpClient:     c, | ||||||
| 		mux:            mux, | 		mux:            mux, | ||||||
| 		errorTemplates: templates.GetTemplates(), | 		errorTemplates: templates.GetTemplates(), | ||||||
|  | 		ak:             ak, | ||||||
| 	} | 	} | ||||||
| 	a.sessions = a.getStore(p) | 	a.sessions = a.getStore(p) | ||||||
| 	mux.Use(web.NewLoggingHandler(muxLogger, func(l *log.Entry, r *http.Request) *log.Entry { | 	mux.Use(web.NewLoggingHandler(muxLogger, func(l *log.Entry, r *http.Request) *log.Entry { | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ package application | |||||||
|  |  | ||||||
| type ProxyClaims struct { | type ProxyClaims struct { | ||||||
| 	UserAttributes  map[string]interface{} `json:"user_attributes"` | 	UserAttributes  map[string]interface{} `json:"user_attributes"` | ||||||
|  | 	BackendOverride string                 `json:"backend_override"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type Claims struct { | type Claims struct { | ||||||
|  | |||||||
| @ -1,7 +1,9 @@ | |||||||
| package application | package application | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
| 	"encoding/base64" | 	"encoding/base64" | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| @ -57,7 +59,8 @@ func (a *Application) addHeaders(headers http.Header, c *Claims) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (a *Application) getTraefikForwardUrl(r *http.Request) *url.URL { | // getTraefikForwardUrl See https://doc.traefik.io/traefik/middlewares/forwardauth/ | ||||||
|  | func (a *Application) getTraefikForwardUrl(r *http.Request) (*url.URL, error) { | ||||||
| 	u, err := url.Parse(fmt.Sprintf( | 	u, err := url.Parse(fmt.Sprintf( | ||||||
| 		"%s://%s%s", | 		"%s://%s%s", | ||||||
| 		r.Header.Get("X-Forwarded-Proto"), | 		r.Header.Get("X-Forwarded-Proto"), | ||||||
| @ -65,33 +68,63 @@ func (a *Application) getTraefikForwardUrl(r *http.Request) *url.URL { | |||||||
| 		r.Header.Get("X-Forwarded-Uri"), | 		r.Header.Get("X-Forwarded-Uri"), | ||||||
| 	)) | 	)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		a.log.WithError(err).Warning("Failed to parse URL from traefik") | 		return nil, err | ||||||
| 		return r.URL |  | ||||||
| 	} | 	} | ||||||
| 	a.log.WithField("url", u.String()).Trace("traefik forwarded url") | 	a.log.WithField("url", u.String()).Trace("traefik forwarded url") | ||||||
| 	return u | 	return u, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (a *Application) IsAllowlisted(r *http.Request) bool { | // getNginxForwardUrl See https://github.com/kubernetes/ingress-nginx/blob/main/rootfs/etc/nginx/template/nginx.tmpl | ||||||
| 	url := r.URL | func (a *Application) getNginxForwardUrl(r *http.Request) (*url.URL, error) { | ||||||
| 	// In Forward auth mode, we can't directly match against the requested URL | 	ou := r.Header.Get("X-Original-URI") | ||||||
| 	// Since that would be /akprox/auth/... | 	if ou != "" { | ||||||
| 	if a.Mode() == api.PROXYMODE_FORWARD_SINGLE || a.Mode() == api.PROXYMODE_FORWARD_DOMAIN { | 		// Turn this full URL into a relative URL | ||||||
| 		// For traefik, we can get the Upstream URL from headers | 		u := &url.URL{ | ||||||
| 		// For nginx we can attempt to as well, but it's not guaranteed to work. | 			Host:   "", | ||||||
| 		if strings.HasPrefix(r.URL.Path, "/akprox/auth") { | 			Scheme: "", | ||||||
| 			url = a.getTraefikForwardUrl(r) | 			Path:   ou, | ||||||
| 		} | 		} | ||||||
|  | 		a.log.WithField("url", u.String()).Info("building forward URL from X-Original-URI") | ||||||
|  | 		return u, nil | ||||||
| 	} | 	} | ||||||
| 	for _, u := range a.UnauthenticatedRegex { | 	h := r.Header.Get("X-Original-URL") | ||||||
|  | 	if len(h) < 1 { | ||||||
|  | 		return nil, errors.New("no forward URL found") | ||||||
|  | 	} | ||||||
|  | 	u, err := url.Parse(h) | ||||||
|  | 	if err != nil { | ||||||
|  | 		a.log.WithError(err).Warning("failed to parse URL from nginx") | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	a.log.WithField("url", u.String()).Trace("nginx forwarded url") | ||||||
|  | 	return u, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (a *Application) ReportMisconfiguration(r *http.Request, msg string, fields map[string]interface{}) { | ||||||
|  | 	fields["message"] = msg | ||||||
|  | 	a.log.WithFields(fields).Error("Reporting configuration error") | ||||||
|  | 	req := api.EventRequest{ | ||||||
|  | 		Action:   api.EVENTACTIONS_CONFIGURATION_ERROR, | ||||||
|  | 		App:      "authentik.providers.proxy", // must match python apps.py name | ||||||
|  | 		ClientIp: *api.NewNullableString(api.PtrString(r.RemoteAddr)), | ||||||
|  | 		Context:  &fields, | ||||||
|  | 	} | ||||||
|  | 	_, _, err := a.ak.Client.EventsApi.EventsEventsCreate(context.Background()).EventRequest(req).Execute() | ||||||
|  | 	if err != nil { | ||||||
|  | 		a.log.WithError(err).Warning("failed to report configuration error") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (a *Application) IsAllowlisted(u *url.URL) bool { | ||||||
|  | 	for _, ur := range a.UnauthenticatedRegex { | ||||||
| 		var testString string | 		var testString string | ||||||
| 		if a.Mode() == api.PROXYMODE_PROXY || a.Mode() == api.PROXYMODE_FORWARD_SINGLE { | 		if a.Mode() == api.PROXYMODE_PROXY || a.Mode() == api.PROXYMODE_FORWARD_SINGLE { | ||||||
| 			testString = url.Path | 			testString = u.Path | ||||||
| 		} else { | 		} else { | ||||||
| 			testString = url.String() | 			testString = u.String() | ||||||
| 		} | 		} | ||||||
| 		a.log.WithField("regex", u.String()).WithField("url", testString).Trace("Matching URL against allow list") | 		a.log.WithField("regex", u.String()).WithField("url", testString).Trace("Matching URL against allow list") | ||||||
| 		if u.MatchString(testString) { | 		if ur.MatchString(testString) { | ||||||
| 			return true | 			return true | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -25,13 +25,27 @@ func (a *Application) configureForward() error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Request) { | func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Request) { | ||||||
|  | 	a.log.WithField("header", r.Header).Trace("tracing headers for debug") | ||||||
|  | 	// First check if we've got everything we need | ||||||
|  | 	fwd, err := a.getTraefikForwardUrl(r) | ||||||
|  | 	if err != nil { | ||||||
|  | 		a.ReportMisconfiguration(r, fmt.Sprintf("Outpost %s (Provider %s) failed to detect a forward URL from Traefik", a.outpostName, a.proxyConfig.Name), map[string]interface{}{ | ||||||
|  | 			"provider": a.proxyConfig.Name, | ||||||
|  | 			"outpost":  a.outpostName, | ||||||
|  | 			"url":      r.URL.String(), | ||||||
|  | 			"headers":  cleanseHeaders(r.Header), | ||||||
|  | 		}) | ||||||
|  | 		http.Error(rw, "configuration error", http.StatusInternalServerError) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	claims, err := a.getClaims(r) | 	claims, err := a.getClaims(r) | ||||||
| 	if claims != nil && err == nil { | 	if claims != nil && err == nil { | ||||||
| 		a.addHeaders(rw.Header(), claims) | 		a.addHeaders(rw.Header(), claims) | ||||||
| 		rw.Header().Set("User-Agent", r.Header.Get("User-Agent")) | 		rw.Header().Set("User-Agent", r.Header.Get("User-Agent")) | ||||||
| 		a.log.WithField("headers", rw.Header()).Trace("headers written to forward_auth") | 		a.log.WithField("headers", rw.Header()).Trace("headers written to forward_auth") | ||||||
| 		return | 		return | ||||||
| 	} else if claims == nil && a.IsAllowlisted(r) { | 	} else if claims == nil && a.IsAllowlisted(fwd) { | ||||||
| 		a.log.Trace("path can be accessed without authentication") | 		a.log.Trace("path can be accessed without authentication") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| @ -45,15 +59,18 @@ func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Reque | |||||||
| 	if *a.proxyConfig.Mode == api.PROXYMODE_FORWARD_SINGLE { | 	if *a.proxyConfig.Mode == api.PROXYMODE_FORWARD_SINGLE { | ||||||
| 		host = web.GetHost(r) | 		host = web.GetHost(r) | ||||||
| 	} else if *a.proxyConfig.Mode == api.PROXYMODE_FORWARD_DOMAIN { | 	} else if *a.proxyConfig.Mode == api.PROXYMODE_FORWARD_DOMAIN { | ||||||
| 		eh, _ := url.Parse(a.proxyConfig.ExternalHost) | 		eh, err := url.Parse(a.proxyConfig.ExternalHost) | ||||||
|  | 		if err != nil { | ||||||
|  | 			a.log.WithField("host", a.proxyConfig.ExternalHost).WithError(err).Warning("invalid external_host") | ||||||
|  | 		} else { | ||||||
| 			host = eh.Host | 			host = eh.Host | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| 	// set the redirect flag to the current URL we have, since we redirect | 	// set the redirect flag to the current URL we have, since we redirect | ||||||
| 	// to a (possibly) different domain, but we want to be redirected back | 	// to a (possibly) different domain, but we want to be redirected back | ||||||
| 	// to the application | 	// to the application | ||||||
| 	// see https://doc.traefik.io/traefik/middlewares/forwardauth/ |  | ||||||
| 	// X-Forwarded-Uri is only the path, so we need to build the entire URL | 	// X-Forwarded-Uri is only the path, so we need to build the entire URL | ||||||
| 	s.Values[constants.SessionRedirect] = a.getTraefikForwardUrl(r).String() | 	s.Values[constants.SessionRedirect] = fwd.String() | ||||||
| 	err = s.Save(r, rw) | 	err = s.Save(r, rw) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		a.log.WithError(err).Warning("failed to save session before redirect") | 		a.log.WithError(err).Warning("failed to save session before redirect") | ||||||
| @ -69,6 +86,19 @@ func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Reque | |||||||
| } | } | ||||||
|  |  | ||||||
| func (a *Application) forwardHandleNginx(rw http.ResponseWriter, r *http.Request) { | func (a *Application) forwardHandleNginx(rw http.ResponseWriter, r *http.Request) { | ||||||
|  | 	a.log.WithField("header", r.Header).Trace("tracing headers for debug") | ||||||
|  | 	fwd, err := a.getNginxForwardUrl(r) | ||||||
|  | 	if err != nil { | ||||||
|  | 		a.ReportMisconfiguration(r, fmt.Sprintf("Outpost %s (Provider %s) failed to detect a forward URL from nginx", a.outpostName, a.proxyConfig.Name), map[string]interface{}{ | ||||||
|  | 			"provider": a.proxyConfig.Name, | ||||||
|  | 			"outpost":  a.outpostName, | ||||||
|  | 			"url":      r.URL.String(), | ||||||
|  | 			"headers":  cleanseHeaders(r.Header), | ||||||
|  | 		}) | ||||||
|  | 		http.Error(rw, "configuration error", http.StatusInternalServerError) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	claims, err := a.getClaims(r) | 	claims, err := a.getClaims(r) | ||||||
| 	if claims != nil && err == nil { | 	if claims != nil && err == nil { | ||||||
| 		a.addHeaders(rw.Header(), claims) | 		a.addHeaders(rw.Header(), claims) | ||||||
| @ -76,13 +106,20 @@ func (a *Application) forwardHandleNginx(rw http.ResponseWriter, r *http.Request | |||||||
| 		rw.WriteHeader(200) | 		rw.WriteHeader(200) | ||||||
| 		a.log.WithField("headers", rw.Header()).Trace("headers written to forward_auth") | 		a.log.WithField("headers", rw.Header()).Trace("headers written to forward_auth") | ||||||
| 		return | 		return | ||||||
| 	} else if claims == nil && a.IsAllowlisted(r) { | 	} else if claims == nil && a.IsAllowlisted(fwd) { | ||||||
| 		a.log.Trace("path can be accessed without authentication") | 		a.log.Trace("path can be accessed without authentication") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	fwu := a.getTraefikForwardUrl(r) |  | ||||||
| 	if fwu.String() != r.URL.String() { | 	s, _ := a.sessions.Get(r, constants.SeesionName) | ||||||
| 		if strings.HasPrefix(fwu.Path, "/akprox") { | 	s.Values[constants.SessionRedirect] = fwd.String() | ||||||
|  | 	err = s.Save(r, rw) | ||||||
|  | 	if err != nil { | ||||||
|  | 		a.log.WithError(err).Warning("failed to save session before redirect") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if fwd.String() != r.URL.String() { | ||||||
|  | 		if strings.HasPrefix(fwd.Path, "/akprox") { | ||||||
| 			a.log.WithField("url", r.URL.String()).Trace("path begins with /akprox, allowing access") | 			a.log.WithField("url", r.URL.String()).Trace("path begins with /akprox, allowing access") | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  | |||||||
							
								
								
									
										134
									
								
								internal/outpost/proxyv2/application/mode_forward_nginx_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								internal/outpost/proxyv2/application/mode_forward_nginx_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,134 @@ | |||||||
|  | package application | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"net/http/httptest" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"goauthentik.io/api" | ||||||
|  | 	"goauthentik.io/internal/outpost/proxyv2/constants" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestForwardHandleNginx_Single_Blank(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil) | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleNginx(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusInternalServerError, rr.Code) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleNginx_Single_Skip(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil) | ||||||
|  | 	req.Header.Set("X-Original-URL", "http://test.goauthentik.io/skip") | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleNginx(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusOK, rr.Code) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleNginx_Single_Headers(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil) | ||||||
|  | 	req.Header.Set("X-Original-URL", "http://test.goauthentik.io/app") | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleNginx(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, rr.Code, http.StatusUnauthorized) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleNginx_Single_URI(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	req, _ := http.NewRequest("GET", "https://foo.bar/akprox/auth/nginx", nil) | ||||||
|  | 	req.Header.Set("X-Original-URI", "/app") | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleNginx(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, rr.Code, http.StatusUnauthorized) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	assert.Equal(t, "/app", s.Values[constants.SessionRedirect]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleNginx_Single_Claims(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil) | ||||||
|  | 	req.Header.Set("X-Original-URI", "/") | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleNginx(rr, req) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	s.Values[constants.SessionClaims] = Claims{ | ||||||
|  | 		Sub: "foo", | ||||||
|  | 		Proxy: ProxyClaims{ | ||||||
|  | 			UserAttributes: map[string]interface{}{ | ||||||
|  | 				"username": "foo", | ||||||
|  | 				"password": "bar", | ||||||
|  | 				"additionalHeaders": map[string]interface{}{ | ||||||
|  | 					"foo": "bar", | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	err := a.sessions.Save(req, rr, s) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	rr = httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleNginx(rr, req) | ||||||
|  |  | ||||||
|  | 	h := rr.Result().Header | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, []string{"Basic Zm9vOmJhcg=="}, h["Authorization"]) | ||||||
|  | 	assert.Equal(t, []string{"bar"}, h["Foo"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["User-Agent"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Email"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Groups"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Jwt"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Meta-App"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Meta-Jwks"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Meta-Outpost"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Name"]) | ||||||
|  | 	assert.Equal(t, []string{"foo"}, h["X-Authentik-Uid"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Username"]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleNginx_Domain_Blank(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr() | ||||||
|  | 	a.proxyConfig.CookieDomain = api.PtrString("foo") | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil) | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleNginx(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusInternalServerError, rr.Code) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleNginx_Domain_Header(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr() | ||||||
|  | 	a.proxyConfig.CookieDomain = api.PtrString("foo") | ||||||
|  | 	a.proxyConfig.ExternalHost = "http://auth.test.goauthentik.io" | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil) | ||||||
|  | 	req.Header.Set("X-Original-URL", "http://test.goauthentik.io/app") | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleNginx(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusUnauthorized, rr.Code) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) | ||||||
|  | } | ||||||
| @ -0,0 +1,132 @@ | |||||||
|  | package application | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"net/http/httptest" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"goauthentik.io/api" | ||||||
|  | 	"goauthentik.io/internal/outpost/proxyv2/constants" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestForwardHandleTraefik_Single_Blank(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil) | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleTraefik(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusInternalServerError, rr.Code) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleTraefik_Single_Skip(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil) | ||||||
|  | 	req.Header.Set("X-Forwarded-Proto", "http") | ||||||
|  | 	req.Header.Set("X-Forwarded-Host", "test.goauthentik.io") | ||||||
|  | 	req.Header.Set("X-Forwarded-Uri", "/skip") | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleTraefik(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusOK, rr.Code) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleTraefik_Single_Headers(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil) | ||||||
|  | 	req.Header.Set("X-Forwarded-Proto", "http") | ||||||
|  | 	req.Header.Set("X-Forwarded-Host", "test.goauthentik.io") | ||||||
|  | 	req.Header.Set("X-Forwarded-Uri", "/app") | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleTraefik(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, rr.Code, http.StatusTemporaryRedirect) | ||||||
|  | 	loc, _ := rr.Result().Location() | ||||||
|  | 	assert.Equal(t, loc.String(), "http://test.goauthentik.io/akprox/start") | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleTraefik_Single_Claims(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil) | ||||||
|  | 	req.Header.Set("X-Forwarded-Proto", "http") | ||||||
|  | 	req.Header.Set("X-Forwarded-Host", "test.goauthentik.io") | ||||||
|  | 	req.Header.Set("X-Forwarded-Uri", "/app") | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleTraefik(rr, req) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	s.Values[constants.SessionClaims] = Claims{ | ||||||
|  | 		Sub: "foo", | ||||||
|  | 		Proxy: ProxyClaims{ | ||||||
|  | 			UserAttributes: map[string]interface{}{ | ||||||
|  | 				"username": "foo", | ||||||
|  | 				"password": "bar", | ||||||
|  | 				"additionalHeaders": map[string]interface{}{ | ||||||
|  | 					"foo": "bar", | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	err := a.sessions.Save(req, rr, s) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	rr = httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleTraefik(rr, req) | ||||||
|  |  | ||||||
|  | 	h := rr.Result().Header | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, []string{"Basic Zm9vOmJhcg=="}, h["Authorization"]) | ||||||
|  | 	assert.Equal(t, []string{"bar"}, h["Foo"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["User-Agent"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Email"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Groups"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Jwt"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Meta-App"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Meta-Jwks"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Meta-Outpost"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Name"]) | ||||||
|  | 	assert.Equal(t, []string{"foo"}, h["X-Authentik-Uid"]) | ||||||
|  | 	assert.Equal(t, []string{""}, h["X-Authentik-Username"]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleTraefik_Domain_Blank(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr() | ||||||
|  | 	a.proxyConfig.CookieDomain = api.PtrString("foo") | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil) | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleTraefik(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusInternalServerError, rr.Code) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestForwardHandleTraefik_Domain_Header(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr() | ||||||
|  | 	a.proxyConfig.CookieDomain = api.PtrString("foo") | ||||||
|  | 	a.proxyConfig.ExternalHost = "http://auth.test.goauthentik.io" | ||||||
|  | 	req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil) | ||||||
|  | 	req.Header.Set("X-Forwarded-Proto", "http") | ||||||
|  | 	req.Header.Set("X-Forwarded-Host", "test.goauthentik.io") | ||||||
|  | 	req.Header.Set("X-Forwarded-Uri", "/app") | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.forwardHandleTraefik(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusTemporaryRedirect, rr.Code) | ||||||
|  | 	loc, _ := rr.Result().Location() | ||||||
|  | 	assert.Equal(t, "http://auth.test.goauthentik.io/akprox/start", loc.String()) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) | ||||||
|  | } | ||||||
| @ -35,7 +35,7 @@ func (a *Application) configureProxy() error { | |||||||
| 	rp.ModifyResponse = a.proxyModifyResponse | 	rp.ModifyResponse = a.proxyModifyResponse | ||||||
| 	a.mux.PathPrefix("/").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { | 	a.mux.PathPrefix("/").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { | ||||||
| 		claims, err := a.getClaims(r) | 		claims, err := a.getClaims(r) | ||||||
| 		if claims == nil && a.IsAllowlisted(r) { | 		if claims == nil && a.IsAllowlisted(r.URL) { | ||||||
| 			a.log.Trace("path can be accessed without authentication") | 			a.log.Trace("path can be accessed without authentication") | ||||||
| 		} else if claims == nil && err != nil { | 		} else if claims == nil && err != nil { | ||||||
| 			a.redirectToStart(rw, r) | 			a.redirectToStart(rw, r) | ||||||
| @ -60,7 +60,7 @@ func (a *Application) configureProxy() error { | |||||||
| 		} | 		} | ||||||
| 		metrics.UpstreamTiming.With(prometheus.Labels{ | 		metrics.UpstreamTiming.With(prometheus.Labels{ | ||||||
| 			"outpost_name":  a.outpostName, | 			"outpost_name":  a.outpostName, | ||||||
| 			"upstream_host": u.String(), | 			"upstream_host": r.URL.Host, | ||||||
| 			"scheme":        r.URL.Scheme, | 			"scheme":        r.URL.Scheme, | ||||||
| 			"method":        r.Method, | 			"method":        r.Method, | ||||||
| 			"path":          r.URL.Path, | 			"path":          r.URL.Path, | ||||||
| @ -71,13 +71,24 @@ func (a *Application) configureProxy() error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (a *Application) proxyModifyRequest(u *url.URL) func(req *http.Request) { | func (a *Application) proxyModifyRequest(ou *url.URL) func(req *http.Request) { | ||||||
| 	return func(req *http.Request) { | 	return func(r *http.Request) { | ||||||
| 		req.URL.Scheme = u.Scheme | 		claims, _ := a.getClaims(r) | ||||||
| 		req.URL.Host = u.Host | 		if claims.Proxy.BackendOverride != "" { | ||||||
|  | 			u, err := url.Parse(claims.Proxy.BackendOverride) | ||||||
|  | 			if err != nil { | ||||||
|  | 				a.log.WithField("backend_override", claims.Proxy.BackendOverride).WithError(err).Warning("failed parse user backend override") | ||||||
|  | 			} | ||||||
|  | 			r.URL.Scheme = u.Scheme | ||||||
|  | 			r.URL.Host = u.Host | ||||||
|  | 		} else { | ||||||
|  | 			r.URL.Scheme = ou.Scheme | ||||||
|  | 			r.URL.Host = ou.Host | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (a *Application) proxyModifyResponse(res *http.Response) error { | func (a *Application) proxyModifyResponse(res *http.Response) error { | ||||||
|  | 	res.Header.Set("X-Powered-By", "authentik_proxy2") | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										40
									
								
								internal/outpost/proxyv2/application/test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								internal/outpost/proxyv2/application/test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | package application | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  |  | ||||||
|  | 	"github.com/quasoft/memstore" | ||||||
|  | 	"goauthentik.io/api" | ||||||
|  | 	"goauthentik.io/internal/outpost/ak" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func newTestApplication() *Application { | ||||||
|  | 	a, _ := NewApplication( | ||||||
|  | 		api.ProxyOutpostConfig{ | ||||||
|  | 			Name:                       ak.TestSecret(), | ||||||
|  | 			ClientId:                   api.PtrString(ak.TestSecret()), | ||||||
|  | 			ClientSecret:               api.PtrString(ak.TestSecret()), | ||||||
|  | 			CookieSecret:               api.PtrString(ak.TestSecret()), | ||||||
|  | 			CookieDomain:               api.PtrString(""), | ||||||
|  | 			Mode:                       api.PROXYMODE_FORWARD_SINGLE.Ptr(), | ||||||
|  | 			SkipPathRegex:              api.PtrString("/skip.*"), | ||||||
|  | 			BasicAuthEnabled:           api.PtrBool(true), | ||||||
|  | 			BasicAuthUserAttribute:     api.PtrString("username"), | ||||||
|  | 			BasicAuthPasswordAttribute: api.PtrString("password"), | ||||||
|  | 		}, | ||||||
|  | 		http.DefaultClient, | ||||||
|  | 		nil, | ||||||
|  | 		ak.MockAK( | ||||||
|  | 			api.Outpost{ | ||||||
|  | 				Config: map[string]interface{}{ | ||||||
|  | 					"authentik_host": ak.TestSecret(), | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			ak.MockConfig(), | ||||||
|  | 		), | ||||||
|  | 	) | ||||||
|  | 	a.sessions = memstore.NewMemStore( | ||||||
|  | 		[]byte(ak.TestSecret()), | ||||||
|  | 	) | ||||||
|  | 	return a | ||||||
|  | } | ||||||
| @ -26,21 +26,14 @@ func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) { | |||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		a.log.WithError(err).Warning("failed to decode session") | 		a.log.WithError(err).Warning("failed to decode session") | ||||||
| 	} | 	} | ||||||
| 	redirectUrl := r.URL.String() | 	redirectUrl := urlJoin(a.proxyConfig.ExternalHost, r.URL.Path) | ||||||
| 	// simple way to copy the URL |  | ||||||
| 	u, _ := url.Parse(redirectUrl) |  | ||||||
| 	// In proxy and forward_single mode we only have one URL that we route on |  | ||||||
| 	// if we somehow got here without that URL, make sure we're at least redirected back to it |  | ||||||
| 	if a.Mode() == api.PROXYMODE_PROXY || a.Mode() == api.PROXYMODE_FORWARD_SINGLE { |  | ||||||
| 		u.Host = a.proxyConfig.ExternalHost |  | ||||||
| 	} |  | ||||||
| 	if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN { | 	if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN { | ||||||
| 		dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".") | 		dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".") | ||||||
| 		// In forward_domain we only check that the current URL's host | 		// In forward_domain we only check that the current URL's host | ||||||
| 		// ends with the cookie domain (remove the leading period if set) | 		// ends with the cookie domain (remove the leading period if set) | ||||||
| 		if !strings.HasSuffix(r.URL.Hostname(), dom) { | 		if !strings.HasSuffix(r.URL.Hostname(), dom) { | ||||||
| 			a.log.WithField("url", r.URL.String()).WithField("cd", dom).Warning("Invalid redirect found") | 			a.log.WithField("url", r.URL.String()).WithField("cd", dom).Warning("Invalid redirect found") | ||||||
| 			redirectUrl = "" | 			redirectUrl = a.proxyConfig.ExternalHost | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	s.Values[constants.SessionRedirect] = redirectUrl | 	s.Values[constants.SessionRedirect] = redirectUrl | ||||||
| @ -94,3 +87,13 @@ func contains(s []string, e string) bool { | |||||||
| 	} | 	} | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func cleanseHeaders(headers http.Header) map[string]string { | ||||||
|  | 	h := make(map[string]string) | ||||||
|  | 	for hk, hv := range headers { | ||||||
|  | 		if len(hv) > 0 { | ||||||
|  | 			h[hk] = hv[0] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return h | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										81
									
								
								internal/outpost/proxyv2/application/utils_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								internal/outpost/proxyv2/application/utils_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | |||||||
|  | package application | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"net/http/httptest" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"goauthentik.io/api" | ||||||
|  | 	"goauthentik.io/internal/outpost/proxyv2/constants" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestRedirectToStart_Proxy(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	a.proxyConfig.Mode = api.PROXYMODE_PROXY.Ptr() | ||||||
|  | 	a.proxyConfig.ExternalHost = "https://test.goauthentik.io" | ||||||
|  | 	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil) | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.redirectToStart(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusFound, rr.Code) | ||||||
|  | 	loc, _ := rr.Result().Location() | ||||||
|  | 	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String()) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	assert.Equal(t, "https://test.goauthentik.io/foo/bar/baz", s.Values[constants.SessionRedirect]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestRedirectToStart_Forward(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_SINGLE.Ptr() | ||||||
|  | 	a.proxyConfig.ExternalHost = "https://test.goauthentik.io" | ||||||
|  | 	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil) | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.redirectToStart(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusFound, rr.Code) | ||||||
|  | 	loc, _ := rr.Result().Location() | ||||||
|  | 	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String()) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	assert.Equal(t, "https://test.goauthentik.io/foo/bar/baz", s.Values[constants.SessionRedirect]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestRedirectToStart_Forward_Domain_Invalid(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	a.proxyConfig.CookieDomain = api.PtrString("foo") | ||||||
|  | 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr() | ||||||
|  | 	a.proxyConfig.ExternalHost = "https://test.goauthentik.io" | ||||||
|  | 	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil) | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.redirectToStart(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusFound, rr.Code) | ||||||
|  | 	loc, _ := rr.Result().Location() | ||||||
|  | 	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String()) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	assert.Equal(t, "https://test.goauthentik.io", s.Values[constants.SessionRedirect]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestRedirectToStart_Forward_Domain(t *testing.T) { | ||||||
|  | 	a := newTestApplication() | ||||||
|  | 	a.proxyConfig.CookieDomain = api.PtrString("goauthentik.io") | ||||||
|  | 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr() | ||||||
|  | 	a.proxyConfig.ExternalHost = "https://test.goauthentik.io" | ||||||
|  | 	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil) | ||||||
|  |  | ||||||
|  | 	rr := httptest.NewRecorder() | ||||||
|  | 	a.redirectToStart(rr, req) | ||||||
|  |  | ||||||
|  | 	assert.Equal(t, http.StatusFound, rr.Code) | ||||||
|  | 	loc, _ := rr.Result().Location() | ||||||
|  | 	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String()) | ||||||
|  |  | ||||||
|  | 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||||
|  | 	assert.Equal(t, "https://test.goauthentik.io", s.Values[constants.SessionRedirect]) | ||||||
|  | } | ||||||
| @ -8,6 +8,7 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/prometheus/client_golang/prometheus" | 	"github.com/prometheus/client_golang/prometheus" | ||||||
|  | 	"goauthentik.io/api" | ||||||
| 	"goauthentik.io/internal/outpost/proxyv2/application" | 	"goauthentik.io/internal/outpost/proxyv2/application" | ||||||
| 	"goauthentik.io/internal/outpost/proxyv2/metrics" | 	"goauthentik.io/internal/outpost/proxyv2/metrics" | ||||||
| 	"goauthentik.io/internal/utils/web" | 	"goauthentik.io/internal/utils/web" | ||||||
| @ -58,6 +59,9 @@ func (ps *ProxyServer) lookupApp(r *http.Request) (*application.Application, str | |||||||
| 	var longestMatch *application.Application | 	var longestMatch *application.Application | ||||||
| 	longestMatchLength := 0 | 	longestMatchLength := 0 | ||||||
| 	for _, app := range ps.apps { | 	for _, app := range ps.apps { | ||||||
|  | 		if app.Mode() != api.PROXYMODE_FORWARD_DOMAIN { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
| 		// Check if the cookie domain has a leading period for a wildcard | 		// Check if the cookie domain has a leading period for a wildcard | ||||||
| 		// This will decrease the weight of a wildcard domain, but a request to example.com | 		// This will decrease the weight of a wildcard domain, but a request to example.com | ||||||
| 		// with the cookie domain set to example.com will still be routed correctly. | 		// with the cookie domain set to example.com will still be routed correctly. | ||||||
| @ -70,6 +74,11 @@ func (ps *ProxyServer) lookupApp(r *http.Request) (*application.Application, str | |||||||
| 		} | 		} | ||||||
| 		longestMatch = app | 		longestMatch = app | ||||||
| 		longestMatchLength = len(cd) | 		longestMatchLength = len(cd) | ||||||
|  | 		// Also for forward_auth_domain, we need to respond on the external domain | ||||||
|  | 		if app.ProxyConfig().ExternalHost == host { | ||||||
|  | 			ps.log.WithField("host", host).WithField("app", app.ProxyConfig().Name).Debug("Found app based on external_host") | ||||||
|  | 			return app, host | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	// Check if our longes match is 0, in which case we didn't match, so we | 	// Check if our longes match is 0, in which case we didn't match, so we | ||||||
| 	// manually return no app | 	// manually return no app | ||||||
|  | |||||||
| @ -46,7 +46,7 @@ func NewProxyServer(ac *ak.APIController, portOffset int) *ProxyServer { | |||||||
| 	rootMux.Use(func(h http.Handler) http.Handler { | 	rootMux.Use(func(h http.Handler) http.Handler { | ||||||
| 		return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { | 		return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { | ||||||
| 			h.ServeHTTP(rw, r) | 			h.ServeHTTP(rw, r) | ||||||
| 			rw.Header().Set("Server", "authentik_proxy2") | 			rw.Header().Set("X-Powered-By", "authentik_proxy2") | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| @ -91,7 +91,7 @@ func (ps *ProxyServer) TimerFlowCacheExpiry() {} | |||||||
| func (ps *ProxyServer) GetCertificate(serverName string) *tls.Certificate { | func (ps *ProxyServer) GetCertificate(serverName string) *tls.Certificate { | ||||||
| 	app, ok := ps.apps[serverName] | 	app, ok := ps.apps[serverName] | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		ps.log.WithField("server-name", serverName).Debug("app does not exist") | 		ps.log.WithField("server-name", serverName).Debug("failed to get certificate for ServerName") | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	if app.Cert == nil { | 	if app.Cert == nil { | ||||||
| @ -151,17 +151,14 @@ func (ps *ProxyServer) Start() error { | |||||||
| 	wg.Add(3) | 	wg.Add(3) | ||||||
| 	go func() { | 	go func() { | ||||||
| 		defer wg.Done() | 		defer wg.Done() | ||||||
| 		ps.log.Debug("Starting HTTP Server...") |  | ||||||
| 		ps.ServeHTTP() | 		ps.ServeHTTP() | ||||||
| 	}() | 	}() | ||||||
| 	go func() { | 	go func() { | ||||||
| 		defer wg.Done() | 		defer wg.Done() | ||||||
| 		ps.log.Debug("Starting HTTPs Server...") |  | ||||||
| 		ps.ServeHTTPS() | 		ps.ServeHTTPS() | ||||||
| 	}() | 	}() | ||||||
| 	go func() { | 	go func() { | ||||||
| 		defer wg.Done() | 		defer wg.Done() | ||||||
| 		ps.log.Debug("Starting Metrics Server...") |  | ||||||
| 		metrics.RunServer() | 		metrics.RunServer() | ||||||
| 	}() | 	}() | ||||||
| 	return nil | 	return nil | ||||||
|  | |||||||
| @ -101,12 +101,12 @@ func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { | |||||||
| 	h.afterHandler(h.logger.WithFields(log.Fields{ | 	h.afterHandler(h.logger.WithFields(log.Fields{ | ||||||
| 		"remote":     req.RemoteAddr, | 		"remote":     req.RemoteAddr, | ||||||
| 		"host":       GetHost(req), | 		"host":       GetHost(req), | ||||||
| 		"request_protocol":  req.Proto, |  | ||||||
| 		"runtime":    fmt.Sprintf("%0.3f", duration), | 		"runtime":    fmt.Sprintf("%0.3f", duration), | ||||||
| 		"method":     req.Method, | 		"method":     req.Method, | ||||||
|  | 		"scheme":     req.URL.Scheme, | ||||||
| 		"size":       responseLogger.Size(), | 		"size":       responseLogger.Size(), | ||||||
| 		"status":     responseLogger.Status(), | 		"status":     responseLogger.Status(), | ||||||
| 		"upstream":   responseLogger.upstream, | 		"upstream":   responseLogger.upstream, | ||||||
| 		"request_useragent": req.UserAgent(), | 		"user_agent": req.UserAgent(), | ||||||
| 	}), req).Info(url.RequestURI()) | 	}), req).Info(url.RequestURI()) | ||||||
| } | } | ||||||
|  | |||||||
| @ -74,6 +74,6 @@ func (ws *WebServer) proxyErrorHandler(rw http.ResponseWriter, req *http.Request | |||||||
| } | } | ||||||
|  |  | ||||||
| func (ws *WebServer) proxyModifyResponse(r *http.Response) error { | func (ws *WebServer) proxyModifyResponse(r *http.Response) error { | ||||||
| 	r.Header.Set("server", "authentik") | 	r.Header.Set("X-Powered-By", "authentik") | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -69,6 +69,7 @@ if [[ "$1" == "server" ]]; then | |||||||
|     python -m lifecycle.migrate |     python -m lifecycle.migrate | ||||||
|     /authentik-proxy |     /authentik-proxy | ||||||
| elif [[ "$1" == "worker" ]]; then | elif [[ "$1" == "worker" ]]; then | ||||||
|  |     wait_for_db | ||||||
|     echo "worker" > $MODE_FILE |     echo "worker" > $MODE_FILE | ||||||
|     check_if_root "celery -A authentik.root.celery worker -Ofair --max-tasks-per-child=1 --autoscale 3,1 -E -B -s /tmp/celerybeat-schedule -Q authentik,authentik_scheduled,authentik_events" |     check_if_root "celery -A authentik.root.celery worker -Ofair --max-tasks-per-child=1 --autoscale 3,1 -E -B -s /tmp/celerybeat-schedule -Q authentik,authentik_scheduled,authentik_events" | ||||||
| elif [[ "$1" == "flower" ]]; then | elif [[ "$1" == "flower" ]]; then | ||||||
|  | |||||||
| @ -1,13 +1,18 @@ | |||||||
| """Gunicorn config""" | """Gunicorn config""" | ||||||
| import os | import os | ||||||
| import pwd | import pwd | ||||||
|  | from hashlib import sha512 | ||||||
| from multiprocessing import cpu_count | from multiprocessing import cpu_count | ||||||
|  |  | ||||||
| import structlog | import structlog | ||||||
| from kubernetes.config.incluster_config import SERVICE_HOST_ENV_NAME | from kubernetes.config.incluster_config import SERVICE_HOST_ENV_NAME | ||||||
|  |  | ||||||
|  | from authentik import get_full_version | ||||||
|  | from authentik.lib.config import CONFIG | ||||||
|  | from authentik.lib.utils.http import get_http_session | ||||||
|  | from authentik.lib.utils.reflection import get_env | ||||||
|  |  | ||||||
| bind = "127.0.0.1:8000" | bind = "127.0.0.1:8000" | ||||||
| reload = True |  | ||||||
|  |  | ||||||
| try: | try: | ||||||
|     pwd.getpwnam("authentik") |     pwd.getpwnam("authentik") | ||||||
| @ -23,6 +28,9 @@ if os.path.exists("/dev/shm"):  # nosec | |||||||
|  |  | ||||||
| os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings") | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings") | ||||||
|  |  | ||||||
|  | max_requests = 1000 | ||||||
|  | max_requests_jitter = 50 | ||||||
|  |  | ||||||
| logconfig_dict = { | logconfig_dict = { | ||||||
|     "version": 1, |     "version": 1, | ||||||
|     "disable_existing_loggers": False, |     "disable_existing_loggers": False, | ||||||
| @ -67,3 +75,31 @@ def worker_exit(server, worker): | |||||||
|     from prometheus_client import multiprocess |     from prometheus_client import multiprocess | ||||||
|  |  | ||||||
|     multiprocess.mark_process_dead(worker.pid) |     multiprocess.mark_process_dead(worker.pid) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | if not CONFIG.y_bool("disable_startup_analytics", False): | ||||||
|  |     env = get_env() | ||||||
|  |     should_send = env not in ["dev", "ci"] | ||||||
|  |     if should_send: | ||||||
|  |         try: | ||||||
|  |             get_http_session().post( | ||||||
|  |                 "https://goauthentik.io/api/event", | ||||||
|  |                 json={ | ||||||
|  |                     "domain": "authentik", | ||||||
|  |                     "name": "pageview", | ||||||
|  |                     "referrer": get_full_version(), | ||||||
|  |                     "url": ( | ||||||
|  |                         f"http://localhost/{env}?utm_source={get_full_version()}&utm_medium={env}" | ||||||
|  |                     ), | ||||||
|  |                 }, | ||||||
|  |                 headers={ | ||||||
|  |                     "User-Agent": sha512(str(CONFIG.y("secret_key")).encode("ascii")).hexdigest()[ | ||||||
|  |                         :16 | ||||||
|  |                     ], | ||||||
|  |                     "Content-Type": "application/json", | ||||||
|  |                 }, | ||||||
|  |                 timeout=5, | ||||||
|  |             ) | ||||||
|  |         # pylint: disable=bare-except | ||||||
|  |         except:  # nosec | ||||||
|  |             pass | ||||||
|  | |||||||
| @ -26,9 +26,13 @@ def j_print(event: str, log_level: str = "info", **kwargs): | |||||||
|     print(dumps(data), file=stderr) |     print(dumps(data), file=stderr) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | j_print("Starting authentik bootstrap") | ||||||
|  |  | ||||||
| # Sanity check, ensure SECRET_KEY is set before we even check for database connectivity | # Sanity check, ensure SECRET_KEY is set before we even check for database connectivity | ||||||
| if CONFIG.y("secret_key") is None or len(CONFIG.y("secret_key")) == 0: | if CONFIG.y("secret_key") is None or len(CONFIG.y("secret_key")) == 0: | ||||||
|  |     j_print("----------------------------------------------------------------------") | ||||||
|     j_print("Secret key missing, check https://goauthentik.io/docs/installation/.") |     j_print("Secret key missing, check https://goauthentik.io/docs/installation/.") | ||||||
|  |     j_print("----------------------------------------------------------------------") | ||||||
|     sysexit(1) |     sysexit(1) | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -45,7 +49,9 @@ while True: | |||||||
|         break |         break | ||||||
|     except OperationalError as exc: |     except OperationalError as exc: | ||||||
|         sleep(1) |         sleep(1) | ||||||
|         j_print(f"PostgreSQL Connection failed, retrying... ({exc})") |         j_print(f"PostgreSQL connection failed, retrying... ({exc})") | ||||||
|  |     finally: | ||||||
|  |         j_print("PostgreSQL connection successful") | ||||||
|  |  | ||||||
| REDIS_PROTOCOL_PREFIX = "redis://" | REDIS_PROTOCOL_PREFIX = "redis://" | ||||||
| if CONFIG.y_bool("redis.tls", False): | if CONFIG.y_bool("redis.tls", False): | ||||||
| @ -63,3 +69,7 @@ while True: | |||||||
|     except RedisError as exc: |     except RedisError as exc: | ||||||
|         sleep(1) |         sleep(1) | ||||||
|         j_print(f"Redis Connection failed, retrying... ({exc})", redis_url=REDIS_URL) |         j_print(f"Redis Connection failed, retrying... ({exc})", redis_url=REDIS_URL) | ||||||
|  |     finally: | ||||||
|  |         j_print("Redis Connection successful") | ||||||
|  |  | ||||||
|  | j_print("Finished authentik bootstrap") | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								locale/es/LC_MESSAGES/django.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								locale/es/LC_MESSAGES/django.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1831
									
								
								locale/es/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1831
									
								
								locale/es/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										252
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										252
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							| @ -163,11 +163,11 @@ visualize = ["graphviz (>0.5.1)", "Twisted (>=16.1.1)"] | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "bandit" | name = "bandit" | ||||||
| version = "1.7.1" | version = "1.7.2" | ||||||
| description = "Security oriented static analyser for python code." | description = "Security oriented static analyser for python code." | ||||||
| category = "dev" | category = "dev" | ||||||
| optional = false | optional = false | ||||||
| python-versions = ">=3.5" | python-versions = ">=3.7" | ||||||
|  |  | ||||||
| [package.dependencies] | [package.dependencies] | ||||||
| colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} | colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} | ||||||
| @ -175,6 +175,11 @@ GitPython = ">=1.0.1" | |||||||
| PyYAML = ">=5.3.1" | PyYAML = ">=5.3.1" | ||||||
| stevedore = ">=1.20.0" | stevedore = ">=1.20.0" | ||||||
|  |  | ||||||
|  | [package.extras] | ||||||
|  | test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] | ||||||
|  | toml = ["toml"] | ||||||
|  | yaml = ["pyyaml"] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "bcrypt" | name = "bcrypt" | ||||||
| version = "3.2.0" | version = "3.2.0" | ||||||
| @ -201,40 +206,35 @@ python-versions = "*" | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "black" | name = "black" | ||||||
| version = "21.12b0" | version = "22.1.0" | ||||||
| description = "The uncompromising code formatter." | description = "The uncompromising code formatter." | ||||||
| category = "dev" | category = "dev" | ||||||
| optional = false | optional = false | ||||||
| python-versions = ">=3.6.2" | python-versions = ">=3.6.2" | ||||||
|  |  | ||||||
| [package.dependencies] | [package.dependencies] | ||||||
| click = ">=7.1.2" | click = ">=8.0.0" | ||||||
| mypy-extensions = ">=0.4.3" | mypy-extensions = ">=0.4.3" | ||||||
| pathspec = ">=0.9.0,<1" | pathspec = ">=0.9.0" | ||||||
| platformdirs = ">=2" | platformdirs = ">=2" | ||||||
| tomli = ">=0.2.6,<2.0.0" | tomli = ">=1.1.0" | ||||||
| typing-extensions = [ |  | ||||||
|     {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, |  | ||||||
|     {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, |  | ||||||
| ] |  | ||||||
|  |  | ||||||
| [package.extras] | [package.extras] | ||||||
| colorama = ["colorama (>=0.4.3)"] | colorama = ["colorama (>=0.4.3)"] | ||||||
| d = ["aiohttp (>=3.7.4)"] | d = ["aiohttp (>=3.7.4)"] | ||||||
| jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] | ||||||
| python2 = ["typed-ast (>=1.4.3)"] |  | ||||||
| uvloop = ["uvloop (>=0.15.2)"] | uvloop = ["uvloop (>=0.15.2)"] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "boto3" | name = "boto3" | ||||||
| version = "1.20.41" | version = "1.20.46" | ||||||
| description = "The AWS SDK for Python" | description = "The AWS SDK for Python" | ||||||
| category = "main" | category = "main" | ||||||
| optional = false | optional = false | ||||||
| python-versions = ">= 3.6" | python-versions = ">= 3.6" | ||||||
|  |  | ||||||
| [package.dependencies] | [package.dependencies] | ||||||
| botocore = ">=1.23.41,<1.24.0" | botocore = ">=1.23.46,<1.24.0" | ||||||
| jmespath = ">=0.7.1,<1.0.0" | jmespath = ">=0.7.1,<1.0.0" | ||||||
| s3transfer = ">=0.5.0,<0.6.0" | s3transfer = ">=0.5.0,<0.6.0" | ||||||
|  |  | ||||||
| @ -243,7 +243,7 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "botocore" | name = "botocore" | ||||||
| version = "1.23.41" | version = "1.23.46" | ||||||
| description = "Low-level, data-driven core of boto 3." | description = "Low-level, data-driven core of boto 3." | ||||||
| category = "main" | category = "main" | ||||||
| optional = false | optional = false | ||||||
| @ -490,11 +490,11 @@ python-versions = "*" | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "coverage" | name = "coverage" | ||||||
| version = "6.2" | version = "6.3" | ||||||
| description = "Code coverage measurement for Python" | description = "Code coverage measurement for Python" | ||||||
| category = "dev" | category = "dev" | ||||||
| optional = false | optional = false | ||||||
| python-versions = ">=3.6" | python-versions = ">=3.7" | ||||||
|  |  | ||||||
| [package.dependencies] | [package.dependencies] | ||||||
| tomli = {version = "*", optional = true, markers = "extra == \"toml\""} | tomli = {version = "*", optional = true, markers = "extra == \"toml\""} | ||||||
| @ -580,7 +580,7 @@ dev = ["tox", "bump2version (<1)", "sphinx (<2)", "importlib-metadata (<3)", "im | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "django" | name = "django" | ||||||
| version = "4.0.1" | version = "4.0.2" | ||||||
| description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." | description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." | ||||||
| category = "main" | category = "main" | ||||||
| optional = false | optional = false | ||||||
| @ -1297,7 +1297,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "pycryptodome" | name = "pycryptodome" | ||||||
| version = "3.13.0" | version = "3.14.0" | ||||||
| description = "Cryptographic library for Python" | description = "Cryptographic library for Python" | ||||||
| category = "main" | category = "main" | ||||||
| optional = false | optional = false | ||||||
| @ -1555,7 +1555,7 @@ test = ["fixtures", "mock", "purl", "pytest", "sphinx", "testrepository (>=0.0.1 | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "requests-oauthlib" | name = "requests-oauthlib" | ||||||
| version = "1.3.0" | version = "1.3.1" | ||||||
| description = "OAuthlib authentication support for Requests." | description = "OAuthlib authentication support for Requests." | ||||||
| category = "main" | category = "main" | ||||||
| optional = false | optional = false | ||||||
| @ -1608,7 +1608,7 @@ urllib3 = {version = ">=1.26,<2.0", extras = ["secure"]} | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "sentry-sdk" | name = "sentry-sdk" | ||||||
| version = "1.5.3" | version = "1.5.4" | ||||||
| description = "Python client for Sentry (https://sentry.io)" | description = "Python client for Sentry (https://sentry.io)" | ||||||
| category = "main" | category = "main" | ||||||
| optional = false | optional = false | ||||||
| @ -1898,11 +1898,11 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "uvicorn" | name = "uvicorn" | ||||||
| version = "0.17.0" | version = "0.17.1" | ||||||
| description = "The lightning-fast ASGI server." | description = "The lightning-fast ASGI server." | ||||||
| category = "main" | category = "main" | ||||||
| optional = false | optional = false | ||||||
| python-versions = "*" | python-versions = ">=3.7" | ||||||
|  |  | ||||||
| [package.dependencies] | [package.dependencies] | ||||||
| asgiref = ">=3.4.0" | asgiref = ">=3.4.0" | ||||||
| @ -2188,14 +2188,17 @@ automat = [ | |||||||
|     {file = "Automat-20.2.0.tar.gz", hash = "sha256:7979803c74610e11ef0c0d68a2942b152df52da55336e0c9d58daf1831cbdf33"}, |     {file = "Automat-20.2.0.tar.gz", hash = "sha256:7979803c74610e11ef0c0d68a2942b152df52da55336e0c9d58daf1831cbdf33"}, | ||||||
| ] | ] | ||||||
| bandit = [ | bandit = [ | ||||||
|     {file = "bandit-1.7.1-py3-none-any.whl", hash = "sha256:f5acd838e59c038a159b5c621cf0f8270b279e884eadd7b782d7491c02add0d4"}, |     {file = "bandit-1.7.2-py3-none-any.whl", hash = "sha256:e20402cadfd126d85b68ed4c8862959663c8c372dbbb1fca8f8e2c9f55a067ec"}, | ||||||
|     {file = "bandit-1.7.1.tar.gz", hash = "sha256:a81b00b5436e6880fa8ad6799bc830e02032047713cbb143a12939ac67eb756c"}, |     {file = "bandit-1.7.2.tar.gz", hash = "sha256:6d11adea0214a43813887bfe71a377b5a9955e4c826c8ffd341b494e3ab25260"}, | ||||||
| ] | ] | ||||||
| bcrypt = [ | bcrypt = [ | ||||||
|  |     {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b589229207630484aefe5899122fb938a5b017b0f4349f769b8c13e78d99a8fd"}, | ||||||
|     {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6"}, |     {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6"}, | ||||||
|     {file = "bcrypt-3.2.0-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7"}, |     {file = "bcrypt-3.2.0-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7"}, | ||||||
|     {file = "bcrypt-3.2.0-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1"}, |     {file = "bcrypt-3.2.0-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1"}, | ||||||
|     {file = "bcrypt-3.2.0-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"}, |     {file = "bcrypt-3.2.0-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"}, | ||||||
|  |     {file = "bcrypt-3.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a0584a92329210fcd75eb8a3250c5a941633f8bfaf2a18f81009b097732839b7"}, | ||||||
|  |     {file = "bcrypt-3.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:56e5da069a76470679f312a7d3d23deb3ac4519991a0361abc11da837087b61d"}, | ||||||
|     {file = "bcrypt-3.2.0-cp36-abi3-win32.whl", hash = "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55"}, |     {file = "bcrypt-3.2.0-cp36-abi3-win32.whl", hash = "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55"}, | ||||||
|     {file = "bcrypt-3.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34"}, |     {file = "bcrypt-3.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34"}, | ||||||
|     {file = "bcrypt-3.2.0.tar.gz", hash = "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29"}, |     {file = "bcrypt-3.2.0.tar.gz", hash = "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29"}, | ||||||
| @ -2205,16 +2208,37 @@ billiard = [ | |||||||
|     {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, |     {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, | ||||||
| ] | ] | ||||||
| black = [ | black = [ | ||||||
|     {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"}, |     {file = "black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6"}, | ||||||
|     {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"}, |     {file = "black-22.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866"}, | ||||||
|  |     {file = "black-22.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71"}, | ||||||
|  |     {file = "black-22.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab"}, | ||||||
|  |     {file = "black-22.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5"}, | ||||||
|  |     {file = "black-22.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a"}, | ||||||
|  |     {file = "black-22.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0"}, | ||||||
|  |     {file = "black-22.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba"}, | ||||||
|  |     {file = "black-22.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1"}, | ||||||
|  |     {file = "black-22.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8"}, | ||||||
|  |     {file = "black-22.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28"}, | ||||||
|  |     {file = "black-22.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912"}, | ||||||
|  |     {file = "black-22.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3"}, | ||||||
|  |     {file = "black-22.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3"}, | ||||||
|  |     {file = "black-22.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61"}, | ||||||
|  |     {file = "black-22.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd"}, | ||||||
|  |     {file = "black-22.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f"}, | ||||||
|  |     {file = "black-22.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0"}, | ||||||
|  |     {file = "black-22.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c"}, | ||||||
|  |     {file = "black-22.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2"}, | ||||||
|  |     {file = "black-22.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321"}, | ||||||
|  |     {file = "black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d"}, | ||||||
|  |     {file = "black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5"}, | ||||||
| ] | ] | ||||||
| boto3 = [ | boto3 = [ | ||||||
|     {file = "boto3-1.20.41-py3-none-any.whl", hash = "sha256:aaddf6cf93568b734ad62fd96991775bccc7f016e93ff4e98dc1aa4f7586440c"}, |     {file = "boto3-1.20.46-py3-none-any.whl", hash = "sha256:a2ffce001160d7e7c72a90c3084700d50eb64ea4a3aae8afe21566971d1fd611"}, | ||||||
|     {file = "boto3-1.20.41.tar.gz", hash = "sha256:fb02467a6e8109c7db994ba77fa2e8381ed129ce312988d8ef23edf6e3a3c7f1"}, |     {file = "boto3-1.20.46.tar.gz", hash = "sha256:d7effba509d7298ef49316ba2da7a2ea115f2a7ff691f875f6354666663cf386"}, | ||||||
| ] | ] | ||||||
| botocore = [ | botocore = [ | ||||||
|     {file = "botocore-1.23.41-py3-none-any.whl", hash = "sha256:41104e1c976c9c410387b3c7d265466b314f287a1c13fd4b543768135301058a"}, |     {file = "botocore-1.23.46-py3-none-any.whl", hash = "sha256:354bce55e5adc8e2fe106acfd455ce448f9b920d7b697d06faa8cf200fd6566b"}, | ||||||
|     {file = "botocore-1.23.41.tar.gz", hash = "sha256:9137c59c4eb1dee60ae3c710e94f56119a1b33b0b17ff3ad878fc2f4ce77843a"}, |     {file = "botocore-1.23.46.tar.gz", hash = "sha256:38dd4564839f531725b667db360ba7df2125ceb3752b0ba12759c3e918015b95"}, | ||||||
| ] | ] | ||||||
| bump2version = [ | bump2version = [ | ||||||
|     {file = "bump2version-1.0.1-py2.py3-none-any.whl", hash = "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410"}, |     {file = "bump2version-1.0.1-py2.py3-none-any.whl", hash = "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410"}, | ||||||
| @ -2344,53 +2368,50 @@ constantly = [ | |||||||
|     {file = "constantly-15.1.0.tar.gz", hash = "sha256:586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"}, |     {file = "constantly-15.1.0.tar.gz", hash = "sha256:586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35"}, | ||||||
| ] | ] | ||||||
| coverage = [ | coverage = [ | ||||||
|     {file = "coverage-6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b"}, |     {file = "coverage-6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e8071e7d9ba9f457fc674afc3de054450be2c9b195c470147fbbc082468d8ff7"}, | ||||||
|     {file = "coverage-6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0"}, |     {file = "coverage-6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86c91c511853dfda81c2cf2360502cb72783f4b7cebabef27869f00cbe1db07d"}, | ||||||
|     {file = "coverage-6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da"}, |     {file = "coverage-6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4ce3b647bd1792d4394f5690d9df6dc035b00bcdbc5595099c01282a59ae01"}, | ||||||
|     {file = "coverage-6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d"}, |     {file = "coverage-6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a491e159294d756e7fc8462f98175e2d2225e4dbe062cca7d3e0d5a75ba6260"}, | ||||||
|     {file = "coverage-6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739"}, |     {file = "coverage-6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d008e0f67ac800b0ca04d7914b8501312c8c6c00ad8c7ba17754609fae1231a"}, | ||||||
|     {file = "coverage-6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971"}, |     {file = "coverage-6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4578728c36de2801c1deb1c6b760d31883e62e33f33c7ba8f982e609dc95167d"}, | ||||||
|     {file = "coverage-6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840"}, |     {file = "coverage-6.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7ee317486593193e066fc5e98ac0ce712178c21529a85c07b7cb978171f25d53"}, | ||||||
|     {file = "coverage-6.2-cp310-cp310-win32.whl", hash = "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c"}, |     {file = "coverage-6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2bc85664b06ba42d14bb74d6ddf19d8bfc520cb660561d2d9ce5786ae72f71b5"}, | ||||||
|     {file = "coverage-6.2-cp310-cp310-win_amd64.whl", hash = "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f"}, |     {file = "coverage-6.3-cp310-cp310-win32.whl", hash = "sha256:27a94db5dc098c25048b0aca155f5fac674f2cf1b1736c5272ba28ead2fc267e"}, | ||||||
|     {file = "coverage-6.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76"}, |     {file = "coverage-6.3-cp310-cp310-win_amd64.whl", hash = "sha256:bde4aeabc0d1b2e52c4036c54440b1ad05beeca8113f47aceb4998bb7471e2c2"}, | ||||||
|     {file = "coverage-6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47"}, |     {file = "coverage-6.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:509c68c3e2015022aeda03b003dd68fa19987cdcf64e9d4edc98db41cfc45d30"}, | ||||||
|     {file = "coverage-6.2-cp311-cp311-win_amd64.whl", hash = "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64"}, |     {file = "coverage-6.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e4ff163602c5c77e7bb4ea81ba5d3b793b4419f8acd296aae149370902cf4e92"}, | ||||||
|     {file = "coverage-6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9"}, |     {file = "coverage-6.3-cp311-cp311-win_amd64.whl", hash = "sha256:d1675db48490e5fa0b300f6329ecb8a9a37c29b9ab64fa9c964d34111788ca2d"}, | ||||||
|     {file = "coverage-6.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d"}, |     {file = "coverage-6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7eed8459a2b81848cafb3280b39d7d49950d5f98e403677941c752e7e7ee47cb"}, | ||||||
|     {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48"}, |     {file = "coverage-6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b4285fde5286b946835a1a53bba3ad41ef74285ba9e8013e14b5ea93deaeafc"}, | ||||||
|     {file = "coverage-6.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e"}, |     {file = "coverage-6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4748349734110fd32d46ff8897b561e6300d8989a494ad5a0a2e4f0ca974fc7"}, | ||||||
|     {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d"}, |     {file = "coverage-6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:823f9325283dc9565ba0aa2d240471a93ca8999861779b2b6c7aded45b58ee0f"}, | ||||||
|     {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17"}, |     {file = "coverage-6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fff16a30fdf57b214778eff86391301c4509e327a65b877862f7c929f10a4253"}, | ||||||
|     {file = "coverage-6.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781"}, |     {file = "coverage-6.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:da1a428bdbe71f9a8c270c7baab29e9552ac9d0e0cba5e7e9a4c9ee6465d258d"}, | ||||||
|     {file = "coverage-6.2-cp36-cp36m-win32.whl", hash = "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a"}, |     {file = "coverage-6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7d82c610a2e10372e128023c5baf9ce3d270f3029fe7274ff5bc2897c68f1318"}, | ||||||
|     {file = "coverage-6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0"}, |     {file = "coverage-6.3-cp37-cp37m-win32.whl", hash = "sha256:11e61c5548ecf74ea1f8b059730b049871f0e32b74f88bd0d670c20c819ad749"}, | ||||||
|     {file = "coverage-6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49"}, |     {file = "coverage-6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:8e0c3525b1a182c8ffc9bca7e56b521e0c2b8b3e82f033c8e16d6d721f1b54d6"}, | ||||||
|     {file = "coverage-6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521"}, |     {file = "coverage-6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a189036c50dcd56100746139a459f0d27540fef95b09aba03e786540b8feaa5f"}, | ||||||
|     {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884"}, |     {file = "coverage-6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32168001f33025fd756884d56d01adebb34e6c8c0b3395ca8584cdcee9c7c9d2"}, | ||||||
|     {file = "coverage-6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa"}, |     {file = "coverage-6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5d79c9af3f410a2b5acad91258b4ae179ee9c83897eb9de69151b179b0227f5"}, | ||||||
|     {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64"}, |     {file = "coverage-6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:85c5fc9029043cf8b07f73fbb0a7ab6d3b717510c3b5642b77058ea55d7cacde"}, | ||||||
|     {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617"}, |     {file = "coverage-6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7596aa2f2b8fa5604129cfc9a27ad9beec0a96f18078cb424d029fdd707468d"}, | ||||||
|     {file = "coverage-6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8"}, |     {file = "coverage-6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ce443a3e6df90d692c38762f108fc4c88314bf477689f04de76b3f252e7a351c"}, | ||||||
|     {file = "coverage-6.2-cp37-cp37m-win32.whl", hash = "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4"}, |     {file = "coverage-6.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:012157499ec4f135fc36cd2177e3d1a1840af9b236cbe80e9a5ccfc83d912a69"}, | ||||||
|     {file = "coverage-6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74"}, |     {file = "coverage-6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a34d313105cdd0d3644c56df2d743fe467270d6ab93b5d4a347eb9fec8924d6"}, | ||||||
|     {file = "coverage-6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e"}, |     {file = "coverage-6.3-cp38-cp38-win32.whl", hash = "sha256:6e78b1e25e5c5695dea012be473e442f7094d066925604be20b30713dbd47f89"}, | ||||||
|     {file = "coverage-6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58"}, |     {file = "coverage-6.3-cp38-cp38-win_amd64.whl", hash = "sha256:433b99f7b0613bdcdc0b00cc3d39ed6d756797e3b078d2c43f8a38288520aec6"}, | ||||||
|     {file = "coverage-6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc"}, |     {file = "coverage-6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9ed3244b415725f08ca3bdf02ed681089fd95e9465099a21c8e2d9c5d6ca2606"}, | ||||||
|     {file = "coverage-6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd"}, |     {file = "coverage-6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab4fc4b866b279740e0d917402f0e9a08683e002f43fa408e9655818ed392196"}, | ||||||
|     {file = "coverage-6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953"}, |     {file = "coverage-6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8582e9280f8d0f38114fe95a92ae8d0790b56b099d728cc4f8a2e14b1c4a18c"}, | ||||||
|     {file = "coverage-6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475"}, |     {file = "coverage-6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c72bb4679283c6737f452eeb9b2a0e570acaef2197ad255fb20162adc80bea76"}, | ||||||
|     {file = "coverage-6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57"}, |     {file = "coverage-6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca29c352389ea27a24c79acd117abdd8a865c6eb01576b6f0990cd9a4e9c9f48"}, | ||||||
|     {file = "coverage-6.2-cp38-cp38-win32.whl", hash = "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c"}, |     {file = "coverage-6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:152cc2624381df4e4e604e21bd8e95eb8059535f7b768c1fb8b8ae0b26f47ab0"}, | ||||||
|     {file = "coverage-6.2-cp38-cp38-win_amd64.whl", hash = "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2"}, |     {file = "coverage-6.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:51372e24b1f7143ee2df6b45cff6a721f3abe93b1e506196f3ffa4155c2497f7"}, | ||||||
|     {file = "coverage-6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd"}, |     {file = "coverage-6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:72d9d186508325a456475dd05b1756f9a204c7086b07fffb227ef8cee03b1dc2"}, | ||||||
|     {file = "coverage-6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685"}, |     {file = "coverage-6.3-cp39-cp39-win32.whl", hash = "sha256:649df3641eb351cdfd0d5533c92fc9df507b6b2bf48a7ef8c71ab63cbc7b5c3c"}, | ||||||
|     {file = "coverage-6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c"}, |     {file = "coverage-6.3-cp39-cp39-win_amd64.whl", hash = "sha256:e67ccd53da5958ea1ec833a160b96357f90859c220a00150de011b787c27b98d"}, | ||||||
|     {file = "coverage-6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3"}, |     {file = "coverage-6.3-pp36.pp37.pp38-none-any.whl", hash = "sha256:27ac7cb84538e278e07569ceaaa6f807a029dc194b1c819a9820b9bb5dbf63ab"}, | ||||||
|     {file = "coverage-6.2-cp39-cp39-win32.whl", hash = "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282"}, |     {file = "coverage-6.3.tar.gz", hash = "sha256:987a84ff98a309994ca77ed3cc4b92424f824278e48e4bf7d1bb79a63cfe2099"}, | ||||||
|     {file = "coverage-6.2-cp39-cp39-win_amd64.whl", hash = "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644"}, |  | ||||||
|     {file = "coverage-6.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de"}, |  | ||||||
|     {file = "coverage-6.2.tar.gz", hash = "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8"}, |  | ||||||
| ] | ] | ||||||
| cryptography = [ | cryptography = [ | ||||||
|     {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b"}, |     {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b"}, | ||||||
| @ -2435,8 +2456,8 @@ deprecated = [ | |||||||
|     {file = "Deprecated-1.2.13.tar.gz", hash = "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d"}, |     {file = "Deprecated-1.2.13.tar.gz", hash = "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d"}, | ||||||
| ] | ] | ||||||
| django = [ | django = [ | ||||||
|     {file = "Django-4.0.1-py3-none-any.whl", hash = "sha256:7cd8e8a3ed2bc0dfda05ce1e53a9c81b30eefd7aa350e538a18884475e4d4ce2"}, |     {file = "Django-4.0.2-py3-none-any.whl", hash = "sha256:996495c58bff749232426c88726d8cd38d24c94d7c1d80835aafffa9bc52985a"}, | ||||||
|     {file = "Django-4.0.1.tar.gz", hash = "sha256:2485eea3cc4c3bae13080dee866ebf90ba9f98d1afe8fda89bfb0eb2e218ef86"}, |     {file = "Django-4.0.2.tar.gz", hash = "sha256:110fb58fb12eca59e072ad59fc42d771cd642dd7a2f2416582aa9da7a8ef954a"}, | ||||||
| ] | ] | ||||||
| django-dbbackup = [ | django-dbbackup = [ | ||||||
|     {file = "django-dbbackup-4.0.0b0.tar.gz", hash = "sha256:aca81265dab91b3a73c3a730cf168d946621c28002f1321d4c33910ba7c63634"}, |     {file = "django-dbbackup-4.0.0b0.tar.gz", hash = "sha256:aca81265dab91b3a73c3a730cf168d946621c28002f1321d4c33910ba7c63634"}, | ||||||
| @ -3053,36 +3074,36 @@ pycparser = [ | |||||||
|     {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, |     {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, | ||||||
| ] | ] | ||||||
| pycryptodome = [ | pycryptodome = [ | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e468724173df02f9d83f3fea830bf0d04aa291b5add22b4a78e01c97aab04873"}, |     {file = "pycryptodome-3.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:bd800856e6dea6924504795ae4ec0d822e912e0a9a215e73b77b585c4d15a0f7"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1fb7a6f222072412f320b9e48d3ce981920efbfce37b06d028ec9bd94093b37f"}, |     {file = "pycryptodome-3.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:625f78ad69aa3c45e19b85b9e9cae3a30aa4a1de6b908981a63426b88e860489"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4f1b594d0cf35bd12ec4244df1155a7f565bf6e6245976ac36174c1564688c90"}, |     {file = "pycryptodome-3.14.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:a1c116dd7a00aac631f67920912fd8ef7a5ad3402cd4d497c6f5cc6b8115747b"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:9ea70f6c3f6566159e3798e4593a4a8016994a0080ac29a45200615b45091a1b"}, |     {file = "pycryptodome-3.14.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0d0b6cca6b707b2c7cd4177c2d3cd950efa959ed8f01c30e676f102c68156f00"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f7aad304575d075faf2806977b726b67da7ba294adc97d878f92a062e357a56a"}, |     {file = "pycryptodome-3.14.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9d939a257117cc8c6840ad69f149b3ca5e07268cfe0429bd9feec0f91da2343d"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:702446a012fd9337b9327d168bb0c7dc714eb93ad361f6f61af9ca8305a301f1"}, |     {file = "pycryptodome-3.14.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:41dbb8c2129d43f34ed555cbd365d5e8f023ef0f9238fd9cd0302086b15a38b3"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27m-win32.whl", hash = "sha256:681ac47c538c64305d710eaed2bb49532f62b3f4c93aa7c423c520df981392e5"}, |     {file = "pycryptodome-3.14.0-cp27-cp27m-win32.whl", hash = "sha256:9b454af09914807cef1222d100a8c523737a160347cb8d699facc4bdfb9fe725"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27m-win_amd64.whl", hash = "sha256:7b3478a187d897f003b2aa1793bcc59463e8d57a42e2aafbcbbe9cd47ec46863"}, |     {file = "pycryptodome-3.14.0-cp27-cp27m-win_amd64.whl", hash = "sha256:95bac6e55411650933f3b615e57bf0966bf08f3ce07c01f07482ced95f18cbec"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:eec02d9199af4b1ccfe1f9c587691a07a1fa39d949d2c1dc69d079ab9af8212f"}, |     {file = "pycryptodome-3.14.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:0ffbca43c1788243421a8583d85acb59f4cd0b82b001c485fdc3fbfd8fd0804f"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9c8e0e6c5e982699801b20fa74f43c19aa080d2b53a39f3c132d35958e153bd4"}, |     {file = "pycryptodome-3.14.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:69b85d78f7db628370d2cc87f1c41a449f6460896ba95f412173618f75027c2c"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f5457e44d3f26d9946091e92b28f3e970a56538b96c87b4b155a84e32a40b7b5"}, |     {file = "pycryptodome-3.14.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:bba348d2823315ab8ebe44f0b2fc2ff8dfac8de881713a08def3dadcfc8e92bb"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:88d6d54e83cf9bbd665ce1e7b9079983ee2d97a05f42e0569ff00a70f1dd8b1e"}, |     {file = "pycryptodome-3.14.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:7d667daa851b1f9a20f2b5cad3cff13fba5204bc2f857d12f27c25b178d8629b"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:72de8c4d71e6b11d54528bb924447fa4fdabcbb3d76cc0e7f61d3b6075def6b3"}, |     {file = "pycryptodome-3.14.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:74918d5de06b12fef2255135bede41307a5f7b929b145ad867111525aea075dc"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:008ef2c631f112cd5a58736e0b29f4a28b4bb853e68878689f8b476fd56e0691"}, |     {file = "pycryptodome-3.14.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c2b6faabd09d2876f9050f8af5d78046d81fe856f99e801c2ddab85b59602007"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:51ebe9624ad0a0b4da1aaaa2d43aabadf8537737fd494cee0ffa37cd6326de02"}, |     {file = "pycryptodome-3.14.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:22a8629315c76d2bec57bc4fd67eb7e01664c3e3b9579df40f530ee5821db1de"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:deede160bdf87ddb71f0a1314ad5a267b1a960be314ea7dc6b7ad86da6da89a3"}, |     {file = "pycryptodome-3.14.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:7e3851e4fbbab72d9b30f98a504f450cc61e497e8e4b0be8205dc198703eee4d"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:857c16bffd938254e3a834cd6b2a755ed24e1a953b1a86e33da136d3e4c16a6f"}, |     {file = "pycryptodome-3.14.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:9006f17944efaacc3be364c01c2253c00a00f0b5fa5a1a85a1191efd861e764d"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:ca6db61335d07220de0b665bfee7b8e9615b2dfc67a54016db4826dac34c2dd2"}, |     {file = "pycryptodome-3.14.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:8f0da308fca149b4c4da78e1388f82d8dd167e0ce12992a44f81b506cede3109"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:073dedf0f9c490ae22ca081b86357646ac9b76f3e2bd89119d137fc697a9e3b6"}, |     {file = "pycryptodome-3.14.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:d186e34747985fbd94df7ed4d621f8377165053a06872314c2a594af34741655"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp35-abi3-win32.whl", hash = "sha256:e3affa03c49cce7b0a9501cc7f608d4f8e61fb2522b276d599ac049b5955576d"}, |     {file = "pycryptodome-3.14.0-cp35-abi3-win32.whl", hash = "sha256:2ed4da8f8afe44895c1f49ae1141a55b15d81dc745b5baa7b7a7265d7b40b81e"}, | ||||||
|     {file = "pycryptodome-3.13.0-cp35-abi3-win_amd64.whl", hash = "sha256:e5d72be02b17e6bd7919555811264403468d1d052fa67c946e402257c3c29a27"}, |     {file = "pycryptodome-3.14.0-cp35-abi3-win_amd64.whl", hash = "sha256:11167a1f892283e5320feb5e81589fd041a1822b94c047820f00bc03eb98a9f7"}, | ||||||
|     {file = "pycryptodome-3.13.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:0896d5d15ffe584d46cb9b69a75cf14a2bc8f6daf635b7bf16c1b041342a44b1"}, |     {file = "pycryptodome-3.14.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:1714ea5f83bcff25e8ae4640e22359d7a0815157a29d9f4eebc2b9e975a3cda0"}, | ||||||
|     {file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:e420cdfca73f80fe15f79bb34756959945231a052440813e5fce531e6e96331a"}, |     {file = "pycryptodome-3.14.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:3a011b9fe674bd21056613e88a3e660c56f1b47263138ebf420aa3ee4b8b0107"}, | ||||||
|     {file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:720fafdf3e5c5de93039d8308f765cc60b8e9e7e852ad7135aa65dd89238191f"}, |     {file = "pycryptodome-3.14.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:3fd50e3682ac3a684ace5b90ba1aef8090a78eeadf38c1ec385aad3a599cfd68"}, | ||||||
|     {file = "pycryptodome-3.13.0-pp27-pypy_73-win32.whl", hash = "sha256:7a8b0e526ff239b4f4c61dd6898e2474d609843ffc437267f3a27ddff626e6f6"}, |     {file = "pycryptodome-3.14.0-pp27-pypy_73-win32.whl", hash = "sha256:08be50d4195edd595df580077bbeec5599d0e5aa0cc468083178ae870e0b29f4"}, | ||||||
|     {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d92a5eddffb0ad39f582f07c1de26e9daf6880e3e782a94bb7ebaf939567f8bf"}, |     {file = "pycryptodome-3.14.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:16c171dd969c9046b7b304c6ba0c643624dcf18093a66bd30b8b091703f177a2"}, | ||||||
|     {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:cb9453c981554984c6f5c5ce7682d7286e65e2173d7416114c3593a977a01bf5"}, |     {file = "pycryptodome-3.14.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:89bb56cfd1fb74663842710bc41a6be26dafceb60eb8d432536891aea08a3740"}, | ||||||
|     {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:765b8b16bc1fd699e183dde642c7f2653b8f3c9c1a50051139908e9683f97732"}, |     {file = "pycryptodome-3.14.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:c30a98c8718ae93d44680a7038adb484a520319860747ba43b6cd0a20f6b5984"}, | ||||||
|     {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:b3af53dddf848afb38b3ac2bae7159ddad1feb9bac14aa3acec6ef1797b82f8d"}, |     {file = "pycryptodome-3.14.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:e972f566ef7b821c8b958dab64174afa072f8271b779e32444ad7c127b0a84b2"}, | ||||||
|     {file = "pycryptodome-3.13.0.tar.gz", hash = "sha256:95bacf9ff7d1b90bba537d3f5f6c834efe6bfbb1a0195cb3573f29e6716ef08d"}, |     {file = "pycryptodome-3.14.0.tar.gz", hash = "sha256:ceea92a4b8ba6c50d8d70f2efbb4ea14b002dac4160ce4dda33f1b7442f8158a"}, | ||||||
| ] | ] | ||||||
| pyjwt = [ | pyjwt = [ | ||||||
|     {file = "PyJWT-2.3.0-py3-none-any.whl", hash = "sha256:e0c4bb8d9f0af0c7f5b1ec4c5036309617d03d56932877f2f7a0beeb5318322f"}, |     {file = "PyJWT-2.3.0-py3-none-any.whl", hash = "sha256:e0c4bb8d9f0af0c7f5b1ec4c5036309617d03d56932877f2f7a0beeb5318322f"}, | ||||||
| @ -3229,9 +3250,8 @@ requests-mock = [ | |||||||
|     {file = "requests_mock-1.9.3-py2.py3-none-any.whl", hash = "sha256:0a2d38a117c08bb78939ec163522976ad59a6b7fdd82b709e23bb98004a44970"}, |     {file = "requests_mock-1.9.3-py2.py3-none-any.whl", hash = "sha256:0a2d38a117c08bb78939ec163522976ad59a6b7fdd82b709e23bb98004a44970"}, | ||||||
| ] | ] | ||||||
| requests-oauthlib = [ | requests-oauthlib = [ | ||||||
|     {file = "requests-oauthlib-1.3.0.tar.gz", hash = "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"}, |     {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, | ||||||
|     {file = "requests_oauthlib-1.3.0-py2.py3-none-any.whl", hash = "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d"}, |     {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"}, | ||||||
|     {file = "requests_oauthlib-1.3.0-py3.7.egg", hash = "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc"}, |  | ||||||
| ] | ] | ||||||
| rsa = [ | rsa = [ | ||||||
|     {file = "rsa-4.8-py3-none-any.whl", hash = "sha256:95c5d300c4e879ee69708c428ba566c59478fd653cc3a22243eeb8ed846950bb"}, |     {file = "rsa-4.8-py3-none-any.whl", hash = "sha256:95c5d300c4e879ee69708c428ba566c59478fd653cc3a22243eeb8ed846950bb"}, | ||||||
| @ -3245,8 +3265,8 @@ selenium = [ | |||||||
|     {file = "selenium-4.1.0-py3-none-any.whl", hash = "sha256:27e7b64df961d609f3d57237caa0df123abbbe22d038f2ec9e332fb90ec1a939"}, |     {file = "selenium-4.1.0-py3-none-any.whl", hash = "sha256:27e7b64df961d609f3d57237caa0df123abbbe22d038f2ec9e332fb90ec1a939"}, | ||||||
| ] | ] | ||||||
| sentry-sdk = [ | sentry-sdk = [ | ||||||
|     {file = "sentry-sdk-1.5.3.tar.gz", hash = "sha256:141da032f0fa4c56f9af6b361fda57360af1789576285bd1944561f9c274f9c0"}, |     {file = "sentry-sdk-1.5.4.tar.gz", hash = "sha256:f7e54567937ebcbe938c4df1075ec891587faeb7c74184b88cf2894e47c86116"}, | ||||||
|     {file = "sentry_sdk-1.5.3-py2.py3-none-any.whl", hash = "sha256:9aeff2a47f4038460296b920bf4d269284e8454e1c67547ee002ccafd9c2442b"}, |     {file = "sentry_sdk-1.5.4-py2.py3-none-any.whl", hash = "sha256:4fc7960a82c95d906a0514cf4d9aacba1743eb9863a5b7c2a01c525a7d9b21e6"}, | ||||||
| ] | ] | ||||||
| service-identity = [ | service-identity = [ | ||||||
|     {file = "service-identity-21.1.0.tar.gz", hash = "sha256:6e6c6086ca271dc11b033d17c3a8bea9f24ebff920c587da090afc9519419d34"}, |     {file = "service-identity-21.1.0.tar.gz", hash = "sha256:6e6c6086ca271dc11b033d17c3a8bea9f24ebff920c587da090afc9519419d34"}, | ||||||
| @ -3386,8 +3406,8 @@ urllib3 = [ | |||||||
|     {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, |     {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, | ||||||
| ] | ] | ||||||
| uvicorn = [ | uvicorn = [ | ||||||
|     {file = "uvicorn-0.17.0-py3-none-any.whl", hash = "sha256:0b89c91bb8fe84c4bded9996af13c4b8c0de799d29bffeaa0c8ad298f2be0934"}, |     {file = "uvicorn-0.17.1-py3-none-any.whl", hash = "sha256:8b16d9ecb76500f7804184f182835fe8a2b54716d3b0b6bb2da0b2b192f62c73"}, | ||||||
|     {file = "uvicorn-0.17.0.tar.gz", hash = "sha256:192c2422b056a3beb512c6c260bf77a7a884204a4ae41856719c1913ead63bbb"}, |     {file = "uvicorn-0.17.1.tar.gz", hash = "sha256:dffbacb8cc25d924d68d231d2c478c4fe6727c36537d8de21e5de591b37afc41"}, | ||||||
| ] | ] | ||||||
| uvloop = [ | uvloop = [ | ||||||
|     {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, |     {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ pythonPlatform = "Linux" | |||||||
|  |  | ||||||
| [tool.black] | [tool.black] | ||||||
| line-length = 100 | line-length = 100 | ||||||
| target-version = ['py39'] | target-version = ['py310'] | ||||||
| exclude = 'node_modules' | exclude = 'node_modules' | ||||||
|  |  | ||||||
| [tool.isort] | [tool.isort] | ||||||
| @ -92,7 +92,7 @@ addopts = "-p no:celery --junitxml=unittest.xml" | |||||||
|  |  | ||||||
| [tool.poetry] | [tool.poetry] | ||||||
| name = "authentik" | name = "authentik" | ||||||
| version = "2022.1.2" | version = "2022.1.4" | ||||||
| description = "" | description = "" | ||||||
| authors = ["Jens Langhammer <jens.langhammer@beryju.org>"] | authors = ["Jens Langhammer <jens.langhammer@beryju.org>"] | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| openapi: 3.0.3 | openapi: 3.0.3 | ||||||
| info: | info: | ||||||
|   title: authentik |   title: authentik | ||||||
|   version: 2022.1.2 |   version: 2022.1.4 | ||||||
|   description: Making authentication simple. |   description: Making authentication simple. | ||||||
|   contact: |   contact: | ||||||
|     email: hello@beryju.org |     email: hello@beryju.org | ||||||
|  | |||||||
| @ -3,7 +3,11 @@ from authentik.lib.generators import generate_id | |||||||
| from yaml import safe_dump | from yaml import safe_dump | ||||||
|  |  | ||||||
| with open("local.env.yml", "w") as _config: | with open("local.env.yml", "w") as _config: | ||||||
|     safe_dump({ |     safe_dump( | ||||||
|  |         { | ||||||
|             "log_level": "debug", |             "log_level": "debug", | ||||||
|             "secret_key": generate_id(), |             "secret_key": generate_id(), | ||||||
|     }, _config, default_flow_style=False) |         }, | ||||||
|  |         _config, | ||||||
|  |         default_flow_style=False, | ||||||
|  |     ) | ||||||
|  | |||||||
| @ -13,7 +13,10 @@ if os.environ.get(env_pr_branch, "") != "": | |||||||
| should_build = str(os.environ.get("DOCKER_USERNAME", "") != "").lower() | should_build = str(os.environ.get("DOCKER_USERNAME", "") != "").lower() | ||||||
|  |  | ||||||
| print("##[set-output name=branchName]%s" % branch_name) | print("##[set-output name=branchName]%s" % branch_name) | ||||||
| print("##[set-output name=branchNameContainer]%s" % branch_name.replace("refs/heads/", "").replace("/", "-")) | print( | ||||||
|  |     "##[set-output name=branchNameContainer]%s" | ||||||
|  |     % branch_name.replace("refs/heads/", "").replace("/", "-") | ||||||
|  | ) | ||||||
| print("##[set-output name=timestamp]%s" % int(time())) | print("##[set-output name=timestamp]%s" % int(time())) | ||||||
| print("##[set-output name=sha]%s" % os.environ[sha]) | print("##[set-output name=sha]%s" % os.environ[sha]) | ||||||
| print("##[set-output name=shouldBuild]%s" % should_build) | print("##[set-output name=shouldBuild]%s" % should_build) | ||||||
|  | |||||||
| @ -8,14 +8,9 @@ TSCONFIG_ESM = { | |||||||
|         "module": "esnext", |         "module": "esnext", | ||||||
|         "moduleResolution": "node", |         "moduleResolution": "node", | ||||||
|         "outDir": "./dist/esm", |         "outDir": "./dist/esm", | ||||||
|     "typeRoots": [ |         "typeRoots": ["node_modules/@types"], | ||||||
|       "node_modules/@types" |  | ||||||
|     ] |  | ||||||
|     }, |     }, | ||||||
|   "exclude": [ |     "exclude": ["dist", "node_modules"], | ||||||
|     "dist", |  | ||||||
|     "node_modules" |  | ||||||
|   ] |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										559
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										559
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -14,15 +14,15 @@ | |||||||
|                 "@babel/plugin-transform-runtime": "^7.16.10", |                 "@babel/plugin-transform-runtime": "^7.16.10", | ||||||
|                 "@babel/preset-env": "^7.16.11", |                 "@babel/preset-env": "^7.16.11", | ||||||
|                 "@babel/preset-typescript": "^7.16.7", |                 "@babel/preset-typescript": "^7.16.7", | ||||||
|                 "@formatjs/intl-listformat": "^6.5.0", |                 "@formatjs/intl-listformat": "^6.5.1", | ||||||
|                 "@fortawesome/fontawesome-free": "^5.15.4", |                 "@fortawesome/fontawesome-free": "^5.15.4", | ||||||
|                 "@goauthentik/api": "^2022.1.1-1642874681", |                 "@goauthentik/api": "^2022.1.3-1643236150", | ||||||
|                 "@jackfranklin/rollup-plugin-markdown": "^0.3.0", |                 "@jackfranklin/rollup-plugin-markdown": "^0.3.0", | ||||||
|                 "@lingui/cli": "^3.13.1", |                 "@lingui/cli": "^3.13.2", | ||||||
|                 "@lingui/core": "^3.13.1", |                 "@lingui/core": "^3.13.2", | ||||||
|                 "@lingui/detect-locale": "^3.13.1", |                 "@lingui/detect-locale": "^3.13.2", | ||||||
|                 "@lingui/macro": "^3.13.1", |                 "@lingui/macro": "^3.13.2", | ||||||
|                 "@patternfly/patternfly": "^4.164.2", |                 "@patternfly/patternfly": "^4.171.1", | ||||||
|                 "@polymer/iron-form": "^3.0.1", |                 "@polymer/iron-form": "^3.0.1", | ||||||
|                 "@polymer/paper-input": "^3.2.1", |                 "@polymer/paper-input": "^3.2.1", | ||||||
|                 "@rollup/plugin-babel": "^5.3.0", |                 "@rollup/plugin-babel": "^5.3.0", | ||||||
| @ -30,34 +30,34 @@ | |||||||
|                 "@rollup/plugin-node-resolve": "^13.1.3", |                 "@rollup/plugin-node-resolve": "^13.1.3", | ||||||
|                 "@rollup/plugin-replace": "^3.0.1", |                 "@rollup/plugin-replace": "^3.0.1", | ||||||
|                 "@rollup/plugin-typescript": "^8.3.0", |                 "@rollup/plugin-typescript": "^8.3.0", | ||||||
|                 "@sentry/browser": "^6.16.1", |                 "@sentry/browser": "^6.17.3", | ||||||
|                 "@sentry/tracing": "^6.16.1", |                 "@sentry/tracing": "^6.17.3", | ||||||
|                 "@squoosh/cli": "^0.7.2", |                 "@squoosh/cli": "^0.7.2", | ||||||
|                 "@trivago/prettier-plugin-sort-imports": "^3.1.1", |                 "@trivago/prettier-plugin-sort-imports": "^3.1.1", | ||||||
|                 "@types/chart.js": "^2.9.35", |                 "@types/chart.js": "^2.9.35", | ||||||
|                 "@types/codemirror": "5.60.5", |                 "@types/codemirror": "5.60.5", | ||||||
|                 "@types/grecaptcha": "^3.0.3", |                 "@types/grecaptcha": "^3.0.3", | ||||||
|                 "@typescript-eslint/eslint-plugin": "^5.10.0", |                 "@typescript-eslint/eslint-plugin": "^5.10.2", | ||||||
|                 "@typescript-eslint/parser": "^5.10.0", |                 "@typescript-eslint/parser": "^5.10.2", | ||||||
|                 "@webcomponents/webcomponentsjs": "^2.6.0", |                 "@webcomponents/webcomponentsjs": "^2.6.0", | ||||||
|                 "babel-plugin-macros": "^3.1.0", |                 "babel-plugin-macros": "^3.1.0", | ||||||
|                 "base64-js": "^1.5.1", |                 "base64-js": "^1.5.1", | ||||||
|                 "chart.js": "^3.7.0", |                 "chart.js": "^3.7.0", | ||||||
|                 "chartjs-adapter-moment": "^1.0.0", |                 "chartjs-adapter-moment": "^1.0.0", | ||||||
|                 "codemirror": "^5.65.1", |                 "codemirror": "^5.65.1", | ||||||
|                 "construct-style-sheets-polyfill": "^3.0.5", |                 "construct-style-sheets-polyfill": "^3.1.0", | ||||||
|                 "country-flag-icons": "^1.4.19", |                 "country-flag-icons": "^1.4.20", | ||||||
|                 "eslint": "^8.7.0", |                 "eslint": "^8.8.0", | ||||||
|                 "eslint-config-google": "^0.14.0", |                 "eslint-config-google": "^0.14.0", | ||||||
|                 "eslint-plugin-custom-elements": "0.0.4", |                 "eslint-plugin-custom-elements": "0.0.4", | ||||||
|                 "eslint-plugin-lit": "^1.6.1", |                 "eslint-plugin-lit": "^1.6.1", | ||||||
|                 "flowchart.js": "^1.17.0", |                 "flowchart.js": "^1.17.0", | ||||||
|                 "fuse.js": "^6.5.3", |                 "fuse.js": "^6.5.3", | ||||||
|                 "lit": "^2.1.1", |                 "lit": "^2.1.2", | ||||||
|                 "moment": "^2.29.1", |                 "moment": "^2.29.1", | ||||||
|                 "prettier": "^2.5.1", |                 "prettier": "^2.5.1", | ||||||
|                 "rapidoc": "^9.1.4", |                 "rapidoc": "^9.1.4", | ||||||
|                 "rollup": "^2.66.0", |                 "rollup": "^2.66.1", | ||||||
|                 "rollup-plugin-copy": "^3.4.0", |                 "rollup-plugin-copy": "^3.4.0", | ||||||
|                 "rollup-plugin-cssimport": "^1.0.2", |                 "rollup-plugin-cssimport": "^1.0.2", | ||||||
|                 "rollup-plugin-minify-html-literals": "^1.2.6", |                 "rollup-plugin-minify-html-literals": "^1.2.6", | ||||||
| @ -1717,28 +1717,28 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@formatjs/ecma402-abstract": { |         "node_modules/@formatjs/ecma402-abstract": { | ||||||
|             "version": "1.11.1", |             "version": "1.11.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.1.tgz", |             "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.2.tgz", | ||||||
|             "integrity": "sha512-tgtNODZUGuUI6PAcnvaLZpGrZLVkXnnAvgzOiueYMzFdOdcOw4iH1WKhCe3+r6VR8rHKToJ2HksUGNCB+zt/bg==", |             "integrity": "sha512-qDgOL0vtfJ51cc0pRbFB/oXc4qDbamG22Z6h/QWy6FBxaQgppiy8JF0iYbmNO35cC8r88bQGsgfd/eM6/eTEQQ==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@formatjs/intl-localematcher": "0.2.22", |                 "@formatjs/intl-localematcher": "0.2.23", | ||||||
|                 "tslib": "^2.1.0" |                 "tslib": "^2.1.0" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@formatjs/intl-listformat": { |         "node_modules/@formatjs/intl-listformat": { | ||||||
|             "version": "6.5.0", |             "version": "6.5.1", | ||||||
|             "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-6.5.0.tgz", |             "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-6.5.1.tgz", | ||||||
|             "integrity": "sha512-gVyAV5QWWtq84MK4cAyJITW+Wb74c2+FT+wa8jhSPxXUky9B5z/k/Ff7or4Vb3KV0YYZuVBQ/vMIoD8Gr182ww==", |             "integrity": "sha512-ijsOM7J7aNnGx+1JYUGWgMAcisnK0CxdlPx7KJpUXKj9Mf2Ph28H2WMTL1h1xv9T7SSvH0Nd6asI0Qw4ffw17w==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@formatjs/ecma402-abstract": "1.11.1", |                 "@formatjs/ecma402-abstract": "1.11.2", | ||||||
|                 "@formatjs/intl-localematcher": "0.2.22", |                 "@formatjs/intl-localematcher": "0.2.23", | ||||||
|                 "tslib": "^2.1.0" |                 "tslib": "^2.1.0" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@formatjs/intl-localematcher": { |         "node_modules/@formatjs/intl-localematcher": { | ||||||
|             "version": "0.2.22", |             "version": "0.2.23", | ||||||
|             "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.22.tgz", |             "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.23.tgz", | ||||||
|             "integrity": "sha512-z+TvbHW8Q/g2l7/PnfUl0mV9gWxV4d0HT6GQyzkO5QI6QjCvCZGiztnmLX7zoyS16uSMvZ2PoMDfSK9xvZkRRA==", |             "integrity": "sha512-oCe2TOciTtB1bEbJ85EvYrXQxD0epusmVJfJ7AduO0tlbXP42CmDIYIH2CZ+kP2GE+PTLQD1Hbt9kpOpl939MQ==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "tslib": "^2.1.0" |                 "tslib": "^2.1.0" | ||||||
|             } |             } | ||||||
| @ -1753,9 +1753,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@goauthentik/api": { |         "node_modules/@goauthentik/api": { | ||||||
|             "version": "2022.1.1-1642874681", |             "version": "2022.1.3-1643236150", | ||||||
|             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2022.1.1-1642874681.tgz", |             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2022.1.3-1643236150.tgz", | ||||||
|             "integrity": "sha512-MOFu1g/5dvQu+BTj8qqc2IMT9fpBICqzERkC949JiDxDSqHg0kuqmxe23vPnFceryQM5zktTBJ+VxXjzR9lX3g==" |             "integrity": "sha512-eteq3Y/4eME6bffuQy8cB6ZrV3DB7rk1IKdvzfUbr9I1hSRzXEBtlzmXp+lhY6RxlEy9hhcJHZO8/OCKFI5l9A==" | ||||||
|         }, |         }, | ||||||
|         "node_modules/@humanwhocodes/config-array": { |         "node_modules/@humanwhocodes/config-array": { | ||||||
|             "version": "0.9.2", |             "version": "0.9.2", | ||||||
| @ -1865,13 +1865,13 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@lingui/babel-plugin-extract-messages": { |         "node_modules/@lingui/babel-plugin-extract-messages": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-3.13.2.tgz", | ||||||
|             "integrity": "sha512-K0ekhQI49ZTE90bVxvndqdxO80X1ZjacVdznWn4RJq6EEN9ElppMKkWUmAe/vfHGJRCH/2aUIp73xvaXPJPbGg==", |             "integrity": "sha512-SyvwfrPqkyj9XM2CB/YK25o0Zi+B8ikoCENwqNSk7201n80YfOJoksc6lQ3X/QODqvy+iuOsiQrVT3qzKblOmg==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@babel/generator": "^7.11.6", |                 "@babel/generator": "^7.11.6", | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "@lingui/conf": "^3.13.1", |                 "@lingui/conf": "^3.13.2", | ||||||
|                 "mkdirp": "^1.0.4" |                 "mkdirp": "^1.0.4" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -1879,17 +1879,17 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@lingui/cli": { |         "node_modules/@lingui/cli": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-3.13.2.tgz", | ||||||
|             "integrity": "sha512-JGfbdAn1qxHBjuhnLeERMhCLe7UXSFafqq9S//g3+VNHKHfVHfa0CKFUmISMDKMLFdKmbdJCZpYU3DRZNrUGyQ==", |             "integrity": "sha512-wPYlsKI7hx1hyntc6enUVUdKVwBM8XW+DnwHslWWw4ShMNvh98gLgAOW1ajXtUym7x0WTjhR+/s436hdxfZ/Og==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@babel/generator": "^7.11.6", |                 "@babel/generator": "^7.11.6", | ||||||
|                 "@babel/parser": "^7.11.5", |                 "@babel/parser": "^7.11.5", | ||||||
|                 "@babel/plugin-syntax-jsx": "^7.10.4", |                 "@babel/plugin-syntax-jsx": "^7.10.4", | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "@babel/types": "^7.11.5", |                 "@babel/types": "^7.11.5", | ||||||
|                 "@lingui/babel-plugin-extract-messages": "^3.13.1", |                 "@lingui/babel-plugin-extract-messages": "^3.13.2", | ||||||
|                 "@lingui/conf": "^3.13.1", |                 "@lingui/conf": "^3.13.2", | ||||||
|                 "babel-plugin-macros": "^3.0.1", |                 "babel-plugin-macros": "^3.0.1", | ||||||
|                 "bcp-47": "^1.0.7", |                 "bcp-47": "^1.0.7", | ||||||
|                 "chalk": "^4.1.0", |                 "chalk": "^4.1.0", | ||||||
| @ -1992,9 +1992,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@lingui/conf": { |         "node_modules/@lingui/conf": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-3.13.2.tgz", | ||||||
|             "integrity": "sha512-xWJVdgNiGqYzkYIxHg4c6KqSNleN5/96M2ly+GzBOmA5H75r4hz27DfQpxuC4FuBUAPC+Mk1HTBO9/aFO0BCZg==", |             "integrity": "sha512-JhiIBxnh2X4QmLP0/+dnTBc7xnZ6qk5MRsQtJqkEOWGFl09CTrha5uPVqjr5MgkmBOQ6Q8+cRYWG+qtJsuUH5A==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "@endemolshinegroup/cosmiconfig-typescript-loader": "^3.0.2", |                 "@endemolshinegroup/cosmiconfig-typescript-loader": "^3.0.2", | ||||||
| @ -2072,9 +2072,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@lingui/core": { |         "node_modules/@lingui/core": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.13.2.tgz", | ||||||
|             "integrity": "sha512-spzRJ/fca9Ddpns27Xmz2f9lgiesrvTZjcpOO2wKJq9QozF1qtv7n1bViQ1Erh2uFaO0kaEzUjkAYU3LtlP4PQ==", |             "integrity": "sha512-ic1uC+bS7hpfM4oVugHKel8UhlLAwykSv2TYw3oyeEQhvCS232nSzh+PFbP0BXK1hZ0UdHve7mODpgADuwHIQA==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "make-plural": "^6.2.2", |                 "make-plural": "^6.2.2", | ||||||
| @ -2085,20 +2085,20 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@lingui/detect-locale": { |         "node_modules/@lingui/detect-locale": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-3.13.2.tgz", | ||||||
|             "integrity": "sha512-ZY/jo3whJ5+QlkpUjZgXzzmON6vA9s0qbXgsKue6xIEOGZ7/z5p05tnHb8RYa6jhpRSYN+CJARx2H82QZMrtwA==", |             "integrity": "sha512-1fouly1ecq1wCKUGtYgFn0Hdsjuz4bBYxh/oIjrqEeb4+bKdjaHbCT2ypsX7rRxs88yOfOWGUYuuzG0EoJXiSw==", | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": ">=10.0.0" |                 "node": ">=10.0.0" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@lingui/macro": { |         "node_modules/@lingui/macro": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-3.13.2.tgz", | ||||||
|             "integrity": "sha512-iXdAbREJpIUs3s78Erbg+7ZRuJsD0S0nyGCeEo9Ml/NDO/MtVYo7XCHecwtCdNxDe/h0NItB3m/7uPZ/BvOLOA==", |             "integrity": "sha512-0BdybZkBq8bl4NrT8txX7k8BodyJ/4uQbMIK0ucPJvQ/6Lhj824CodBq5KuMWpcXoMSxUWjQIkIGr1Fi1ckLGg==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "@lingui/conf": "^3.13.1", |                 "@lingui/conf": "^3.13.2", | ||||||
|                 "ramda": "^0.27.1" |                 "ramda": "^0.27.1" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -2176,9 +2176,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@patternfly/patternfly": { |         "node_modules/@patternfly/patternfly": { | ||||||
|             "version": "4.164.2", |             "version": "4.171.1", | ||||||
|             "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.164.2.tgz", |             "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.171.1.tgz", | ||||||
|             "integrity": "sha512-gezQi83JKd6tW0z1J6Q5VvMCW/a58+ys4TWcTuXUMqcV3APQdNxVP+ZV6FIv5353oIPi9HuWAaApVwcCxYZYYg==" |             "integrity": "sha512-e5Ykg+QOo8TsyOyG6SqytAs52MJXwaP020z3twb8z9G3ZNra92uNsrxGgZEqPJoWbjU4K7LGDxy2DOM1FeRoFw==" | ||||||
|         }, |         }, | ||||||
|         "node_modules/@polymer/font-roboto": { |         "node_modules/@polymer/font-roboto": { | ||||||
|             "version": "3.0.2", |             "version": "3.0.2", | ||||||
| @ -2433,13 +2433,13 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry/browser": { |         "node_modules/@sentry/browser": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.17.3.tgz", | ||||||
|             "integrity": "sha512-F2I5RL7RTLQF9CccMrqt73GRdK3FdqaChED3RulGQX5lH6U3exHGFxwyZxSrY4x6FedfBFYlfXWWCJXpLnFkow==", |             "integrity": "sha512-UElPk6/Q/78eL8tHGHy080uHVQAuieWXlSMSzrJMVNa+vwXPwEeyL+WbPtKkND2jGwdODjg+pSj960RqhIv+ig==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry/core": "6.16.1", |                 "@sentry/core": "6.17.3", | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "@sentry/utils": "6.16.1", |                 "@sentry/utils": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -2452,14 +2452,14 @@ | |||||||
|             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" |             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry/core": { |         "node_modules/@sentry/core": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.17.3.tgz", | ||||||
|             "integrity": "sha512-UFI0264CPUc5cR1zJH+S2UPOANpm6dLJOnsvnIGTjsrwzR0h8Hdl6rC2R/GPq+WNbnipo9hkiIwDlqbqvIU5vw==", |             "integrity": "sha512-h7WgrNL0RVlr8Dceh97ZiXNdmEumDutpoqFijjiX4x72IiC6zSaVD4IsqrdGln+v8iJ3l3lX44HHqzubDub1OQ==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry/hub": "6.16.1", |                 "@sentry/hub": "6.17.3", | ||||||
|                 "@sentry/minimal": "6.16.1", |                 "@sentry/minimal": "6.17.3", | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "@sentry/utils": "6.16.1", |                 "@sentry/utils": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -2472,12 +2472,12 @@ | |||||||
|             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" |             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry/hub": { |         "node_modules/@sentry/hub": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.17.3.tgz", | ||||||
|             "integrity": "sha512-4PGtg6AfpqMkreTpL7ymDeQ/U1uXv03bKUuFdtsSTn/FRf9TLS4JB0KuTZCxfp1IRgAA+iFg6B784dDkT8R9eg==", |             "integrity": "sha512-TDxv8nRvk45xvfQg6zs8GYzQzgo0EMhI3wjQZLiNfW2rzybKmIwVp2x3O4PAc3WPzwg4bYNgSAkYKVlHmYjRCg==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "@sentry/utils": "6.16.1", |                 "@sentry/utils": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -2490,12 +2490,12 @@ | |||||||
|             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" |             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry/minimal": { |         "node_modules/@sentry/minimal": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.17.3.tgz", | ||||||
|             "integrity": "sha512-dq+mI1EQIvUM+zJtGCVgH3/B3Sbx4hKlGf2Usovm9KoqWYA+QpfVBholYDe/H2RXgO7LFEefDLvOdHDkqeJoyA==", |             "integrity": "sha512-zvGGfHNNA92Lqx6P8ZwOUkmRmAiQl0AQFRXl9So1Ayq9bJRnFLJZv4YFVnp2wE4HXYIlfBYb51+GlGB5LIuPmw==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry/hub": "6.16.1", |                 "@sentry/hub": "6.17.3", | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -2508,14 +2508,14 @@ | |||||||
|             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" |             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry/tracing": { |         "node_modules/@sentry/tracing": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.17.3.tgz", | ||||||
|             "integrity": "sha512-MPSbqXX59P+OEeST+U2V/8Hu/8QjpTUxTNeNyTHWIbbchdcMMjDbXTS3etCgajZR6Ro+DHElOz5cdSxH6IBGlA==", |             "integrity": "sha512-GnHugxw5qkWwYmeQbbrswuWpb0bpYqyJr/dO25QQOCwp+cckQrvBYTMC8zGJG10u94O4el0lQaQnNFz9WF3r6g==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry/hub": "6.16.1", |                 "@sentry/hub": "6.17.3", | ||||||
|                 "@sentry/minimal": "6.16.1", |                 "@sentry/minimal": "6.17.3", | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "@sentry/utils": "6.16.1", |                 "@sentry/utils": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -2528,19 +2528,19 @@ | |||||||
|             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" |             "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry/types": { |         "node_modules/@sentry/types": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.17.3.tgz", | ||||||
|             "integrity": "sha512-Wh354g30UsJ5kYJbercektGX4ZMc9MHU++1NjeN2bTMnbofEcpUDWIiKeulZEY65IC1iU+1zRQQgtYO+/hgCUQ==", |             "integrity": "sha512-0AXCjYcfl8Vx26GfyLY4rBQ78Lyt1oND3UozTTMaVXlcKYIjzV+f7TOo5IZx+Kbr6EGUNDLdpA4xfbkWdW/1NA==", | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": ">=6" |                 "node": ">=6" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry/utils": { |         "node_modules/@sentry/utils": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.17.3.tgz", | ||||||
|             "integrity": "sha512-7ngq/i4R8JZitJo9Sl8PDnjSbDehOxgr1vsoMmerIsyRZ651C/8B+jVkMhaAPgSdyJ0AlE3O7DKKTP1FXFw9qw==", |             "integrity": "sha512-6/2awDIeHSj0JgiC7DDdV1lxvLmf+/BisWhw09dKvmhVQB3ADvQZbohjUgM+Qam5zE0xmZAfQhvuDwC41W8Wnw==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -2844,13 +2844,13 @@ | |||||||
|             "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" |             "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" | ||||||
|         }, |         }, | ||||||
|         "node_modules/@typescript-eslint/eslint-plugin": { |         "node_modules/@typescript-eslint/eslint-plugin": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.2.tgz", | ||||||
|             "integrity": "sha512-XXVKnMsq2fuu9K2KsIxPUGqb6xAImz8MEChClbXmE3VbveFtBUU5bzM6IPVWqzyADIgdkS2Ws/6Xo7W2TeZWjQ==", |             "integrity": "sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@typescript-eslint/scope-manager": "5.10.0", |                 "@typescript-eslint/scope-manager": "5.10.2", | ||||||
|                 "@typescript-eslint/type-utils": "5.10.0", |                 "@typescript-eslint/type-utils": "5.10.2", | ||||||
|                 "@typescript-eslint/utils": "5.10.0", |                 "@typescript-eslint/utils": "5.10.2", | ||||||
|                 "debug": "^4.3.2", |                 "debug": "^4.3.2", | ||||||
|                 "functional-red-black-tree": "^1.0.1", |                 "functional-red-black-tree": "^1.0.1", | ||||||
|                 "ignore": "^5.1.8", |                 "ignore": "^5.1.8", | ||||||
| @ -2898,13 +2898,13 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@typescript-eslint/parser": { |         "node_modules/@typescript-eslint/parser": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.10.2.tgz", | ||||||
|             "integrity": "sha512-pJB2CCeHWtwOAeIxv8CHVGJhI5FNyJAIpx5Pt72YkK3QfEzt6qAlXZuyaBmyfOdM62qU0rbxJzNToPTVeJGrQw==", |             "integrity": "sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@typescript-eslint/scope-manager": "5.10.0", |                 "@typescript-eslint/scope-manager": "5.10.2", | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "@typescript-eslint/typescript-estree": "5.10.0", |                 "@typescript-eslint/typescript-estree": "5.10.2", | ||||||
|                 "debug": "^4.3.2" |                 "debug": "^4.3.2" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -2924,12 +2924,12 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@typescript-eslint/scope-manager": { |         "node_modules/@typescript-eslint/scope-manager": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.2.tgz", | ||||||
|             "integrity": "sha512-tgNgUgb4MhqK6DoKn3RBhyZ9aJga7EQrw+2/OiDk5hKf3pTVZWyqBi7ukP+Z0iEEDMF5FDa64LqODzlfE4O/Dg==", |             "integrity": "sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "@typescript-eslint/visitor-keys": "5.10.0" |                 "@typescript-eslint/visitor-keys": "5.10.2" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0" |                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0" | ||||||
| @ -2940,11 +2940,11 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@typescript-eslint/type-utils": { |         "node_modules/@typescript-eslint/type-utils": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.10.2.tgz", | ||||||
|             "integrity": "sha512-TzlyTmufJO5V886N+hTJBGIfnjQDQ32rJYxPaeiyWKdjsv2Ld5l8cbS7pxim4DeNs62fKzRSt8Q14Evs4JnZyQ==", |             "integrity": "sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@typescript-eslint/utils": "5.10.0", |                 "@typescript-eslint/utils": "5.10.2", | ||||||
|                 "debug": "^4.3.2", |                 "debug": "^4.3.2", | ||||||
|                 "tsutils": "^3.21.0" |                 "tsutils": "^3.21.0" | ||||||
|             }, |             }, | ||||||
| @ -2965,9 +2965,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@typescript-eslint/types": { |         "node_modules/@typescript-eslint/types": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.2.tgz", | ||||||
|             "integrity": "sha512-wUljCgkqHsMZbw60IbOqT/puLfyqqD5PquGiBo1u1IS3PLxdi3RDGlyf032IJyh+eQoGhz9kzhtZa+VC4eWTlQ==", |             "integrity": "sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w==", | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0" |                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0" | ||||||
|             }, |             }, | ||||||
| @ -2977,12 +2977,12 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@typescript-eslint/typescript-estree": { |         "node_modules/@typescript-eslint/typescript-estree": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.2.tgz", | ||||||
|             "integrity": "sha512-x+7e5IqfwLwsxTdliHRtlIYkgdtYXzE0CkFeV6ytAqq431ZyxCFzNMNR5sr3WOlIG/ihVZr9K/y71VHTF/DUQA==", |             "integrity": "sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "@typescript-eslint/visitor-keys": "5.10.0", |                 "@typescript-eslint/visitor-keys": "5.10.2", | ||||||
|                 "debug": "^4.3.2", |                 "debug": "^4.3.2", | ||||||
|                 "globby": "^11.0.4", |                 "globby": "^11.0.4", | ||||||
|                 "is-glob": "^4.0.3", |                 "is-glob": "^4.0.3", | ||||||
| @ -3017,14 +3017,14 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@typescript-eslint/utils": { |         "node_modules/@typescript-eslint/utils": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.10.2.tgz", | ||||||
|             "integrity": "sha512-IGYwlt1CVcFoE2ueW4/ioEwybR60RAdGeiJX/iDAw0t5w0wK3S7QncDwpmsM70nKgGTuVchEWB8lwZwHqPAWRg==", |             "integrity": "sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@types/json-schema": "^7.0.9", |                 "@types/json-schema": "^7.0.9", | ||||||
|                 "@typescript-eslint/scope-manager": "5.10.0", |                 "@typescript-eslint/scope-manager": "5.10.2", | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "@typescript-eslint/typescript-estree": "5.10.0", |                 "@typescript-eslint/typescript-estree": "5.10.2", | ||||||
|                 "eslint-scope": "^5.1.1", |                 "eslint-scope": "^5.1.1", | ||||||
|                 "eslint-utils": "^3.0.0" |                 "eslint-utils": "^3.0.0" | ||||||
|             }, |             }, | ||||||
| @ -3040,11 +3040,11 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@typescript-eslint/visitor-keys": { |         "node_modules/@typescript-eslint/visitor-keys": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.2.tgz", | ||||||
|             "integrity": "sha512-GMxj0K1uyrFLPKASLmZzCuSddmjZVbVj3Ouy5QVuIGKZopxvOr24JsS7gruz6C3GExE01mublZ3mIBOaon9zuQ==", |             "integrity": "sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "eslint-visitor-keys": "^3.0.0" |                 "eslint-visitor-keys": "^3.0.0" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -3831,12 +3831,9 @@ | |||||||
|             "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" |             "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" | ||||||
|         }, |         }, | ||||||
|         "node_modules/construct-style-sheets-polyfill": { |         "node_modules/construct-style-sheets-polyfill": { | ||||||
|             "version": "3.0.5", |             "version": "3.1.0", | ||||||
|             "resolved": "https://registry.npmjs.org/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-3.0.5.tgz", |             "resolved": "https://registry.npmjs.org/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-3.1.0.tgz", | ||||||
|             "integrity": "sha512-prLKSx9gYwtmqWtq+pZxppU1SaH9o4ug7JIc0I/1zMV2bFE3GvRtQaMTIpotlhw33XjtC7rGQFOZJsOFnlAAhQ==", |             "integrity": "sha512-HBLKP0chz8BAY6rBdzda11c3wAZeCZ+kIG4weVC2NM3AXzxx09nhe8t0SQNdloAvg5GLuHwq/0SPOOSPvtCcKw==" | ||||||
|             "engines": { |  | ||||||
|                 "npm": ">=7" |  | ||||||
|             } |  | ||||||
|         }, |         }, | ||||||
|         "node_modules/convert-source-map": { |         "node_modules/convert-source-map": { | ||||||
|             "version": "1.8.0", |             "version": "1.8.0", | ||||||
| @ -3909,9 +3906,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/country-flag-icons": { |         "node_modules/country-flag-icons": { | ||||||
|             "version": "1.4.19", |             "version": "1.4.20", | ||||||
|             "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.4.19.tgz", |             "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.4.20.tgz", | ||||||
|             "integrity": "sha512-1hmXFJ4UURQt0Ex0990B7oOL4n9KLpT9NOSEmZoYh+/5DQ7/pikyqaptqCLUFFv/bYHyvYFeo0fqV82XxU6VOA==" |             "integrity": "sha512-f9/cO9IEDIkLdOQeTUMDLEWMcDk4qbTRjbQLpy5pm+yil7Fa7QkKxgiMOQ2z1+Jht8/BAD3JJAmPG4qtK/tbUw==" | ||||||
|         }, |         }, | ||||||
|         "node_modules/create-require": { |         "node_modules/create-require": { | ||||||
|             "version": "1.1.1", |             "version": "1.1.1", | ||||||
| @ -4105,9 +4102,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/eslint": { |         "node_modules/eslint": { | ||||||
|             "version": "8.7.0", |             "version": "8.8.0", | ||||||
|             "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", |             "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", | ||||||
|             "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", |             "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@eslint/eslintrc": "^1.0.5", |                 "@eslint/eslintrc": "^1.0.5", | ||||||
|                 "@humanwhocodes/config-array": "^0.9.2", |                 "@humanwhocodes/config-array": "^0.9.2", | ||||||
| @ -5782,9 +5779,9 @@ | |||||||
|             "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" |             "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" | ||||||
|         }, |         }, | ||||||
|         "node_modules/lit": { |         "node_modules/lit": { | ||||||
|             "version": "2.1.1", |             "version": "2.1.2", | ||||||
|             "resolved": "https://registry.npmjs.org/lit/-/lit-2.1.1.tgz", |             "resolved": "https://registry.npmjs.org/lit/-/lit-2.1.2.tgz", | ||||||
|             "integrity": "sha512-yqDqf36IhXwOxIQSFqCMgpfvDCRdxLCLZl7m/+tO5C9W/OBHUj17qZpiMBT35v97QMVKcKEi1KZ3hZRyTwBNsQ==", |             "integrity": "sha512-XacK89dJXF7BJbpiZSMvzT4RxHag7Wt+yNx7tErEVgGVlOFAeN871bj7ivotCMgYeBFWVp/hjKF/PDTk6L7gMA==", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@lit/reactive-element": "^1.1.0", |                 "@lit/reactive-element": "^1.1.0", | ||||||
|                 "lit-element": "^3.1.0", |                 "lit-element": "^3.1.0", | ||||||
| @ -7308,9 +7305,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/rollup": { |         "node_modules/rollup": { | ||||||
|             "version": "2.66.0", |             "version": "2.66.1", | ||||||
|             "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.66.0.tgz", |             "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.66.1.tgz", | ||||||
|             "integrity": "sha512-L6mKOkdyP8HK5kKJXaiWG7KZDumPJjuo1P+cfyHOJPNNTK3Moe7zCH5+fy7v8pVmHXtlxorzaBjvkBMB23s98g==", |             "integrity": "sha512-crSgLhSkLMnKr4s9iZ/1qJCplgAgrRY+igWv8KhG/AjKOJ0YX/WpmANyn8oxrw+zenF3BXWDLa7Xl/QZISH+7w==", | ||||||
|             "bin": { |             "bin": { | ||||||
|                 "rollup": "dist/bin/rollup" |                 "rollup": "dist/bin/rollup" | ||||||
|             }, |             }, | ||||||
| @ -10026,28 +10023,28 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@formatjs/ecma402-abstract": { |         "@formatjs/ecma402-abstract": { | ||||||
|             "version": "1.11.1", |             "version": "1.11.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.1.tgz", |             "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.2.tgz", | ||||||
|             "integrity": "sha512-tgtNODZUGuUI6PAcnvaLZpGrZLVkXnnAvgzOiueYMzFdOdcOw4iH1WKhCe3+r6VR8rHKToJ2HksUGNCB+zt/bg==", |             "integrity": "sha512-qDgOL0vtfJ51cc0pRbFB/oXc4qDbamG22Z6h/QWy6FBxaQgppiy8JF0iYbmNO35cC8r88bQGsgfd/eM6/eTEQQ==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@formatjs/intl-localematcher": "0.2.22", |                 "@formatjs/intl-localematcher": "0.2.23", | ||||||
|                 "tslib": "^2.1.0" |                 "tslib": "^2.1.0" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@formatjs/intl-listformat": { |         "@formatjs/intl-listformat": { | ||||||
|             "version": "6.5.0", |             "version": "6.5.1", | ||||||
|             "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-6.5.0.tgz", |             "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-6.5.1.tgz", | ||||||
|             "integrity": "sha512-gVyAV5QWWtq84MK4cAyJITW+Wb74c2+FT+wa8jhSPxXUky9B5z/k/Ff7or4Vb3KV0YYZuVBQ/vMIoD8Gr182ww==", |             "integrity": "sha512-ijsOM7J7aNnGx+1JYUGWgMAcisnK0CxdlPx7KJpUXKj9Mf2Ph28H2WMTL1h1xv9T7SSvH0Nd6asI0Qw4ffw17w==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@formatjs/ecma402-abstract": "1.11.1", |                 "@formatjs/ecma402-abstract": "1.11.2", | ||||||
|                 "@formatjs/intl-localematcher": "0.2.22", |                 "@formatjs/intl-localematcher": "0.2.23", | ||||||
|                 "tslib": "^2.1.0" |                 "tslib": "^2.1.0" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@formatjs/intl-localematcher": { |         "@formatjs/intl-localematcher": { | ||||||
|             "version": "0.2.22", |             "version": "0.2.23", | ||||||
|             "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.22.tgz", |             "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.23.tgz", | ||||||
|             "integrity": "sha512-z+TvbHW8Q/g2l7/PnfUl0mV9gWxV4d0HT6GQyzkO5QI6QjCvCZGiztnmLX7zoyS16uSMvZ2PoMDfSK9xvZkRRA==", |             "integrity": "sha512-oCe2TOciTtB1bEbJ85EvYrXQxD0epusmVJfJ7AduO0tlbXP42CmDIYIH2CZ+kP2GE+PTLQD1Hbt9kpOpl939MQ==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "tslib": "^2.1.0" |                 "tslib": "^2.1.0" | ||||||
|             } |             } | ||||||
| @ -10058,9 +10055,9 @@ | |||||||
|             "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==" |             "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==" | ||||||
|         }, |         }, | ||||||
|         "@goauthentik/api": { |         "@goauthentik/api": { | ||||||
|             "version": "2022.1.1-1642874681", |             "version": "2022.1.3-1643236150", | ||||||
|             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2022.1.1-1642874681.tgz", |             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2022.1.3-1643236150.tgz", | ||||||
|             "integrity": "sha512-MOFu1g/5dvQu+BTj8qqc2IMT9fpBICqzERkC949JiDxDSqHg0kuqmxe23vPnFceryQM5zktTBJ+VxXjzR9lX3g==" |             "integrity": "sha512-eteq3Y/4eME6bffuQy8cB6ZrV3DB7rk1IKdvzfUbr9I1hSRzXEBtlzmXp+lhY6RxlEy9hhcJHZO8/OCKFI5l9A==" | ||||||
|         }, |         }, | ||||||
|         "@humanwhocodes/config-array": { |         "@humanwhocodes/config-array": { | ||||||
|             "version": "0.9.2", |             "version": "0.9.2", | ||||||
| @ -10145,28 +10142,28 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@lingui/babel-plugin-extract-messages": { |         "@lingui/babel-plugin-extract-messages": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-3.13.2.tgz", | ||||||
|             "integrity": "sha512-K0ekhQI49ZTE90bVxvndqdxO80X1ZjacVdznWn4RJq6EEN9ElppMKkWUmAe/vfHGJRCH/2aUIp73xvaXPJPbGg==", |             "integrity": "sha512-SyvwfrPqkyj9XM2CB/YK25o0Zi+B8ikoCENwqNSk7201n80YfOJoksc6lQ3X/QODqvy+iuOsiQrVT3qzKblOmg==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@babel/generator": "^7.11.6", |                 "@babel/generator": "^7.11.6", | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "@lingui/conf": "^3.13.1", |                 "@lingui/conf": "^3.13.2", | ||||||
|                 "mkdirp": "^1.0.4" |                 "mkdirp": "^1.0.4" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@lingui/cli": { |         "@lingui/cli": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-3.13.2.tgz", | ||||||
|             "integrity": "sha512-JGfbdAn1qxHBjuhnLeERMhCLe7UXSFafqq9S//g3+VNHKHfVHfa0CKFUmISMDKMLFdKmbdJCZpYU3DRZNrUGyQ==", |             "integrity": "sha512-wPYlsKI7hx1hyntc6enUVUdKVwBM8XW+DnwHslWWw4ShMNvh98gLgAOW1ajXtUym7x0WTjhR+/s436hdxfZ/Og==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@babel/generator": "^7.11.6", |                 "@babel/generator": "^7.11.6", | ||||||
|                 "@babel/parser": "^7.11.5", |                 "@babel/parser": "^7.11.5", | ||||||
|                 "@babel/plugin-syntax-jsx": "^7.10.4", |                 "@babel/plugin-syntax-jsx": "^7.10.4", | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "@babel/types": "^7.11.5", |                 "@babel/types": "^7.11.5", | ||||||
|                 "@lingui/babel-plugin-extract-messages": "^3.13.1", |                 "@lingui/babel-plugin-extract-messages": "^3.13.2", | ||||||
|                 "@lingui/conf": "^3.13.1", |                 "@lingui/conf": "^3.13.2", | ||||||
|                 "babel-plugin-macros": "^3.0.1", |                 "babel-plugin-macros": "^3.0.1", | ||||||
|                 "bcp-47": "^1.0.7", |                 "bcp-47": "^1.0.7", | ||||||
|                 "chalk": "^4.1.0", |                 "chalk": "^4.1.0", | ||||||
| @ -10239,9 +10236,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@lingui/conf": { |         "@lingui/conf": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-3.13.2.tgz", | ||||||
|             "integrity": "sha512-xWJVdgNiGqYzkYIxHg4c6KqSNleN5/96M2ly+GzBOmA5H75r4hz27DfQpxuC4FuBUAPC+Mk1HTBO9/aFO0BCZg==", |             "integrity": "sha512-JhiIBxnh2X4QmLP0/+dnTBc7xnZ6qk5MRsQtJqkEOWGFl09CTrha5uPVqjr5MgkmBOQ6Q8+cRYWG+qtJsuUH5A==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "@endemolshinegroup/cosmiconfig-typescript-loader": "^3.0.2", |                 "@endemolshinegroup/cosmiconfig-typescript-loader": "^3.0.2", | ||||||
| @ -10297,9 +10294,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@lingui/core": { |         "@lingui/core": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/core/-/core-3.13.2.tgz", | ||||||
|             "integrity": "sha512-spzRJ/fca9Ddpns27Xmz2f9lgiesrvTZjcpOO2wKJq9QozF1qtv7n1bViQ1Erh2uFaO0kaEzUjkAYU3LtlP4PQ==", |             "integrity": "sha512-ic1uC+bS7hpfM4oVugHKel8UhlLAwykSv2TYw3oyeEQhvCS232nSzh+PFbP0BXK1hZ0UdHve7mODpgADuwHIQA==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "make-plural": "^6.2.2", |                 "make-plural": "^6.2.2", | ||||||
| @ -10307,17 +10304,17 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@lingui/detect-locale": { |         "@lingui/detect-locale": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-3.13.2.tgz", | ||||||
|             "integrity": "sha512-ZY/jo3whJ5+QlkpUjZgXzzmON6vA9s0qbXgsKue6xIEOGZ7/z5p05tnHb8RYa6jhpRSYN+CJARx2H82QZMrtwA==" |             "integrity": "sha512-1fouly1ecq1wCKUGtYgFn0Hdsjuz4bBYxh/oIjrqEeb4+bKdjaHbCT2ypsX7rRxs88yOfOWGUYuuzG0EoJXiSw==" | ||||||
|         }, |         }, | ||||||
|         "@lingui/macro": { |         "@lingui/macro": { | ||||||
|             "version": "3.13.1", |             "version": "3.13.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-3.13.1.tgz", |             "resolved": "https://registry.npmjs.org/@lingui/macro/-/macro-3.13.2.tgz", | ||||||
|             "integrity": "sha512-iXdAbREJpIUs3s78Erbg+7ZRuJsD0S0nyGCeEo9Ml/NDO/MtVYo7XCHecwtCdNxDe/h0NItB3m/7uPZ/BvOLOA==", |             "integrity": "sha512-0BdybZkBq8bl4NrT8txX7k8BodyJ/4uQbMIK0ucPJvQ/6Lhj824CodBq5KuMWpcXoMSxUWjQIkIGr1Fi1ckLGg==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@babel/runtime": "^7.11.2", |                 "@babel/runtime": "^7.11.2", | ||||||
|                 "@lingui/conf": "^3.13.1", |                 "@lingui/conf": "^3.13.2", | ||||||
|                 "ramda": "^0.27.1" |                 "ramda": "^0.27.1" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -10369,9 +10366,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@patternfly/patternfly": { |         "@patternfly/patternfly": { | ||||||
|             "version": "4.164.2", |             "version": "4.171.1", | ||||||
|             "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.164.2.tgz", |             "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.171.1.tgz", | ||||||
|             "integrity": "sha512-gezQi83JKd6tW0z1J6Q5VvMCW/a58+ys4TWcTuXUMqcV3APQdNxVP+ZV6FIv5353oIPi9HuWAaApVwcCxYZYYg==" |             "integrity": "sha512-e5Ykg+QOo8TsyOyG6SqytAs52MJXwaP020z3twb8z9G3ZNra92uNsrxGgZEqPJoWbjU4K7LGDxy2DOM1FeRoFw==" | ||||||
|         }, |         }, | ||||||
|         "@polymer/font-roboto": { |         "@polymer/font-roboto": { | ||||||
|             "version": "3.0.2", |             "version": "3.0.2", | ||||||
| @ -10588,13 +10585,13 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@sentry/browser": { |         "@sentry/browser": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.17.3.tgz", | ||||||
|             "integrity": "sha512-F2I5RL7RTLQF9CccMrqt73GRdK3FdqaChED3RulGQX5lH6U3exHGFxwyZxSrY4x6FedfBFYlfXWWCJXpLnFkow==", |             "integrity": "sha512-UElPk6/Q/78eL8tHGHy080uHVQAuieWXlSMSzrJMVNa+vwXPwEeyL+WbPtKkND2jGwdODjg+pSj960RqhIv+ig==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@sentry/core": "6.16.1", |                 "@sentry/core": "6.17.3", | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "@sentry/utils": "6.16.1", |                 "@sentry/utils": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
| @ -10606,14 +10603,14 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@sentry/core": { |         "@sentry/core": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.17.3.tgz", | ||||||
|             "integrity": "sha512-UFI0264CPUc5cR1zJH+S2UPOANpm6dLJOnsvnIGTjsrwzR0h8Hdl6rC2R/GPq+WNbnipo9hkiIwDlqbqvIU5vw==", |             "integrity": "sha512-h7WgrNL0RVlr8Dceh97ZiXNdmEumDutpoqFijjiX4x72IiC6zSaVD4IsqrdGln+v8iJ3l3lX44HHqzubDub1OQ==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@sentry/hub": "6.16.1", |                 "@sentry/hub": "6.17.3", | ||||||
|                 "@sentry/minimal": "6.16.1", |                 "@sentry/minimal": "6.17.3", | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "@sentry/utils": "6.16.1", |                 "@sentry/utils": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
| @ -10625,12 +10622,12 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@sentry/hub": { |         "@sentry/hub": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.17.3.tgz", | ||||||
|             "integrity": "sha512-4PGtg6AfpqMkreTpL7ymDeQ/U1uXv03bKUuFdtsSTn/FRf9TLS4JB0KuTZCxfp1IRgAA+iFg6B784dDkT8R9eg==", |             "integrity": "sha512-TDxv8nRvk45xvfQg6zs8GYzQzgo0EMhI3wjQZLiNfW2rzybKmIwVp2x3O4PAc3WPzwg4bYNgSAkYKVlHmYjRCg==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "@sentry/utils": "6.16.1", |                 "@sentry/utils": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
| @ -10642,12 +10639,12 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@sentry/minimal": { |         "@sentry/minimal": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.17.3.tgz", | ||||||
|             "integrity": "sha512-dq+mI1EQIvUM+zJtGCVgH3/B3Sbx4hKlGf2Usovm9KoqWYA+QpfVBholYDe/H2RXgO7LFEefDLvOdHDkqeJoyA==", |             "integrity": "sha512-zvGGfHNNA92Lqx6P8ZwOUkmRmAiQl0AQFRXl9So1Ayq9bJRnFLJZv4YFVnp2wE4HXYIlfBYb51+GlGB5LIuPmw==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@sentry/hub": "6.16.1", |                 "@sentry/hub": "6.17.3", | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
| @ -10659,14 +10656,14 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@sentry/tracing": { |         "@sentry/tracing": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.17.3.tgz", | ||||||
|             "integrity": "sha512-MPSbqXX59P+OEeST+U2V/8Hu/8QjpTUxTNeNyTHWIbbchdcMMjDbXTS3etCgajZR6Ro+DHElOz5cdSxH6IBGlA==", |             "integrity": "sha512-GnHugxw5qkWwYmeQbbrswuWpb0bpYqyJr/dO25QQOCwp+cckQrvBYTMC8zGJG10u94O4el0lQaQnNFz9WF3r6g==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@sentry/hub": "6.16.1", |                 "@sentry/hub": "6.17.3", | ||||||
|                 "@sentry/minimal": "6.16.1", |                 "@sentry/minimal": "6.17.3", | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "@sentry/utils": "6.16.1", |                 "@sentry/utils": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
| @ -10678,16 +10675,16 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@sentry/types": { |         "@sentry/types": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.17.3.tgz", | ||||||
|             "integrity": "sha512-Wh354g30UsJ5kYJbercektGX4ZMc9MHU++1NjeN2bTMnbofEcpUDWIiKeulZEY65IC1iU+1zRQQgtYO+/hgCUQ==" |             "integrity": "sha512-0AXCjYcfl8Vx26GfyLY4rBQ78Lyt1oND3UozTTMaVXlcKYIjzV+f7TOo5IZx+Kbr6EGUNDLdpA4xfbkWdW/1NA==" | ||||||
|         }, |         }, | ||||||
|         "@sentry/utils": { |         "@sentry/utils": { | ||||||
|             "version": "6.16.1", |             "version": "6.17.3", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.16.1.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.17.3.tgz", | ||||||
|             "integrity": "sha512-7ngq/i4R8JZitJo9Sl8PDnjSbDehOxgr1vsoMmerIsyRZ651C/8B+jVkMhaAPgSdyJ0AlE3O7DKKTP1FXFw9qw==", |             "integrity": "sha512-6/2awDIeHSj0JgiC7DDdV1lxvLmf+/BisWhw09dKvmhVQB3ADvQZbohjUgM+Qam5zE0xmZAfQhvuDwC41W8Wnw==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@sentry/types": "6.16.1", |                 "@sentry/types": "6.17.3", | ||||||
|                 "tslib": "^1.9.3" |                 "tslib": "^1.9.3" | ||||||
|             }, |             }, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
| @ -10963,13 +10960,13 @@ | |||||||
|             "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" |             "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" | ||||||
|         }, |         }, | ||||||
|         "@typescript-eslint/eslint-plugin": { |         "@typescript-eslint/eslint-plugin": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.2.tgz", | ||||||
|             "integrity": "sha512-XXVKnMsq2fuu9K2KsIxPUGqb6xAImz8MEChClbXmE3VbveFtBUU5bzM6IPVWqzyADIgdkS2Ws/6Xo7W2TeZWjQ==", |             "integrity": "sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@typescript-eslint/scope-manager": "5.10.0", |                 "@typescript-eslint/scope-manager": "5.10.2", | ||||||
|                 "@typescript-eslint/type-utils": "5.10.0", |                 "@typescript-eslint/type-utils": "5.10.2", | ||||||
|                 "@typescript-eslint/utils": "5.10.0", |                 "@typescript-eslint/utils": "5.10.2", | ||||||
|                 "debug": "^4.3.2", |                 "debug": "^4.3.2", | ||||||
|                 "functional-red-black-tree": "^1.0.1", |                 "functional-red-black-tree": "^1.0.1", | ||||||
|                 "ignore": "^5.1.8", |                 "ignore": "^5.1.8", | ||||||
| @ -10994,47 +10991,47 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@typescript-eslint/parser": { |         "@typescript-eslint/parser": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.10.2.tgz", | ||||||
|             "integrity": "sha512-pJB2CCeHWtwOAeIxv8CHVGJhI5FNyJAIpx5Pt72YkK3QfEzt6qAlXZuyaBmyfOdM62qU0rbxJzNToPTVeJGrQw==", |             "integrity": "sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@typescript-eslint/scope-manager": "5.10.0", |                 "@typescript-eslint/scope-manager": "5.10.2", | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "@typescript-eslint/typescript-estree": "5.10.0", |                 "@typescript-eslint/typescript-estree": "5.10.2", | ||||||
|                 "debug": "^4.3.2" |                 "debug": "^4.3.2" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@typescript-eslint/scope-manager": { |         "@typescript-eslint/scope-manager": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.2.tgz", | ||||||
|             "integrity": "sha512-tgNgUgb4MhqK6DoKn3RBhyZ9aJga7EQrw+2/OiDk5hKf3pTVZWyqBi7ukP+Z0iEEDMF5FDa64LqODzlfE4O/Dg==", |             "integrity": "sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "@typescript-eslint/visitor-keys": "5.10.0" |                 "@typescript-eslint/visitor-keys": "5.10.2" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@typescript-eslint/type-utils": { |         "@typescript-eslint/type-utils": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.10.2.tgz", | ||||||
|             "integrity": "sha512-TzlyTmufJO5V886N+hTJBGIfnjQDQ32rJYxPaeiyWKdjsv2Ld5l8cbS7pxim4DeNs62fKzRSt8Q14Evs4JnZyQ==", |             "integrity": "sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@typescript-eslint/utils": "5.10.0", |                 "@typescript-eslint/utils": "5.10.2", | ||||||
|                 "debug": "^4.3.2", |                 "debug": "^4.3.2", | ||||||
|                 "tsutils": "^3.21.0" |                 "tsutils": "^3.21.0" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@typescript-eslint/types": { |         "@typescript-eslint/types": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.2.tgz", | ||||||
|             "integrity": "sha512-wUljCgkqHsMZbw60IbOqT/puLfyqqD5PquGiBo1u1IS3PLxdi3RDGlyf032IJyh+eQoGhz9kzhtZa+VC4eWTlQ==" |             "integrity": "sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w==" | ||||||
|         }, |         }, | ||||||
|         "@typescript-eslint/typescript-estree": { |         "@typescript-eslint/typescript-estree": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.2.tgz", | ||||||
|             "integrity": "sha512-x+7e5IqfwLwsxTdliHRtlIYkgdtYXzE0CkFeV6ytAqq431ZyxCFzNMNR5sr3WOlIG/ihVZr9K/y71VHTF/DUQA==", |             "integrity": "sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "@typescript-eslint/visitor-keys": "5.10.0", |                 "@typescript-eslint/visitor-keys": "5.10.2", | ||||||
|                 "debug": "^4.3.2", |                 "debug": "^4.3.2", | ||||||
|                 "globby": "^11.0.4", |                 "globby": "^11.0.4", | ||||||
|                 "is-glob": "^4.0.3", |                 "is-glob": "^4.0.3", | ||||||
| @ -11053,24 +11050,24 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@typescript-eslint/utils": { |         "@typescript-eslint/utils": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.10.2.tgz", | ||||||
|             "integrity": "sha512-IGYwlt1CVcFoE2ueW4/ioEwybR60RAdGeiJX/iDAw0t5w0wK3S7QncDwpmsM70nKgGTuVchEWB8lwZwHqPAWRg==", |             "integrity": "sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@types/json-schema": "^7.0.9", |                 "@types/json-schema": "^7.0.9", | ||||||
|                 "@typescript-eslint/scope-manager": "5.10.0", |                 "@typescript-eslint/scope-manager": "5.10.2", | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "@typescript-eslint/typescript-estree": "5.10.0", |                 "@typescript-eslint/typescript-estree": "5.10.2", | ||||||
|                 "eslint-scope": "^5.1.1", |                 "eslint-scope": "^5.1.1", | ||||||
|                 "eslint-utils": "^3.0.0" |                 "eslint-utils": "^3.0.0" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "@typescript-eslint/visitor-keys": { |         "@typescript-eslint/visitor-keys": { | ||||||
|             "version": "5.10.0", |             "version": "5.10.2", | ||||||
|             "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.0.tgz", |             "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.2.tgz", | ||||||
|             "integrity": "sha512-GMxj0K1uyrFLPKASLmZzCuSddmjZVbVj3Ouy5QVuIGKZopxvOr24JsS7gruz6C3GExE01mublZ3mIBOaon9zuQ==", |             "integrity": "sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@typescript-eslint/types": "5.10.0", |                 "@typescript-eslint/types": "5.10.2", | ||||||
|                 "eslint-visitor-keys": "^3.0.0" |                 "eslint-visitor-keys": "^3.0.0" | ||||||
|             }, |             }, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
| @ -11636,9 +11633,9 @@ | |||||||
|             "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" |             "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" | ||||||
|         }, |         }, | ||||||
|         "construct-style-sheets-polyfill": { |         "construct-style-sheets-polyfill": { | ||||||
|             "version": "3.0.5", |             "version": "3.1.0", | ||||||
|             "resolved": "https://registry.npmjs.org/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-3.0.5.tgz", |             "resolved": "https://registry.npmjs.org/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-3.1.0.tgz", | ||||||
|             "integrity": "sha512-prLKSx9gYwtmqWtq+pZxppU1SaH9o4ug7JIc0I/1zMV2bFE3GvRtQaMTIpotlhw33XjtC7rGQFOZJsOFnlAAhQ==" |             "integrity": "sha512-HBLKP0chz8BAY6rBdzda11c3wAZeCZ+kIG4weVC2NM3AXzxx09nhe8t0SQNdloAvg5GLuHwq/0SPOOSPvtCcKw==" | ||||||
|         }, |         }, | ||||||
|         "convert-source-map": { |         "convert-source-map": { | ||||||
|             "version": "1.8.0", |             "version": "1.8.0", | ||||||
| @ -11692,9 +11689,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "country-flag-icons": { |         "country-flag-icons": { | ||||||
|             "version": "1.4.19", |             "version": "1.4.20", | ||||||
|             "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.4.19.tgz", |             "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.4.20.tgz", | ||||||
|             "integrity": "sha512-1hmXFJ4UURQt0Ex0990B7oOL4n9KLpT9NOSEmZoYh+/5DQ7/pikyqaptqCLUFFv/bYHyvYFeo0fqV82XxU6VOA==" |             "integrity": "sha512-f9/cO9IEDIkLdOQeTUMDLEWMcDk4qbTRjbQLpy5pm+yil7Fa7QkKxgiMOQ2z1+Jht8/BAD3JJAmPG4qtK/tbUw==" | ||||||
|         }, |         }, | ||||||
|         "create-require": { |         "create-require": { | ||||||
|             "version": "1.1.1", |             "version": "1.1.1", | ||||||
| @ -11837,9 +11834,9 @@ | |||||||
|             "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" |             "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" | ||||||
|         }, |         }, | ||||||
|         "eslint": { |         "eslint": { | ||||||
|             "version": "8.7.0", |             "version": "8.8.0", | ||||||
|             "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", |             "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", | ||||||
|             "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", |             "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@eslint/eslintrc": "^1.0.5", |                 "@eslint/eslintrc": "^1.0.5", | ||||||
|                 "@humanwhocodes/config-array": "^0.9.2", |                 "@humanwhocodes/config-array": "^0.9.2", | ||||||
| @ -13074,9 +13071,9 @@ | |||||||
|             "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" |             "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" | ||||||
|         }, |         }, | ||||||
|         "lit": { |         "lit": { | ||||||
|             "version": "2.1.1", |             "version": "2.1.2", | ||||||
|             "resolved": "https://registry.npmjs.org/lit/-/lit-2.1.1.tgz", |             "resolved": "https://registry.npmjs.org/lit/-/lit-2.1.2.tgz", | ||||||
|             "integrity": "sha512-yqDqf36IhXwOxIQSFqCMgpfvDCRdxLCLZl7m/+tO5C9W/OBHUj17qZpiMBT35v97QMVKcKEi1KZ3hZRyTwBNsQ==", |             "integrity": "sha512-XacK89dJXF7BJbpiZSMvzT4RxHag7Wt+yNx7tErEVgGVlOFAeN871bj7ivotCMgYeBFWVp/hjKF/PDTk6L7gMA==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "@lit/reactive-element": "^1.1.0", |                 "@lit/reactive-element": "^1.1.0", | ||||||
|                 "lit-element": "^3.1.0", |                 "lit-element": "^3.1.0", | ||||||
| @ -14218,9 +14215,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "rollup": { |         "rollup": { | ||||||
|             "version": "2.66.0", |             "version": "2.66.1", | ||||||
|             "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.66.0.tgz", |             "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.66.1.tgz", | ||||||
|             "integrity": "sha512-L6mKOkdyP8HK5kKJXaiWG7KZDumPJjuo1P+cfyHOJPNNTK3Moe7zCH5+fy7v8pVmHXtlxorzaBjvkBMB23s98g==", |             "integrity": "sha512-crSgLhSkLMnKr4s9iZ/1qJCplgAgrRY+igWv8KhG/AjKOJ0YX/WpmANyn8oxrw+zenF3BXWDLa7Xl/QZISH+7w==", | ||||||
|             "requires": { |             "requires": { | ||||||
|                 "fsevents": "~2.3.2" |                 "fsevents": "~2.3.2" | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -20,7 +20,9 @@ | |||||||
|             "en", |             "en", | ||||||
|             "pseudo-LOCALE", |             "pseudo-LOCALE", | ||||||
|             "fr_FR", |             "fr_FR", | ||||||
|             "tr" |             "tr", | ||||||
|  |             "es", | ||||||
|  |             "pl" | ||||||
|         ], |         ], | ||||||
|         "formatOptions": { |         "formatOptions": { | ||||||
|             "lineNumbers": false |             "lineNumbers": false | ||||||
| @ -51,15 +53,15 @@ | |||||||
|         "@babel/plugin-transform-runtime": "^7.16.10", |         "@babel/plugin-transform-runtime": "^7.16.10", | ||||||
|         "@babel/preset-env": "^7.16.11", |         "@babel/preset-env": "^7.16.11", | ||||||
|         "@babel/preset-typescript": "^7.16.7", |         "@babel/preset-typescript": "^7.16.7", | ||||||
|         "@formatjs/intl-listformat": "^6.5.0", |         "@formatjs/intl-listformat": "^6.5.1", | ||||||
|         "@fortawesome/fontawesome-free": "^5.15.4", |         "@fortawesome/fontawesome-free": "^5.15.4", | ||||||
|         "@goauthentik/api": "^2022.1.1-1642874681", |         "@goauthentik/api": "^2022.1.3-1643236150", | ||||||
|         "@jackfranklin/rollup-plugin-markdown": "^0.3.0", |         "@jackfranklin/rollup-plugin-markdown": "^0.3.0", | ||||||
|         "@lingui/cli": "^3.13.1", |         "@lingui/cli": "^3.13.2", | ||||||
|         "@lingui/core": "^3.13.1", |         "@lingui/core": "^3.13.2", | ||||||
|         "@lingui/detect-locale": "^3.13.1", |         "@lingui/detect-locale": "^3.13.2", | ||||||
|         "@lingui/macro": "^3.13.1", |         "@lingui/macro": "^3.13.2", | ||||||
|         "@patternfly/patternfly": "^4.164.2", |         "@patternfly/patternfly": "^4.171.1", | ||||||
|         "@polymer/iron-form": "^3.0.1", |         "@polymer/iron-form": "^3.0.1", | ||||||
|         "@polymer/paper-input": "^3.2.1", |         "@polymer/paper-input": "^3.2.1", | ||||||
|         "@rollup/plugin-babel": "^5.3.0", |         "@rollup/plugin-babel": "^5.3.0", | ||||||
| @ -67,34 +69,34 @@ | |||||||
|         "@rollup/plugin-node-resolve": "^13.1.3", |         "@rollup/plugin-node-resolve": "^13.1.3", | ||||||
|         "@rollup/plugin-replace": "^3.0.1", |         "@rollup/plugin-replace": "^3.0.1", | ||||||
|         "@rollup/plugin-typescript": "^8.3.0", |         "@rollup/plugin-typescript": "^8.3.0", | ||||||
|         "@sentry/browser": "^6.16.1", |         "@sentry/browser": "^6.17.3", | ||||||
|         "@sentry/tracing": "^6.16.1", |         "@sentry/tracing": "^6.17.3", | ||||||
|         "@squoosh/cli": "^0.7.2", |         "@squoosh/cli": "^0.7.2", | ||||||
|         "@trivago/prettier-plugin-sort-imports": "^3.1.1", |         "@trivago/prettier-plugin-sort-imports": "^3.1.1", | ||||||
|         "@types/chart.js": "^2.9.35", |         "@types/chart.js": "^2.9.35", | ||||||
|         "@types/codemirror": "5.60.5", |         "@types/codemirror": "5.60.5", | ||||||
|         "@types/grecaptcha": "^3.0.3", |         "@types/grecaptcha": "^3.0.3", | ||||||
|         "@typescript-eslint/eslint-plugin": "^5.10.0", |         "@typescript-eslint/eslint-plugin": "^5.10.2", | ||||||
|         "@typescript-eslint/parser": "^5.10.0", |         "@typescript-eslint/parser": "^5.10.2", | ||||||
|         "@webcomponents/webcomponentsjs": "^2.6.0", |         "@webcomponents/webcomponentsjs": "^2.6.0", | ||||||
|         "babel-plugin-macros": "^3.1.0", |         "babel-plugin-macros": "^3.1.0", | ||||||
|         "base64-js": "^1.5.1", |         "base64-js": "^1.5.1", | ||||||
|         "chart.js": "^3.7.0", |         "chart.js": "^3.7.0", | ||||||
|         "chartjs-adapter-moment": "^1.0.0", |         "chartjs-adapter-moment": "^1.0.0", | ||||||
|         "codemirror": "^5.65.1", |         "codemirror": "^5.65.1", | ||||||
|         "construct-style-sheets-polyfill": "^3.0.5", |         "construct-style-sheets-polyfill": "^3.1.0", | ||||||
|         "country-flag-icons": "^1.4.19", |         "country-flag-icons": "^1.4.20", | ||||||
|         "eslint": "^8.7.0", |         "eslint": "^8.8.0", | ||||||
|         "eslint-config-google": "^0.14.0", |         "eslint-config-google": "^0.14.0", | ||||||
|         "eslint-plugin-custom-elements": "0.0.4", |         "eslint-plugin-custom-elements": "0.0.4", | ||||||
|         "eslint-plugin-lit": "^1.6.1", |         "eslint-plugin-lit": "^1.6.1", | ||||||
|         "flowchart.js": "^1.17.0", |         "flowchart.js": "^1.17.0", | ||||||
|         "fuse.js": "^6.5.3", |         "fuse.js": "^6.5.3", | ||||||
|         "lit": "^2.1.1", |         "lit": "^2.1.2", | ||||||
|         "moment": "^2.29.1", |         "moment": "^2.29.1", | ||||||
|         "prettier": "^2.5.1", |         "prettier": "^2.5.1", | ||||||
|         "rapidoc": "^9.1.4", |         "rapidoc": "^9.1.4", | ||||||
|         "rollup": "^2.66.0", |         "rollup": "^2.66.1", | ||||||
|         "rollup-plugin-copy": "^3.4.0", |         "rollup-plugin-copy": "^3.4.0", | ||||||
|         "rollup-plugin-cssimport": "^1.0.2", |         "rollup-plugin-cssimport": "^1.0.2", | ||||||
|         "rollup-plugin-minify-html-literals": "^1.2.6", |         "rollup-plugin-minify-html-literals": "^1.2.6", | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success"; | |||||||
| export const ERROR_CLASS = "pf-m-danger"; | export const ERROR_CLASS = "pf-m-danger"; | ||||||
| export const PROGRESS_CLASS = "pf-m-in-progress"; | export const PROGRESS_CLASS = "pf-m-in-progress"; | ||||||
| export const CURRENT_CLASS = "pf-m-current"; | export const CURRENT_CLASS = "pf-m-current"; | ||||||
| export const VERSION = "2022.1.2"; | export const VERSION = "2022.1.4"; | ||||||
| export const TITLE_DEFAULT = "authentik"; | export const TITLE_DEFAULT = "authentik"; | ||||||
| export const ROUTE_SEPARATOR = ";"; | export const ROUTE_SEPARATOR = ";"; | ||||||
|  |  | ||||||
|  | |||||||
| @ -113,6 +113,9 @@ export class FlowExecutor extends LitElement implements StageHost { | |||||||
|             .pf-c-drawer__content { |             .pf-c-drawer__content { | ||||||
|                 background-color: transparent; |                 background-color: transparent; | ||||||
|             } |             } | ||||||
|  |             .pf-c-login__main { | ||||||
|  |                 width: 100%; | ||||||
|  |             } | ||||||
|         `); |         `); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,11 +1,13 @@ | |||||||
| import { en, fr, tr } from "make-plural/plurals"; | import { en, es, fr, pl, tr } from "make-plural/plurals"; | ||||||
|  |  | ||||||
| import { Messages, i18n } from "@lingui/core"; | import { Messages, i18n } from "@lingui/core"; | ||||||
| import { detect, fromNavigator, fromStorage, fromUrl } from "@lingui/detect-locale"; | import { detect, fromNavigator, fromStorage, fromUrl } from "@lingui/detect-locale"; | ||||||
| import { t } from "@lingui/macro"; | import { t } from "@lingui/macro"; | ||||||
|  |  | ||||||
| import { messages as localeEN } from "../locales/en"; | import { messages as localeEN } from "../locales/en"; | ||||||
|  | import { messages as localeES } from "../locales/es"; | ||||||
| import { messages as localeFR_FR } from "../locales/fr_FR"; | import { messages as localeFR_FR } from "../locales/fr_FR"; | ||||||
|  | import { messages as localePL } from "../locales/pl"; | ||||||
| import { messages as localeDEBUG } from "../locales/pseudo-LOCALE"; | import { messages as localeDEBUG } from "../locales/pseudo-LOCALE"; | ||||||
| import { messages as localeTR } from "../locales/tr"; | import { messages as localeTR } from "../locales/tr"; | ||||||
|  |  | ||||||
| @ -29,7 +31,7 @@ export const LOCALES: { | |||||||
|         locale: localeDEBUG, |         locale: localeDEBUG, | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         code: "fr_FR", |         code: "fr", | ||||||
|         plurals: fr, |         plurals: fr, | ||||||
|         label: t`French`, |         label: t`French`, | ||||||
|         locale: localeFR_FR, |         locale: localeFR_FR, | ||||||
| @ -40,6 +42,18 @@ export const LOCALES: { | |||||||
|         label: t`Turkish`, |         label: t`Turkish`, | ||||||
|         locale: localeTR, |         locale: localeTR, | ||||||
|     }, |     }, | ||||||
|  |     { | ||||||
|  |         code: "es", | ||||||
|  |         plurals: es, | ||||||
|  |         label: t`Spanish`, | ||||||
|  |         locale: localeES, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         code: "pl", | ||||||
|  |         plurals: pl, | ||||||
|  |         label: t`Polish`, | ||||||
|  |         locale: localePL, | ||||||
|  |     }, | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
| LOCALES.forEach((locale) => { | LOCALES.forEach((locale) => { | ||||||
| @ -50,9 +64,13 @@ LOCALES.forEach((locale) => { | |||||||
| const DEFAULT_FALLBACK = () => "en"; | const DEFAULT_FALLBACK = () => "en"; | ||||||
|  |  | ||||||
| export function autoDetectLanguage() { | export function autoDetectLanguage() { | ||||||
|     const detected = |     let detected = | ||||||
|         detect(fromUrl("lang"), fromStorage("lang"), fromNavigator(), DEFAULT_FALLBACK) || |         detect(fromUrl("lang"), fromStorage("lang"), fromNavigator(), DEFAULT_FALLBACK) || | ||||||
|         DEFAULT_FALLBACK(); |         DEFAULT_FALLBACK(); | ||||||
|  |     // For now we only care about the first locale part | ||||||
|  |     if (detected.includes("_")) { | ||||||
|  |         detected = detected.split("_")[0]; | ||||||
|  |     } | ||||||
|     if (detected in i18n._messages) { |     if (detected in i18n._messages) { | ||||||
|         console.debug(`authentik/locale: Activating detected locale '${detected}'`); |         console.debug(`authentik/locale: Activating detected locale '${detected}'`); | ||||||
|         i18n.activate(detected); |         i18n.activate(detected); | ||||||
|  | |||||||
| @ -3608,6 +3608,10 @@ msgstr "Policy {0}" | |||||||
| msgid "Policy-specific settings" | msgid "Policy-specific settings" | ||||||
| msgstr "Policy-specific settings" | msgstr "Policy-specific settings" | ||||||
|  |  | ||||||
|  | #: src/interfaces/locale.ts | ||||||
|  | msgid "Polish" | ||||||
|  | msgstr "Polish" | ||||||
|  |  | ||||||
| #: src/pages/providers/saml/SAMLProviderForm.ts | #: src/pages/providers/saml/SAMLProviderForm.ts | ||||||
| msgid "Post" | msgid "Post" | ||||||
| msgstr "Post" | msgstr "Post" | ||||||
| @ -4433,6 +4437,10 @@ msgstr "Sources" | |||||||
| msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | ||||||
| msgstr "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | msgstr "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | ||||||
|  |  | ||||||
|  | #: src/interfaces/locale.ts | ||||||
|  | msgid "Spanish" | ||||||
|  | msgstr "Spanish" | ||||||
|  |  | ||||||
| #: src/pages/sources/ldap/LDAPSourceForm.ts | #: src/pages/sources/ldap/LDAPSourceForm.ts | ||||||
| msgid "Specify multiple server URIs by separating them with a comma." | msgid "Specify multiple server URIs by separating them with a comma." | ||||||
| msgstr "Specify multiple server URIs by separating them with a comma." | msgstr "Specify multiple server URIs by separating them with a comma." | ||||||
|  | |||||||
							
								
								
									
										6090
									
								
								web/src/locales/es.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6090
									
								
								web/src/locales/es.po
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -3580,6 +3580,10 @@ msgstr "Poliitique {0}" | |||||||
| msgid "Policy-specific settings" | msgid "Policy-specific settings" | ||||||
| msgstr "Paramètres spécifiques à la politique" | msgstr "Paramètres spécifiques à la politique" | ||||||
|  |  | ||||||
|  | #: src/interfaces/locale.ts | ||||||
|  | msgid "Polish" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: src/pages/providers/saml/SAMLProviderForm.ts | #: src/pages/providers/saml/SAMLProviderForm.ts | ||||||
| msgid "Post" | msgid "Post" | ||||||
| msgstr "Appliquer" | msgstr "Appliquer" | ||||||
| @ -4395,6 +4399,10 @@ msgstr "Sources" | |||||||
| msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | ||||||
| msgstr "Sources d'identités, qui peuvent soit être synchronisées dans la base de données d'Authentik, soit être utilisées par les utilisateurs pour s'authentifier et s'inscrire." | msgstr "Sources d'identités, qui peuvent soit être synchronisées dans la base de données d'Authentik, soit être utilisées par les utilisateurs pour s'authentifier et s'inscrire." | ||||||
|  |  | ||||||
|  | #: src/interfaces/locale.ts | ||||||
|  | msgid "Spanish" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: src/pages/sources/ldap/LDAPSourceForm.ts | #: src/pages/sources/ldap/LDAPSourceForm.ts | ||||||
| msgid "Specify multiple server URIs by separating them with a comma." | msgid "Specify multiple server URIs by separating them with a comma." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
							
								
								
									
										6090
									
								
								web/src/locales/pl.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6090
									
								
								web/src/locales/pl.po
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -3598,6 +3598,10 @@ msgstr "" | |||||||
| msgid "Policy-specific settings" | msgid "Policy-specific settings" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: src/interfaces/locale.ts | ||||||
|  | msgid "Polish" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: src/pages/providers/saml/SAMLProviderForm.ts | #: src/pages/providers/saml/SAMLProviderForm.ts | ||||||
| msgid "Post" | msgid "Post" | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -4423,6 +4427,10 @@ msgstr "" | |||||||
| msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: src/interfaces/locale.ts | ||||||
|  | msgid "Spanish" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: src/pages/sources/ldap/LDAPSourceForm.ts | #: src/pages/sources/ldap/LDAPSourceForm.ts | ||||||
| msgid "Specify multiple server URIs by separating them with a comma." | msgid "Specify multiple server URIs by separating them with a comma." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
| @ -3546,6 +3546,10 @@ msgstr "İlke {0}" | |||||||
| msgid "Policy-specific settings" | msgid "Policy-specific settings" | ||||||
| msgstr "İlke özel ayarlar" | msgstr "İlke özel ayarlar" | ||||||
|  |  | ||||||
|  | #: src/interfaces/locale.ts | ||||||
|  | msgid "Polish" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: src/pages/providers/saml/SAMLProviderForm.ts | #: src/pages/providers/saml/SAMLProviderForm.ts | ||||||
| msgid "Post" | msgid "Post" | ||||||
| msgstr "Post" | msgstr "Post" | ||||||
| @ -4344,6 +4348,10 @@ msgstr "Kaynaklar" | |||||||
| msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves." | ||||||
| msgstr "Auentik'in veritabanına senkronize edilebilen ya da kullanıcılar tarafından kimlik doğrulaması ve kayıt yaptırmak için kullanılabilen kimliklerin kaynakları." | msgstr "Auentik'in veritabanına senkronize edilebilen ya da kullanıcılar tarafından kimlik doğrulaması ve kayıt yaptırmak için kullanılabilen kimliklerin kaynakları." | ||||||
|  |  | ||||||
|  | #: src/interfaces/locale.ts | ||||||
|  | msgid "Spanish" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: src/pages/sources/ldap/LDAPSourceForm.ts | #: src/pages/sources/ldap/LDAPSourceForm.ts | ||||||
| msgid "Specify multiple server URIs by separating them with a comma." | msgid "Specify multiple server URIs by separating them with a comma." | ||||||
| msgstr "Birden çok sunucu URI'lerini virgülle ayırarak belirtin." | msgstr "Birden çok sunucu URI'lerini virgülle ayırarak belirtin." | ||||||
|  | |||||||
| @ -216,6 +216,7 @@ export class SAMLProviderViewPage extends LitElement { | |||||||
|                                       ${t`Download`} |                                       ${t`Download`} | ||||||
|                                   </a> |                                   </a> | ||||||
|                                   <ak-action-button |                                   <ak-action-button | ||||||
|  |                                       class="pf-m-secondary" | ||||||
|                                       .apiRequest=${() => { |                                       .apiRequest=${() => { | ||||||
|                                           const fullUrl = |                                           const fullUrl = | ||||||
|                                               window.location.origin + |                                               window.location.origin + | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ export class AuthenticatorSMSStageForm extends ModelForm<AuthenticatorSMSStage, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @property({ attribute: false }) |     @property({ attribute: false }) | ||||||
|     provider?: ProviderEnum; |     provider: ProviderEnum = ProviderEnum.Twilio; | ||||||
|  |  | ||||||
|     @property({ attribute: false }) |     @property({ attribute: false }) | ||||||
|     authType?: AuthTypeEnum; |     authType?: AuthTypeEnum; | ||||||
| @ -60,6 +60,101 @@ export class AuthenticatorSMSStageForm extends ModelForm<AuthenticatorSMSStage, | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     renderProviderTwillio(): TemplateResult { | ||||||
|  |         return html` <ak-form-element-horizontal | ||||||
|  |                 label=${t`Twilio Account SID`} | ||||||
|  |                 ?required=${true} | ||||||
|  |                 name="accountSid" | ||||||
|  |             > | ||||||
|  |                 <input | ||||||
|  |                     type="text" | ||||||
|  |                     value="${ifDefined(this.instance?.accountSid || "")}" | ||||||
|  |                     class="pf-c-form-control" | ||||||
|  |                     required | ||||||
|  |                 /> | ||||||
|  |                 <p class="pf-c-form__helper-text"> | ||||||
|  |                     ${t`Get this value from https://console.twilio.com`} | ||||||
|  |                 </p> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal label=${t`Twilio Auth Token`} ?required=${true} name="auth"> | ||||||
|  |                 <input | ||||||
|  |                     type="text" | ||||||
|  |                     value="${ifDefined(this.instance?.auth || "")}" | ||||||
|  |                     class="pf-c-form-control" | ||||||
|  |                     required | ||||||
|  |                 /> | ||||||
|  |                 <p class="pf-c-form__helper-text"> | ||||||
|  |                     ${t`Get this value from https://console.twilio.com`} | ||||||
|  |                 </p> | ||||||
|  |             </ak-form-element-horizontal>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     renderProviderGeneric(): TemplateResult { | ||||||
|  |         return html` <ak-form-element-horizontal | ||||||
|  |                 label=${t`Authentication Type`} | ||||||
|  |                 @change=${(ev: Event) => { | ||||||
|  |                     const current = (ev.target as HTMLInputElement).value; | ||||||
|  |                     this.authType = current as AuthTypeEnum; | ||||||
|  |                 }} | ||||||
|  |                 ?required=${true} | ||||||
|  |                 name="authType" | ||||||
|  |             > | ||||||
|  |                 <select class="pf-c-form-control"> | ||||||
|  |                     <option | ||||||
|  |                         value="${AuthTypeEnum.Basic}" | ||||||
|  |                         ?selected=${this.instance?.authType === AuthTypeEnum.Basic} | ||||||
|  |                     > | ||||||
|  |                         ${t`Basic Auth`} | ||||||
|  |                     </option> | ||||||
|  |                     <option | ||||||
|  |                         value="${AuthTypeEnum.Bearer}" | ||||||
|  |                         ?selected=${this.instance?.authType === AuthTypeEnum.Bearer} | ||||||
|  |                     > | ||||||
|  |                         ${t`Bearer Token`} | ||||||
|  |                     </option> | ||||||
|  |                 </select> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${t`External API URL`} | ||||||
|  |                 ?required=${true} | ||||||
|  |                 name="accountSid" | ||||||
|  |             > | ||||||
|  |                 <input | ||||||
|  |                     type="text" | ||||||
|  |                     value="${ifDefined(this.instance?.accountSid || "")}" | ||||||
|  |                     class="pf-c-form-control" | ||||||
|  |                     required | ||||||
|  |                 /> | ||||||
|  |                 <p class="pf-c-form__helper-text"> | ||||||
|  |                     ${t`This is the full endpoint to send POST requests to.`} | ||||||
|  |                 </p> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal label=${t`API Auth Username`} ?required=${true} name="auth"> | ||||||
|  |                 <input | ||||||
|  |                     type="text" | ||||||
|  |                     value="${ifDefined(this.instance?.auth || "")}" | ||||||
|  |                     class="pf-c-form-control" | ||||||
|  |                 /> | ||||||
|  |                 <p class="pf-c-form__helper-text"> | ||||||
|  |                     ${t`This is the username to be used with basic auth or the token when used with bearer token`} | ||||||
|  |                 </p> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${t`API Auth password`} | ||||||
|  |                 ?required=${false} | ||||||
|  |                 name="authPassword" | ||||||
|  |             > | ||||||
|  |                 <input | ||||||
|  |                     type="text" | ||||||
|  |                     value="${ifDefined(this.instance?.authPassword)}" | ||||||
|  |                     class="pf-c-form-control" | ||||||
|  |                 /> | ||||||
|  |                 <p class="pf-c-form__helper-text"> | ||||||
|  |                     ${t`This is the password to be used with basic auth`} | ||||||
|  |                 </p> | ||||||
|  |             </ak-form-element-horizontal>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     renderForm(): TemplateResult { |     renderForm(): TemplateResult { | ||||||
|         return html`<form class="pf-c-form pf-m-horizontal"> |         return html`<form class="pf-c-form pf-m-horizontal"> | ||||||
|             <div class="form-help-text"> |             <div class="form-help-text"> | ||||||
| @ -117,113 +212,9 @@ export class AuthenticatorSMSStageForm extends ModelForm<AuthenticatorSMSStage, | |||||||
|                             ${t`Number the SMS will be sent from.`} |                             ${t`Number the SMS will be sent from.`} | ||||||
|                         </p> |                         </p> | ||||||
|                     </ak-form-element-horizontal> |                     </ak-form-element-horizontal> | ||||||
|  |                     ${this.provider === ProviderEnum.Generic | ||||||
|                     <ak-form-element-horizontal |                         ? this.renderProviderGeneric() | ||||||
|                         label=${t`Twilio Account SID`} |                         : this.renderProviderTwillio()} | ||||||
|                         ?hidden=${this.provider !== ProviderEnum.Twilio} |  | ||||||
|                         ?required=${true} |  | ||||||
|                         name="accountSid" |  | ||||||
|                     > |  | ||||||
|                         <input |  | ||||||
|                             type="text" |  | ||||||
|                             value="${ifDefined(this.instance?.accountSid || "")}" |  | ||||||
|                             class="pf-c-form-control" |  | ||||||
|                             required |  | ||||||
|                         /> |  | ||||||
|                         <p class="pf-c-form__helper-text"> |  | ||||||
|                             ${t`Get this value from https://console.twilio.com`} |  | ||||||
|                         </p> |  | ||||||
|                     </ak-form-element-horizontal> |  | ||||||
|                     <ak-form-element-horizontal |  | ||||||
|                         label=${t`Twilio Auth Token`} |  | ||||||
|                         ?hidden=${this.provider !== ProviderEnum.Twilio} |  | ||||||
|                         ?required=${true} |  | ||||||
|                         name="auth" |  | ||||||
|                     > |  | ||||||
|                         <input |  | ||||||
|                             type="text" |  | ||||||
|                             value="${ifDefined(this.instance?.auth || "")}" |  | ||||||
|                             class="pf-c-form-control" |  | ||||||
|                             required |  | ||||||
|                         /> |  | ||||||
|                         <p class="pf-c-form__helper-text"> |  | ||||||
|                             ${t`Get this value from https://console.twilio.com`} |  | ||||||
|                         </p> |  | ||||||
|                     </ak-form-element-horizontal> |  | ||||||
|                     <ak-form-element-horizontal |  | ||||||
|                         label=${t`Authentication Type`} |  | ||||||
|                         ?hidden=${this.provider !== ProviderEnum.Generic} |  | ||||||
|                         @change=${(ev: Event) => { |  | ||||||
|                             const current = (ev.target as HTMLInputElement).value; |  | ||||||
|                             this.authType = current as AuthTypeEnum; |  | ||||||
|                         }} |  | ||||||
|                         ?required=${true} |  | ||||||
|                         name="authType" |  | ||||||
|                     > |  | ||||||
|                         <select class="pf-c-form-control"> |  | ||||||
|                             <option |  | ||||||
|                                 value="${AuthTypeEnum.Basic}" |  | ||||||
|                                 ?selected=${this.instance?.authType === AuthTypeEnum.Basic} |  | ||||||
|                             > |  | ||||||
|                                 ${t`Basic Auth`} |  | ||||||
|                             </option> |  | ||||||
|                             <option |  | ||||||
|                                 value="${AuthTypeEnum.Bearer}" |  | ||||||
|                                 ?selected=${this.instance?.authType === AuthTypeEnum.Bearer} |  | ||||||
|                             > |  | ||||||
|                                 ${t`Bearer Token`} |  | ||||||
|                             </option> |  | ||||||
|                         </select> |  | ||||||
|                     </ak-form-element-horizontal> |  | ||||||
|                     <ak-form-element-horizontal |  | ||||||
|                         label=${t`External API URL`} |  | ||||||
|                         ?hidden=${this.provider !== ProviderEnum.Generic} |  | ||||||
|                         ?required=${true} |  | ||||||
|                         name="accountSid" |  | ||||||
|                     > |  | ||||||
|                         <input |  | ||||||
|                             type="text" |  | ||||||
|                             value="${ifDefined(this.instance?.accountSid || "")}" |  | ||||||
|                             class="pf-c-form-control" |  | ||||||
|                             required |  | ||||||
|                         /> |  | ||||||
|                         <p class="pf-c-form__helper-text"> |  | ||||||
|                             ${t`This is the full endpoint to send POST requests to.`} |  | ||||||
|                         </p> |  | ||||||
|                     </ak-form-element-horizontal> |  | ||||||
|                     <ak-form-element-horizontal |  | ||||||
|                         label=${t`API Auth Username`} |  | ||||||
|                         ?hidden=${this.provider !== ProviderEnum.Generic} |  | ||||||
|                         ?required=${true} |  | ||||||
|                         name="auth" |  | ||||||
|                     > |  | ||||||
|                         <input |  | ||||||
|                             type="text" |  | ||||||
|                             value="${ifDefined(this.instance?.auth || "")}" |  | ||||||
|                             class="pf-c-form-control" |  | ||||||
|                         /> |  | ||||||
|                         <p class="pf-c-form__helper-text"> |  | ||||||
|                             ${t`This is the username to be used with basic auth or the token when used with bearer token`} |  | ||||||
|                         </p> |  | ||||||
|                     </ak-form-element-horizontal> |  | ||||||
|                     <ak-form-element-horizontal |  | ||||||
|                         label=${t`API Auth password`} |  | ||||||
|                         ?hidden=${!( |  | ||||||
|                             this.provider === ProviderEnum.Generic && |  | ||||||
|                             this.authType === AuthTypeEnum.Basic |  | ||||||
|                         )} |  | ||||||
|                         ?required=${false} |  | ||||||
|                         name="authPassword" |  | ||||||
|                     > |  | ||||||
|                         <input |  | ||||||
|                             type="text" |  | ||||||
|                             value="${ifDefined(this.instance?.authPassword)}" |  | ||||||
|                             class="pf-c-form-control" |  | ||||||
|                         /> |  | ||||||
|                         <p class="pf-c-form__helper-text"> |  | ||||||
|                             ${t`This is the password to be used with basic auth`} |  | ||||||
|                         </p> |  | ||||||
|                     </ak-form-element-horizontal> |  | ||||||
|                     <ak-form-element-horizontal label=${t`Configuration flow`} name="configureFlow"> |                     <ak-form-element-horizontal label=${t`Configuration flow`} name="configureFlow"> | ||||||
|                         <select class="pf-c-form-control"> |                         <select class="pf-c-form-control"> | ||||||
|                             <option |                             <option | ||||||
|  | |||||||
| @ -227,6 +227,7 @@ export class UserListPage extends TablePage<User> { | |||||||
|                                             } |                                             } | ||||||
|                                             return html` |                                             return html` | ||||||
|                                                 <ak-action-button |                                                 <ak-action-button | ||||||
|  |                                                     class="pf-m-secondary" | ||||||
|                                                     .apiRequest=${() => { |                                                     .apiRequest=${() => { | ||||||
|                                                         return new CoreApi(DEFAULT_CONFIG) |                                                         return new CoreApi(DEFAULT_CONFIG) | ||||||
|                                                             .coreUsersRecoveryRetrieve({ |                                                             .coreUsersRecoveryRetrieve({ | ||||||
|  | |||||||
| @ -103,7 +103,7 @@ export class UserDetailsForm extends ModelForm<UserSelf, number> { | |||||||
|                                     value=${locale.code} |                                     value=${locale.code} | ||||||
|                                     ?selected=${config.locale === locale.code} |                                     ?selected=${config.locale === locale.code} | ||||||
|                                 > |                                 > | ||||||
|                                     ${locale.label} |                                     ${locale.code.toUpperCase()} - ${locale.label} | ||||||
|                                 </option>`; |                                 </option>`; | ||||||
|                             })} |                             })} | ||||||
|                         </select> |                         </select> | ||||||
|  | |||||||
							
								
								
									
										38
									
								
								website/developer-docs/docs/writing-documentation.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								website/developer-docs/docs/writing-documentation.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | --- | ||||||
|  | title: Writing documentation | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | Writing documentation for authentik is a great way for both new and experienced users to improve and contribute to the project. Here are a few guidelines to ensure | ||||||
|  | the documentation is easy to read and uses similar phrasing. | ||||||
|  |  | ||||||
|  | # General guidelines | ||||||
|  |  | ||||||
|  | - authentik should always be stylized as `authentik` (with a lower-case a and ending with a k) | ||||||
|  | - Documentation should use American english | ||||||
|  | - Feel free to use Docusaurus-specific features, see [here](https://docusaurus.io/docs/next/markdown-features) | ||||||
|  | - Use abbreviations where it makes sense (for commonly used terms like SAML and OAuth) | ||||||
|  | - Phrasing should never blame the user, and should be subjective, i.e | ||||||
|  |  | ||||||
|  |     - **DON'T** `You may never click x.` | ||||||
|  |     - **DO** `x should never be clicked.` | ||||||
|  |  | ||||||
|  | - When referring to other objects in authentik, use cursive text, and link to the corresponding documentation if possible. | ||||||
|  | - When referring to external tools, give an example how to use the tools or explain how the user can use them. | ||||||
|  | - Make sure to add the documentation to add to the sidebar, if adding a new page. | ||||||
|  | - Test how the documentation renders using the Netlify Preview, especially when using Docusaurus-specific features. | ||||||
|  |  | ||||||
|  | If you find any documentation that doesn't match these guidelines, feel free to either open an Issue or a PR so they can be fixed. | ||||||
|  |  | ||||||
|  | ## Integration guidelines | ||||||
|  |  | ||||||
|  | These guidelines apply in addition to the ones above. | ||||||
|  |  | ||||||
|  | - For placeholders, use angle brackets (`<placeholder-name>`). | ||||||
|  |  | ||||||
|  |     Make sure to also define if the placeholder is something the user needs to define, something another system defines, or randomly generated. | ||||||
|  |  | ||||||
|  |     If you're adding configuration snippets to the documentation, and the snippet is in a language that supports comments, | ||||||
|  |     other placeholders may be used, for example comments referencing an earlier step. | ||||||
|  |  | ||||||
|  | - For placeholder domains, use `authentik.company` and `app-name.company`, where `app-name` is the name of the application you are writing documentation for. | ||||||
|  | - Try to order the documentation in the order that makes it easiest for the user to configure. | ||||||
| @ -1,11 +1,15 @@ | |||||||
| --- | --- | ||||||
| title: Translation | title: Translations | ||||||
| --- | --- | ||||||
|  |  | ||||||
| Translation in authentik is done in two places. Most of the text is defined in the frontend in `web/`, and a subset of messages is defined in the backend. | Translation in authentik is done in two places. Most of the text is defined in the frontend in `web/`, and a subset of messages is defined in the backend. | ||||||
|  |  | ||||||
| The frontend uses [lingui](https://lingui.js.org/), and the backend uses the built-in django translation tools. | The frontend uses [lingui](https://lingui.js.org/), and the backend uses the built-in django translation tools. | ||||||
|  |  | ||||||
|  | :::info | ||||||
|  | Please review the [Writing documentation](./docs/writing-documentation) guidelines as they apply to documentation too. | ||||||
|  | ::: | ||||||
|  |  | ||||||
| ## Online translation | ## Online translation | ||||||
|  |  | ||||||
| To simplify translation you can use https://www.transifex.com/beryjuorg/authentik/, which has no local requirements. | To simplify translation you can use https://www.transifex.com/beryjuorg/authentik/, which has no local requirements. | ||||||
|  | |||||||
| @ -18,6 +18,17 @@ Example: | |||||||
| user_email_local = regex_replace(request.user.email, '(.+)@.+', '') | user_email_local = regex_replace(request.user.email, '(.+)@.+', '') | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | ### `list_flatten(value: list[Any] | Any) -> Optional[Any}` | ||||||
|  |  | ||||||
|  | Flatten a list by either returning its first element, None if the list is empty, or the passed in object if its not a list. | ||||||
|  |  | ||||||
|  | Example: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | user = list_flatten(["foo"]) | ||||||
|  | # user = "foo" | ||||||
|  | ``` | ||||||
|  |  | ||||||
| ### `ak_is_group_member(user: User, **group_filters) -> bool` | ### `ak_is_group_member(user: User, **group_filters) -> bool` | ||||||
|  |  | ||||||
| Check if `user` is member of a group matching `**group_filters`. | Check if `user` is member of a group matching `**group_filters`. | ||||||
|  | |||||||
| @ -23,12 +23,12 @@ The container is created with the following hardcoded properties: | |||||||
|     Additionally, the proxy outposts have the following extra labels to add themselves into traefik automatically. |     Additionally, the proxy outposts have the following extra labels to add themselves into traefik automatically. | ||||||
|  |  | ||||||
|     - `traefik.enable`: "true" |     - `traefik.enable`: "true" | ||||||
|     - `traefik.http.routers.ak-outpost-<outpost-id>-router.rule`: `Host(...)` |     - `traefik.http.routers.ak-outpost-<outpost-name>-router.rule`: `Host(...)` | ||||||
|     - `traefik.http.routers.ak-outpost-<outpost-id>-router.service`: `ak-outpost-<outpost-id>-service` |     - `traefik.http.routers.ak-outpost-<outpost-name>-router.service`: `ak-outpost-<outpost-name>-service` | ||||||
|     - `traefik.http.routers.ak-outpost-<outpost-id>-router.tls`: "true" |     - `traefik.http.routers.ak-outpost-<outpost-name>-router.tls`: "true" | ||||||
|     - `traefik.http.services.ak-outpost-<outpost-id>-service.loadbalancer.healthcheck.path`: "/akprox/ping" |     - `traefik.http.services.ak-outpost-<outpost-name>-service.loadbalancer.healthcheck.path`: "/akprox/ping" | ||||||
|     - `traefik.http.services.ak-outpost-<outpost-id>-service.loadbalancer.healthcheck.port`: "9300" |     - `traefik.http.services.ak-outpost-<outpost-name>-service.loadbalancer.healthcheck.port`: "9300" | ||||||
|     - `traefik.http.services.ak-outpost-<outpost-id>-service.loadbalancer.server.port`: "9000" |     - `traefik.http.services.ak-outpost-<outpost-name>-service.loadbalancer.server.port`: "9000" | ||||||
|  |  | ||||||
| ## Permissions | ## Permissions | ||||||
|  |  | ||||||
|  | |||||||
| @ -32,5 +32,5 @@ metadata: | |||||||
|     nginx.ingress.kubernetes.io/auth-response-headers: | |     nginx.ingress.kubernetes.io/auth-response-headers: | | ||||||
|       Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid |       Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid | ||||||
|     nginx.ingress.kubernetes.io/auth-snippet: | |     nginx.ingress.kubernetes.io/auth-snippet: | | ||||||
|        proxy_set_header X-Forwarded-Host $http_host; |        proxy_set_header Host $http_host; | ||||||
| ``` | ``` | ||||||
|  | |||||||
| @ -6,8 +6,6 @@ For Nginx Proxy Manager you can use this snippet | |||||||
| # header from upstream' error when trying to access an application protected by goauthentik | # header from upstream' error when trying to access an application protected by goauthentik | ||||||
| proxy_buffers 8 16k; | proxy_buffers 8 16k; | ||||||
| proxy_buffer_size 32k; | proxy_buffer_size 32k; | ||||||
| fastcgi_buffers 16 16k; |  | ||||||
| fastcgi_buffer_size 32k; |  | ||||||
|  |  | ||||||
| location / { | location / { | ||||||
|     # Put your proxy_pass to your application here |     # Put your proxy_pass to your application here | ||||||
| @ -16,6 +14,8 @@ location / { | |||||||
|     # authentik-specific config |     # authentik-specific config | ||||||
|     auth_request        /akprox/auth/nginx; |     auth_request        /akprox/auth/nginx; | ||||||
|     error_page          401 = @akprox_signin; |     error_page          401 = @akprox_signin; | ||||||
|  |     auth_request_set $auth_cookie $upstream_http_set_cookie; | ||||||
|  |     add_header Set-Cookie $auth_cookie; | ||||||
|  |  | ||||||
|     # translate headers from the outposts back to the actual upstream |     # translate headers from the outposts back to the actual upstream | ||||||
|     auth_request_set $authentik_username $upstream_http_x_authentik_username; |     auth_request_set $authentik_username $upstream_http_x_authentik_username; | ||||||
| @ -37,6 +37,7 @@ location /akprox { | |||||||
|     # ensure the host of this vserver matches your external URL you've configured |     # ensure the host of this vserver matches your external URL you've configured | ||||||
|     # in authentik |     # in authentik | ||||||
|     proxy_set_header    Host $host; |     proxy_set_header    Host $host; | ||||||
|  |     proxy_set_header    X-Original-URL $scheme://$http_host$request_uri; | ||||||
|     add_header          Set-Cookie $auth_cookie; |     add_header          Set-Cookie $auth_cookie; | ||||||
|     auth_request_set    $auth_cookie $upstream_http_set_cookie; |     auth_request_set    $auth_cookie $upstream_http_set_cookie; | ||||||
| } | } | ||||||
|  | |||||||
| @ -13,8 +13,6 @@ server { | |||||||
|     # header from upstream' error when trying to access an application protected by goauthentik |     # header from upstream' error when trying to access an application protected by goauthentik | ||||||
|     proxy_buffers 8 16k; |     proxy_buffers 8 16k; | ||||||
|     proxy_buffer_size 32k; |     proxy_buffer_size 32k; | ||||||
|     fastcgi_buffers 16 16k; |  | ||||||
|     fastcgi_buffer_size 32k; |  | ||||||
|  |  | ||||||
|     location / { |     location / { | ||||||
|         # Put your proxy_pass to your application here |         # Put your proxy_pass to your application here | ||||||
| @ -25,6 +23,8 @@ server { | |||||||
|         error_page          401 = @akprox_signin; |         error_page          401 = @akprox_signin; | ||||||
|         # For domain level, use the below error_page to redirect to your authentik server with the full redirect path |         # For domain level, use the below error_page to redirect to your authentik server with the full redirect path | ||||||
|         # error_page          401 =302 https://authentik.company/akprox/start?rd=$scheme://$http_host$request_uri; |         # error_page          401 =302 https://authentik.company/akprox/start?rd=$scheme://$http_host$request_uri; | ||||||
|  |         auth_request_set $auth_cookie $upstream_http_set_cookie; | ||||||
|  |         add_header Set-Cookie $auth_cookie; | ||||||
|  |  | ||||||
|         # translate headers from the outposts back to the actual upstream |         # translate headers from the outposts back to the actual upstream | ||||||
|         auth_request_set $authentik_username $upstream_http_x_authentik_username; |         auth_request_set $authentik_username $upstream_http_x_authentik_username; | ||||||
| @ -46,6 +46,7 @@ server { | |||||||
|         # ensure the host of this vserver matches your external URL you've configured |         # ensure the host of this vserver matches your external URL you've configured | ||||||
|         # in authentik |         # in authentik | ||||||
|         proxy_set_header    Host $host; |         proxy_set_header    Host $host; | ||||||
|  |         proxy_set_header    X-Original-URL $scheme://$http_host$request_uri; | ||||||
|         add_header          Set-Cookie $auth_cookie; |         add_header          Set-Cookie $auth_cookie; | ||||||
|         auth_request_set    $auth_cookie $upstream_http_set_cookie; |         auth_request_set    $auth_cookie $upstream_http_set_cookie; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -58,6 +58,50 @@ This release mostly removes legacy fields and features that have been deprecated | |||||||
| - web/admin: fix missing configure flow setting on webuahtn setup stage form | - web/admin: fix missing configure flow setting on webuahtn setup stage form | ||||||
| - web/flows: remove node directly instead of using removeChild() | - web/flows: remove node directly instead of using removeChild() | ||||||
|  |  | ||||||
|  | ## Fixed in 2022.1.2 | ||||||
|  |  | ||||||
|  | - internal/proxyv2: only allow access to /akprox in nginx mode when forward url could be extracted | ||||||
|  | - lib: disable backup by default, add note to configuration | ||||||
|  | - lifecycle: replace lowercase, deprecated prometheus_multiproc_dir | ||||||
|  | - outposts: allow custom label for docker containers | ||||||
|  | - policies/hibp: ensure password is encodable | ||||||
|  | - providers/proxy: add PathPrefix to auto-traefik labels | ||||||
|  | - root: upgrade python dependencies | ||||||
|  |  | ||||||
|  | ## Fixed in 2022.1.3 | ||||||
|  |  | ||||||
|  | - internal: add support for X-Original-URL | ||||||
|  | - internal: add optional debug server listening on 9900 | ||||||
|  | - internal: don't override server header | ||||||
|  | - internal: start adding tests to outpost | ||||||
|  | - lifecycle: make secret_key warning more prominent | ||||||
|  | - lifecycle: wait for db in worker | ||||||
|  | - outposts/ldap: Fix more case sensitivity issues. (#2144) | ||||||
|  | - outposts/proxy: add more test cases for domain-level auth | ||||||
|  | - outposts/proxy: fix potential empty redirect, add tests | ||||||
|  | - outposts/proxy: trace full headers to debug | ||||||
|  | - providers/proxy: fix traefik label | ||||||
|  | - root: add max-requests for gunicorn and max tasks for celery | ||||||
|  | - root: fix redis passwords not being encoded correctly | ||||||
|  | - web/admin: fix links which look like labels | ||||||
|  | - web/admin: fix SMS Stage form not working | ||||||
|  |  | ||||||
|  | ## Fixed in 2022.1.4 | ||||||
|  |  | ||||||
|  | - core: fix view_token permission not being assigned on token creation for non-admin user | ||||||
|  | - lifecycle: remove gunicorn reload option | ||||||
|  | - lifecycle: send analytics in gunicorn config to decrease outgoing requests when workers get restarted | ||||||
|  | - providers/proxy: add support for X-Original-URI in nginx, better handle missing headers and report errors to authentik | ||||||
|  | - providers/proxy: don't include hostname and scheme in redirect when we only got a path and not a full URL | ||||||
|  | - providers/proxy: fix routing for external_host when using forward_auth_domain | ||||||
|  | - providers/proxy: set traefik labels using object_naming_template instead of UUID | ||||||
|  | - sources/ldap: add list_flatten function to property mappings, enable on managed LDAP mappings | ||||||
|  | - web: add es locale | ||||||
|  | - web: add pl locale | ||||||
|  | - web/admin: only check first half of locale when detecting | ||||||
|  | - web/flows: fix width on flow container | ||||||
|  | - web/user: include locale code in locale selection | ||||||
|  |  | ||||||
| ## Upgrading | ## Upgrading | ||||||
|  |  | ||||||
| This release does not introduce any new requirements. | This release does not introduce any new requirements. | ||||||
|  | |||||||
							
								
								
									
										72
									
								
								website/integrations/services/zulip/index.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								website/integrations/services/zulip/index.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | |||||||
|  | --- | ||||||
|  | title: Zulip | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ## What is Zulip | ||||||
|  |  | ||||||
|  | From https://zulip.com | ||||||
|  |  | ||||||
|  | :::note | ||||||
|  | **Zulip**: Chat for distributed teams. Zulip combines the immediacy of real-time chat with an email threading model. | ||||||
|  | With Zulip, you can catch up on important conversations while ignoring irrelevant ones.  | ||||||
|  | ::: | ||||||
|  |  | ||||||
|  | ## Preperation | ||||||
|  |  | ||||||
|  | The following placeholders will be used: | ||||||
|  |  | ||||||
|  | - `authentik.company` is the FQDN of the authentik install. | ||||||
|  | - `zulip.company` is the FQDN of the Zulip instance. | ||||||
|  |  | ||||||
|  | Create an application in authentik and note the slug, as this will be used later. Create a SAML provider with the following parameters: | ||||||
|  |  | ||||||
|  | - ACS URL: `https://zulip.company/complete/saml/` | ||||||
|  | - Issuer: `https://authentik.company` | ||||||
|  | - Service Provider Binding: `Post` | ||||||
|  | - Signing Keypair: Select any certificate you have. | ||||||
|  | - Property mappings: Select all Managed mappings. | ||||||
|  |  | ||||||
|  | ## Zulip Configuration | ||||||
|  |  | ||||||
|  | Zulip is a Django application and is configured using `/etc/zulip/settings.py`. Only settings that differ | ||||||
|  | from the defaults are displayed below. Please make sure you have the latest `settings.py` file as more settings  | ||||||
|  | might have been added to defaults since you installed Zulip. | ||||||
|  |  | ||||||
|  | Uncomment `zproject.backends.SAMLAuthBackend` inside the `AUTHENTICATION_BACKENDS` parameter to enable SAML support | ||||||
|  | and fill in the following required configuration. | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  | SOCIAL_AUTH_SAML_ORG_INFO = { | ||||||
|  |     "en-US": { | ||||||
|  |         "displayname": "authentik Zulip", | ||||||
|  |         "name": "zulip", | ||||||
|  |         "url": "{}{}".format("https://", EXTERNAL_HOST), | ||||||
|  |     }, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SOCIAL_AUTH_SAML_ENABLED_IDPS: Dict[str, Any] = { | ||||||
|  |     # idp identifier and settings | ||||||
|  |     "authentik": { | ||||||
|  |         | ||||||
|  | 	    # KEEP OTHER SETTINGS AS DEFAULT OR CONFIGURE THEM ACCORDING TO YOUR PREFERENCES | ||||||
|  |         "entity_id": "https://authentik.company", | ||||||
|  |         "url": "https://authentik.company/application/saml/<application slug>/sso/binding/redirect/", | ||||||
|  |         "display_name": "authentik SAML", | ||||||
|  |     }, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Place the certificate you associated with the SAML provider in authentik inside the `/etc/zulip/saml/idps` directory.  | ||||||
|  | The certificate file name must match the idp identifier name you set in the configuration (i.e. authentik.crt). | ||||||
|  |  | ||||||
|  | :::note | ||||||
|  | Remember to restart Zulip. | ||||||
|  | ::: | ||||||
|  | ## Additional Resources | ||||||
|  |  | ||||||
|  | Please refer to the following for further information: | ||||||
|  |  | ||||||
|  | - https://zulip.com/ | ||||||
|  | - https://zulip.readthedocs.io | ||||||
|  | - https://chat.zulip.org/ (Official public Zulip Chat instance) | ||||||
| @ -31,17 +31,17 @@ The following placeholders will be used: | |||||||
|  |  | ||||||
|      |      | ||||||
|  |  | ||||||
| Additional infos: https://support.microfocus.com/kb/doc.php?id=7023371 | Additional info: https://support.microfocus.com/kb/doc.php?id=7023371 | ||||||
|  |  | ||||||
| ## authentik Setup | ## authentik Setup | ||||||
|  |  | ||||||
| In authentik, create a new LDAP Source in Resources -> Sources. | In authentik, create a new LDAP Source in Directory -> Federation & Social login. | ||||||
|  |  | ||||||
| Use these settings: | Use these settings: | ||||||
|  |  | ||||||
| - Server URI: `ldap://ad.company` | - Server URI: `ldap://ad.company` | ||||||
|  |  | ||||||
|     For authentik to be able to write passwords back to Active Directory, make sure to use `ldaps://` |     For authentik to be able to write passwords back to Active Directory, make sure to use `ldaps://`. You can test to verify LDAPS is working using `ldp.exe`. | ||||||
|  |  | ||||||
|     You can specify multiple servers by separating URIs with a comma, like `ldap://dc1.ad.company,ldap://dc2.ad.company`. |     You can specify multiple servers by separating URIs with a comma, like `ldap://dc1.ad.company,ldap://dc2.ad.company`. | ||||||
|  |  | ||||||
| @ -53,17 +53,16 @@ Use these settings: | |||||||
| - Property mappings: Control/Command-select all Mappings which start with "authentik default LDAP" and "authentik default Active Directory" | - Property mappings: Control/Command-select all Mappings which start with "authentik default LDAP" and "authentik default Active Directory" | ||||||
| - Group property mappings: Select "authentik default LDAP Mapping: Name" | - Group property mappings: Select "authentik default LDAP Mapping: Name" | ||||||
|  |  | ||||||
| The other settings might need to be adjusted based on the setup of your domain. | Additional settings that might need to be adjusted based on the setup of your domain: | ||||||
|  |  | ||||||
| - Addition User/Group DN: Additional DN which is _prepended_ to your Base DN for user synchronization. | - Group: If enabled, all synchronized groups will be given this group as a parent. | ||||||
| - Addition Group DN: Additional DN which is _prepended_ to your Base DN for group synchronization. | - Addition User/Group DN: Additional DN which is _prepended_ to your Base DN configured above to limit the scope of synchronization for Users and Groups | ||||||
| - User object filter: Which objects should be considered users. | - User object filter: Which objects should be considered users. For Active Directory set it to `(&(objectClass=user)(!(objectClass=computer)))` to exclude Computer accounts. | ||||||
| - Group object filter: Which objects should be considered groups. | - Group object filter: Which objects should be considered groups. | ||||||
| - Group membership field: Which user field saves the group membership | - Group membership field: Which user field saves the group membership | ||||||
| - Object uniqueness field: A user field which contains a unique Identifier | - Object uniqueness field: A user field which contains a unique Identifier | ||||||
| - Sync parent group: If enabled, all synchronized groups will be given this group as a parent. |  | ||||||
|  |  | ||||||
| After you save the source, a synchronization will start in the background. When its done, you cen see the summary on the System Tasks page. | After you save the source, a synchronization will start in the background. When its done, you can see the summary under Dashboards -> System Tasks. | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -33,3 +33,11 @@ For FreeIPA, follow the [FreeIPA Integration](../freeipa/) | |||||||
| - Sync groups: Enable/disable group synchronization. Groups are synced in the background every 5 minutes. | - Sync groups: Enable/disable group synchronization. Groups are synced in the background every 5 minutes. | ||||||
| - Sync parent group: Optionally set this group as the parent group for all synced groups. An example use case of this would be to import Active Directory groups under a root `imported-from-ad` group. | - Sync parent group: Optionally set this group as the parent group for all synced groups. An example use case of this would be to import Active Directory groups under a root `imported-from-ad` group. | ||||||
| - Property mappings: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also [LDAP Property Mappings](../../../docs/property-mappings/#ldap-property-mapping) | - Property mappings: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also [LDAP Property Mappings](../../../docs/property-mappings/#ldap-property-mapping) | ||||||
|  |  | ||||||
|  | ## Property mappings | ||||||
|  |  | ||||||
|  | LDAP property mappings can be used to convert the raw LDAP response into an authentik user/group. | ||||||
|  |  | ||||||
|  | By default, authentik ships with some pre-configured mappings for the most common LDAP setups. | ||||||
|  |  | ||||||
|  | You can assign the value of a mapping to any user attribute, or save it as a custom attribute by prefixing the object field with `attribute.` Keep in mind though, data types from the LDAP server will be carried over. This means that with some implementations, where fields ar stored as array in LDAP, they will be saved as array in authentik. To prevent this, use the built-in `list_flatten` function. | ||||||
|  | |||||||
							
								
								
									
										3007
									
								
								website/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3007
									
								
								website/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -12,8 +12,8 @@ | |||||||
|         "serve": "docusaurus serve" |         "serve": "docusaurus serve" | ||||||
|     }, |     }, | ||||||
|     "dependencies": { |     "dependencies": { | ||||||
|         "@docusaurus/plugin-client-redirects": "2.0.0-beta.14", |         "@docusaurus/plugin-client-redirects": "2.0.0-beta.15", | ||||||
|         "@docusaurus/preset-classic": "2.0.0-beta.14", |         "@docusaurus/preset-classic": "2.0.0-beta.15", | ||||||
|         "@mdx-js/react": "^1.6.22", |         "@mdx-js/react": "^1.6.22", | ||||||
|         "clsx": "^1.1.1", |         "clsx": "^1.1.1", | ||||||
|         "postcss": "^8.4.5", |         "postcss": "^8.4.5", | ||||||
|  | |||||||
| @ -26,5 +26,9 @@ module.exports = { | |||||||
|             type: "doc", |             type: "doc", | ||||||
|             id: "translation", |             id: "translation", | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             type: "doc", | ||||||
|  |             id: "docs/writing-documentation", | ||||||
|  |         }, | ||||||
|     ], |     ], | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -42,6 +42,7 @@ module.exports = { | |||||||
|                 "services/wiki-js/index", |                 "services/wiki-js/index", | ||||||
|                 "services/wordpress/index", |                 "services/wordpress/index", | ||||||
|                 "services/zabbix/index", |                 "services/zabbix/index", | ||||||
|  |                 "services/zulip/index", | ||||||
|             ], |             ], | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	