Merge branch 'next' into form-refresh-on-save

This commit is contained in:
Jens Langhammer 2021-05-11 11:47:29 +02:00
commit fd44765ff4
60 changed files with 755 additions and 535 deletions

View File

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

View File

@ -1,5 +1,13 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily
time: "04:00"
open-pull-requests-limit: 10
assignees:
- BeryJu
- package-ecosystem: gomod
directory: "/outpost"
schedule:

View File

@ -3,36 +3,49 @@ name: authentik-on-release
on:
release:
types: [published, created]
push:
branches:
- version-*
jobs:
# Build
build-server:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v1.1.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Docker Login Registry
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_PASSWORD }}
password: ${{ secrets.DOCKER_USERNAME }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: prepare ts api client
run: |
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/api --additional-properties=typescriptThreePlus=true,supportsES6=true,npmName=authentik-api,npmVersion=1.0.0
- name: Building Docker Image
uses: docker/build-push-action@v2
with:
push: true
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik:2021.4.5,
beryju/authentik:2021.5.1-rc7,
beryju/authentik:latest,
ghcr.io/goauthentik/server:2021.4.5,
ghcr.io/goauthentik/server:2021.5.1-rc7,
ghcr.io/goauthentik/server:latest
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8
platforms: linux/amd64,linux/arm64
context: .
build-proxy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "^1.15"
@ -41,32 +54,38 @@ jobs:
cd outpost
go get -u github.com/go-swagger/go-swagger/cmd/swagger
swagger generate client -f ../swagger.yaml -A authentik -t pkg/
go build -v .
go build -v ./cmd/proxy/server.go
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v1.1.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Docker Login Registry
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_PASSWORD }}
password: ${{ secrets.DOCKER_USERNAME }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Building Docker Image
uses: docker/build-push-action@v2
with:
push: true
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-proxy:2021.4.5,
beryju/authentik-proxy:2021.5.1-rc7,
beryju/authentik-proxy:latest,
ghcr.io/goauthentik/proxy:2021.4.5,
ghcr.io/goauthentik/proxy:2021.5.1-rc7,
ghcr.io/goauthentik/proxy:latest
context: outpost/
file: outpost/proxy.Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8
platforms: linux/amd64,linux/arm64
build-ldap:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "^1.15"
@ -75,36 +94,43 @@ jobs:
cd outpost
go get -u github.com/go-swagger/go-swagger/cmd/swagger
swagger generate client -f ../swagger.yaml -A authentik -t pkg/
go build -v .
go build -v ./cmd/ldap/server.go
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v1.1.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Docker Login Registry
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_PASSWORD }}
password: ${{ secrets.DOCKER_USERNAME }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Building Docker Image
uses: docker/build-push-action@v2
with:
push: true
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-ldap:2021.4.5,
beryju/authentik-ldap:2021.5.1-rc7,
beryju/authentik-ldap:latest,
ghcr.io/goauthentik/ldap:2021.4.5,
ghcr.io/goauthentik/ldap:2021.5.1-rc7,
ghcr.io/goauthentik/ldap:latest
context: outpost/
file: outpost/ldap.Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8
platforms: linux/amd64,linux/arm64
test-release:
if: ${{ github.event_name == 'release' }}
needs:
- build-server
- build-proxy
- build-ldap
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Run test suite in final docker images
run: |
sudo apt-get install -y pwgen
@ -115,11 +141,12 @@ jobs:
docker-compose start postgresql redis
docker-compose run -u root --entrypoint /bin/bash server -c "pip install --no-cache -r requirements-dev.txt && ./manage.py test authentik"
sentry-release:
if: ${{ github.event_name == 'release' }}
needs:
- test-release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Create a Sentry.io release
uses: getsentry/action-release@v1
env:
@ -128,5 +155,5 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
version: authentik@2021.4.5
version: authentik@2021.5.1-rc7
environment: beryjuorg-prod

View File

@ -10,7 +10,10 @@ jobs:
name: Create Release from Tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/checkout@v2
- name: prepare ts api client
run: |
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/api --additional-properties=typescriptThreePlus=true,supportsES6=true,npmName=authentik-api,npmVersion=1.0.0
- name: Pre-release test
run: |
sudo apt-get install -y pwgen

View File

@ -52,11 +52,12 @@ RUN apt-get update && \
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \
echo "deb http://apt.postgresql.org/pub/repos/apt buster-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
apt-get update && \
apt-get install -y --no-install-recommends postgresql-client-12 postgresql-client-11 build-essential libxmlsec1-dev pkg-config libmaxminddb0 && \
apt-get clean && \
apt-get install -y --no-install-recommends libpq-dev postgresql-client build-essential libxmlsec1-dev pkg-config libmaxminddb0 && \
pip install -r /requirements.txt --no-cache-dir && \
apt-get remove --purge -y build-essential && \
apt-get autoremove --purge -y && \
apt-get clean && \
rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/ && \
# This is quite hacky, but docker has no guaranteed Group ID
# we could instead check for the GID of the socket and add the user dynamically,
# but then we have to drop permmissions later

36
Pipfile.lock generated
View File

@ -88,10 +88,10 @@
},
"attrs": {
"hashes": [
"sha256:3901be1cb7c2a780f14668691474d9252c070a756be0a9ead98cfeabfa11aeb8",
"sha256:8ee1e5f5a1afc5b19bdfae4fdf0c35ed324074bdce3500c939842c8f818645d9"
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
],
"version": "==21.1.0"
"version": "==21.2.0"
},
"autobahn": {
"hashes": [
@ -116,18 +116,18 @@
},
"boto3": {
"hashes": [
"sha256:56f1766f1271b6b4e979c7b56225377f8912050e5935adc5c1c9e3a0338b949e",
"sha256:c61c809d288e88b9a0d926f56f803d0128b498aa9b45a42a6e03cd9a83e5c124"
"sha256:6c8c9c173a8d6c5127a9812ec4b9369280caec4f574e297900dc8e735a92f71f",
"sha256:8bdbe29bc9308124e7e96ef912dfa1d656400499edcf398b677db739939e9ba6"
],
"index": "pypi",
"version": "==1.17.68"
"version": "==1.17.70"
},
"botocore": {
"hashes": [
"sha256:0f693f5ad6348ec1a62b3a66fee2840d3b722d66b44896022d644275ff8b143d",
"sha256:eb3544911cb0316a33b328a27d137130af278a9c0006be0c95e5e402b01d9865"
"sha256:3dea2656b5555a1bcb299a83fdefe6f0ef331ffae55cc8f8edf06557342738c0",
"sha256:9bc8bd5f601d35658b2aaa78ebeef154fd092e64b37059e8eeef51648a3936c8"
],
"version": "==1.20.68"
"version": "==1.20.70"
},
"cachetools": {
"hashes": [
@ -351,11 +351,11 @@
},
"django-otp": {
"hashes": [
"sha256:04852c5301befb02d1d8ba4a31d375eb08d7c2cb6fe86b5f840867435ab1309c",
"sha256:3916fc7652c2f934b1cf3807dd8ed257ce7605c10dfefa27fadda5628d9a9c9e"
"sha256:75a815747a0542cc5442e3a6396dfd272c49a0866bee2149ac57ecc36ddd3961",
"sha256:cc657a0e7266cda6ab42f861bdc3840ed24f7e441bc7f249916174dd1a6375a0"
],
"index": "pypi",
"version": "==1.0.4"
"version": "==1.0.5"
},
"django-prometheus": {
"hashes": [
@ -1101,11 +1101,11 @@
},
"service-identity": {
"hashes": [
"sha256:001c0707759cb3de7e49c078a7c0c9cd12594161d3bf06b9c254fdcb1a60dc36",
"sha256:0858a54aabc5b459d1aafa8a518ed2081a285087f349fe3e55197989232e2e2d"
"sha256:6e6c6086ca271dc11b033d17c3a8bea9f24ebff920c587da090afc9519419d34",
"sha256:f0b0caac3d40627c3c04d7a51b6e06721857a0e10a8775f2d1d7e72901b3a7db"
],
"index": "pypi",
"version": "==18.1.0"
"version": "==21.1.0"
},
"six": {
"hashes": [
@ -1424,10 +1424,10 @@
},
"attrs": {
"hashes": [
"sha256:3901be1cb7c2a780f14668691474d9252c070a756be0a9ead98cfeabfa11aeb8",
"sha256:8ee1e5f5a1afc5b19bdfae4fdf0c35ed324074bdce3500c939842c8f818645d9"
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
],
"version": "==21.1.0"
"version": "==21.2.0"
},
"bandit": {
"hashes": [

View File

@ -1,3 +1,3 @@
"""authentik"""
__version__ = "2021.4.5"
__version__ = "2021.5.1-rc7"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -7,6 +7,7 @@ from django.urls import reverse
from authentik import __version__
from authentik.core.models import Group, User
from authentik.core.tasks import clean_expired_models
from authentik.events.monitored_tasks import TaskResultStatus
class TestAdminAPI(TestCase):
@ -30,6 +31,26 @@ class TestAdminAPI(TestCase):
any(task["task_name"] == "clean_expired_models" for task in body)
)
def test_tasks_single(self):
"""Test Task API (read single)"""
clean_expired_models.delay()
response = self.client.get(
reverse(
"authentik_api:admin_system_tasks-detail",
kwargs={"pk": "clean_expired_models"},
)
)
self.assertEqual(response.status_code, 200)
body = loads(response.content)
self.assertEqual(body["status"], TaskResultStatus.SUCCESSFUL.name)
self.assertEqual(body["task_name"], "clean_expired_models")
response = self.client.get(
reverse(
"authentik_api:admin_system_tasks-detail", kwargs={"pk": "qwerqwer"}
)
)
self.assertEqual(response.status_code, 404)
def test_tasks_retry(self):
"""Test Task API (retry)"""
clean_expired_models.delay()

View File

@ -54,4 +54,4 @@ class AuthentikTokenAuthentication(BaseAuthentication):
if not token:
return None
return (token.user, None)
return (token.user, None) # pragma: no cover

View File

@ -22,3 +22,10 @@ class TestSwaggerGeneration(APITestCase):
reverse("authentik_api:schema-json", kwargs={"format": ".json"}),
)
self.assertTrue(loads(response.content.decode()))
def test_browser(self):
"""Test API Browser"""
response = self.client.get(
reverse("authentik_api:swagger"),
)
self.assertEqual(response.status_code, 200)

View File

@ -3,6 +3,7 @@ from enum import Enum
from typing import Any, Optional, Type
from django.contrib import messages
from django.db import IntegrityError
from django.db.models.query_utils import Q
from django.http import HttpRequest, HttpResponse, HttpResponseBadRequest
from django.shortcuts import redirect
@ -116,9 +117,11 @@ class SourceFlowManager:
)
return Action.DENY, None
query = Q(username__exact=self.enroll_info.get("username", None))
self._logger.debug("trying to link with existing user", query=query)
matching_users = User.objects.filter(query)
# No matching users, always enroll
if not matching_users.exists():
self._logger.debug("no matching users found, enrolling")
return Action.ENROLL, self.update_connection(new_connection, **kwargs)
user = matching_users.first()
@ -147,7 +150,11 @@ class SourceFlowManager:
def get_flow(self, **kwargs) -> HttpResponse:
"""Get the flow response based on user_matching_mode"""
action, connection = self.get_action(**kwargs)
try:
action, connection = self.get_action(**kwargs)
except IntegrityError as exc:
self._logger.warning("failed to get action", exc=exc)
return redirect("/")
self._logger.debug("get_action() says", action=action, connection=connection)
if connection:
if action == Action.LINK:

View File

@ -1,7 +1,9 @@
"""Notification API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from guardian.utils import get_anonymous_user
from rest_framework import mixins
from rest_framework.fields import ReadOnlyField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
@ -47,6 +49,11 @@ class NotificationViewSet(
"event",
"seen",
]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()

View File

@ -0,0 +1,13 @@
"""Fix dbbackup quoting the password"""
from dbbackup.db.postgresql import PgDumpConnector
class PgCustom(PgDumpConnector):
"""Fix dbbackup quoting the password"""
def run_command(self, *args, **kwargs):
if self.settings.get("PASSWORD"):
env = kwargs.get("env", {})
env["PGPASSWORD"] = self.settings["PASSWORD"]
kwargs["env"] = env
return super(PgDumpConnector, self).run_command(*args, **kwargs)

View File

@ -3,6 +3,7 @@ postgresql:
host: localhost
name: authentik
user: authentik
port: 5432
password: 'env://POSTGRES_PASSWORD'
web:

View File

@ -1,23 +1,35 @@
"""Outpost API Views"""
from dacite.core import from_dict
from dacite.exceptions import DaciteError
from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.fields import BooleanField, CharField, DateTimeField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import JSONField, ModelSerializer
from rest_framework.serializers import JSONField, ModelSerializer, ValidationError
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.utils import PassiveSerializer, is_dict
from authentik.outposts.models import Outpost, default_outpost_config
from authentik.outposts.models import Outpost, OutpostConfig, default_outpost_config
class OutpostSerializer(ModelSerializer):
"""Outpost Serializer"""
_config = JSONField(validators=[is_dict])
config = JSONField(validators=[is_dict], source="_config")
# TODO: Remove _config again, this is only here for legacy with older outposts
_config = JSONField(validators=[is_dict], read_only=True)
providers_obj = ProviderSerializer(source="providers", many=True, read_only=True)
def validate_config(self, config) -> dict:
"""Check that the config has all required fields"""
try:
from_dict(OutpostConfig, config)
except DaciteError as exc:
raise ValidationError(f"Failed to validate config: {str(exc)}") from exc
return config
class Meta:
model = Outpost
@ -29,6 +41,7 @@ class OutpostSerializer(ModelSerializer):
"providers_obj",
"service_connection",
"token_identifier",
"config",
"_config",
]

View File

@ -56,6 +56,12 @@ class BaseController:
"""Handler to delete everything we've created"""
raise NotImplementedError
def down_with_logs(self) -> list[str]:
"""Call .down() but capture all log output and return it."""
with capture_logs() as logs:
self.down()
return [x["event"] for x in logs]
def get_static_deployment(self) -> str:
"""Return a static deployment configuration"""
raise NotImplementedError

View File

@ -30,11 +30,6 @@ class NeedsUpdate(ReconcileTrigger):
"""Exception to trigger an update to the Kubernetes Object"""
class Disabled(SentryIgnoredException):
"""Exception which can be thrown in a reconciler to signal than an
object should not be created."""
class KubernetesObjectReconciler(Generic[T]):
"""Base Kubernetes Reconciler, handles the basic logic."""
@ -45,22 +40,29 @@ class KubernetesObjectReconciler(Generic[T]):
self.namespace = controller.outpost.config.kubernetes_namespace
self.logger = get_logger().bind(type=self.__class__.__name__)
@property
def noop(self) -> bool:
"""Return true if this object should not be created/updated/deleted in this cluster"""
return False
@property
def name(self) -> str:
"""Get the name of the object this reconciler manages"""
return self.controller.outpost.config.object_naming_template % {
"name": slugify(self.controller.outpost.name),
"uuid": self.controller.outpost.uuid.hex,
}
return (
self.controller.outpost.config.object_naming_template
% {
"name": slugify(self.controller.outpost.name),
"uuid": self.controller.outpost.uuid.hex,
}
).lower()
def up(self):
"""Create object if it doesn't exist, update if needed or recreate if needed."""
current = None
try:
reference = self.get_reference_object()
except Disabled:
self.logger.debug("Object not required")
if self.noop:
self.logger.debug("Object is noop")
return
reference = self.get_reference_object()
try:
try:
current = self.retrieve()
@ -89,11 +91,8 @@ class KubernetesObjectReconciler(Generic[T]):
def down(self):
"""Delete object if found"""
# Call self.get_reference_object to check if we even need to do anything
try:
self.get_reference_object()
except Disabled:
self.logger.debug("Object not required")
if self.noop:
self.logger.debug("Object is noop")
return
try:
current = self.retrieve()

View File

@ -0,0 +1,11 @@
"""k8s utils"""
from pathlib import Path
def get_namespace() -> str:
"""Get the namespace if we're running in a pod, otherwise default to default"""
path = Path("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if path.exists():
with open(path, "r") as _namespace_file:
return _namespace_file.read()
return "default"

View File

@ -8,7 +8,7 @@ from structlog.testing import capture_logs
from yaml import dump_all
from authentik.outposts.controllers.base import BaseController, ControllerException
from authentik.outposts.controllers.k8s.base import Disabled, KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
from authentik.outposts.controllers.k8s.secret import SecretReconciler
from authentik.outposts.controllers.k8s.service import ServiceReconciler
@ -49,6 +49,9 @@ class KubernetesController(BaseController):
try:
all_logs = []
for reconcile_key in self.reconcile_order:
if reconcile_key in self.outpost.config.kubernetes_disabled_components:
all_logs += [f"{reconcile_key.title()}: Disabled"]
continue
with capture_logs() as logs:
reconciler = self.reconcilers[reconcile_key](self)
reconciler.up()
@ -61,19 +64,34 @@ class KubernetesController(BaseController):
try:
for reconcile_key in self.reconcile_order:
reconciler = self.reconcilers[reconcile_key](self)
self.logger.debug("Tearing down object", name=reconcile_key)
reconciler.down()
except ApiException as exc:
raise ControllerException(str(exc)) from exc
def down_with_logs(self) -> list[str]:
try:
all_logs = []
for reconcile_key in self.reconcile_order:
if reconcile_key in self.outpost.config.kubernetes_disabled_components:
all_logs += [f"{reconcile_key.title()}: Disabled"]
continue
with capture_logs() as logs:
reconciler = self.reconcilers[reconcile_key](self)
reconciler.down()
all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs]
return all_logs
except ApiException as exc:
raise ControllerException(str(exc)) from exc
def get_static_deployment(self) -> str:
documents = []
for reconcile_key in self.reconcile_order:
reconciler = self.reconcilers[reconcile_key](self)
try:
documents.append(reconciler.get_reference_object().to_dict())
except Disabled:
if reconciler.noop:
continue
documents.append(reconciler.get_reference_object().to_dict())
with StringIO() as _str:
dump_all(

View File

@ -33,6 +33,7 @@ from authentik.lib.config import CONFIG
from authentik.lib.models import InheritanceForeignKey
from authentik.lib.sentry import SentryIgnoredException
from authentik.lib.utils.http import USER_ATTRIBUTE_CAN_OVERRIDE_IP
from authentik.outposts.controllers.k8s.utils import get_namespace
from authentik.outposts.docker_tls import DockerInlineTLS
OUR_VERSION = parse(__version__)
@ -59,10 +60,11 @@ class OutpostConfig:
object_naming_template: str = field(default="ak-outpost-%(name)s")
kubernetes_replicas: int = field(default=1)
kubernetes_namespace: str = field(default="default")
kubernetes_namespace: str = field(default_factory=get_namespace)
kubernetes_ingress_annotations: dict[str, str] = field(default_factory=dict)
kubernetes_ingress_secret_name: str = field(default="authentik-outpost-tls")
kubernetes_service_type: str = field(default="ClusterIP")
kubernetes_disabled_components: list[str] = field(default_factory=list)
class OutpostModel(Model):

View File

@ -1,5 +1,5 @@
"""authentik outpost signals"""
from django.conf import settings
from django.core.cache import cache
from django.db.models import Model
from django.db.models.signals import post_save, pre_delete, pre_save
from django.dispatch import receiver
@ -8,9 +8,12 @@ from structlog.stdlib import get_logger
from authentik.core.models import Provider
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.utils.reflection import class_to_path
from authentik.outposts.controllers.base import ControllerException
from authentik.outposts.models import Outpost, OutpostServiceConnection
from authentik.outposts.tasks import outpost_controller_down, outpost_post_save
from authentik.outposts.tasks import (
CACHE_KEY_OUTPOST_DOWN,
outpost_controller,
outpost_post_save,
)
LOGGER = get_logger()
UPDATE_TRIGGERING_MODELS = (
@ -39,7 +42,8 @@ def pre_save_outpost(sender, instance: Outpost, **_):
)
if bool(dirty):
LOGGER.info("Outpost needs re-deployment due to changes", instance=instance)
outpost_controller_down_wrapper(old_instance)
cache.set(CACHE_KEY_OUTPOST_DOWN % instance.pk.hex, old_instance)
outpost_controller.delay(instance.pk.hex, action="down", from_cache=True)
@receiver(post_save)
@ -63,23 +67,5 @@ def post_save_update(sender, instance: Model, **_):
def pre_delete_cleanup(sender, instance: Outpost, **_):
"""Ensure that Outpost's user is deleted (which will delete the token through cascade)"""
instance.user.delete()
outpost_controller_down_wrapper(instance)
def outpost_controller_down_wrapper(instance: Outpost):
"""To ensure that deployment is cleaned up *consistently* we call the controller, and wait
for it to finish. We don't want to call it in this thread, as we don't have the Outpost
Service connection here"""
try:
outpost_controller_down.delay(instance.pk.hex).get()
except RuntimeError: # pragma: no cover
# In e2e/integration tests, this might run inside a thread/process and
# trigger the celery `Never call result.get() within a task` detection
if settings.TEST:
pass
else:
raise
except ControllerException as exc:
LOGGER.warning(
"failed to cleanup outpost deployment", exc=exc, instance=instance
)
cache.set(CACHE_KEY_OUTPOST_DOWN % instance.pk.hex, instance)
outpost_controller.delay(instance.pk.hex, action="down", from_cache=True)

View File

@ -36,6 +36,7 @@ from authentik.providers.proxy.controllers.kubernetes import ProxyKubernetesCont
from authentik.root.celery import CELERY_APP
LOGGER = get_logger()
CACHE_KEY_OUTPOST_DOWN = "outpost_teardown_%s"
def controller_for_outpost(outpost: Outpost) -> Optional[BaseController]:
@ -56,13 +57,6 @@ def controller_for_outpost(outpost: Outpost) -> Optional[BaseController]:
return None
@CELERY_APP.task()
def outpost_controller_all():
"""Launch Controller for all Outposts which support it"""
for outpost in Outpost.objects.exclude(service_connection=None):
outpost_controller.delay(outpost.pk.hex)
@CELERY_APP.task()
def outpost_service_connection_state(connection_pk: Any):
"""Update cached state of a service connection"""
@ -89,17 +83,29 @@ def outpost_service_connection_monitor(self: MonitoredTask):
)
@CELERY_APP.task()
def outpost_controller_all():
"""Launch Controller for all Outposts which support it"""
for outpost in Outpost.objects.exclude(service_connection=None):
outpost_controller.delay(outpost.pk.hex, "up", from_cache=False)
@CELERY_APP.task(bind=True, base=MonitoredTask)
def outpost_controller(self: MonitoredTask, outpost_pk: str):
"""Create/update/monitor the deployment of an Outpost"""
def outpost_controller(
self: MonitoredTask, outpost_pk: str, action: str = "up", from_cache: bool = False
):
"""Create/update/monitor/delete the deployment of an Outpost"""
logs = []
outpost: Outpost = Outpost.objects.get(pk=outpost_pk)
if from_cache:
outpost: Outpost = cache.get(CACHE_KEY_OUTPOST_DOWN % outpost_pk)
else:
outpost: Outpost = Outpost.objects.get(pk=outpost_pk)
self.set_uid(slugify(outpost.name))
try:
controller = controller_for_outpost(outpost)
if not controller:
return
logs = controller.up_with_logs()
logs = getattr(controller, f"{action}_with_logs")()
LOGGER.debug("---------------Outpost Controller logs starting----------------")
for log in logs:
LOGGER.debug(log)
@ -110,16 +116,6 @@ def outpost_controller(self: MonitoredTask, outpost_pk: str):
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, logs))
@CELERY_APP.task()
def outpost_controller_down(outpost_pk: str):
"""Delete outpost objects before deleting the DB Object"""
outpost = Outpost.objects.get(pk=outpost_pk)
controller = controller_for_outpost(outpost)
if not controller:
return
controller.down()
@CELERY_APP.task(bind=True, base=MonitoredTask)
def outpost_token_ensurer(self: MonitoredTask):
"""Periodically ensure that all Outposts have valid Service Accounts

View File

@ -3,6 +3,10 @@ from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import PropertyMapping, User
from authentik.flows.models import Flow
from authentik.outposts.api.outposts import OutpostSerializer
from authentik.outposts.models import default_outpost_config
from authentik.providers.proxy.models import ProxyProvider
class TestOutpostServiceConnectionsAPI(APITestCase):
@ -22,3 +26,22 @@ class TestOutpostServiceConnectionsAPI(APITestCase):
reverse("authentik_api:outpostserviceconnection-types"),
)
self.assertEqual(response.status_code, 200)
def test_outpost_config(self):
"""Test Outpost's config field"""
provider = ProxyProvider.objects.create(
name="test", authorization_flow=Flow.objects.first()
)
invalid = OutpostSerializer(
data={"name": "foo", "providers": [provider.pk], "config": {}}
)
self.assertFalse(invalid.is_valid())
self.assertIn("config", invalid.errors)
valid = OutpostSerializer(
data={
"name": "foo",
"providers": [provider.pk],
"config": default_outpost_config("foo"),
}
)
self.assertTrue(valid.is_valid())

View File

@ -1,7 +1,9 @@
"""OAuth2Provider API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from guardian.utils import get_anonymous_user
from rest_framework import mixins
from rest_framework.fields import CharField, ListField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
@ -37,6 +39,11 @@ class AuthorizationCodeViewSet(
serializer_class = ExpiringBaseGrantModelSerializer
filterset_fields = ["user", "provider"]
ordering = ["provider", "expires"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()
@ -57,6 +64,11 @@ class RefreshTokenViewSet(
serializer_class = ExpiringBaseGrantModelSerializer
filterset_fields = ["user", "provider"]
ordering = ["provider", "expires"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()

View File

@ -17,7 +17,6 @@ from kubernetes.client.models.networking_v1beta1_ingress_rule import (
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import (
Disabled,
KubernetesObjectReconciler,
NeedsUpdate,
)
@ -137,9 +136,6 @@ class IngressReconciler(KubernetesObjectReconciler[NetworkingV1beta1Ingress]):
),
)
rules.append(rule)
if not rules:
self.logger.debug("No providers use proxying, no ingress needed")
raise Disabled()
tls_config = None
if tls_hosts:
tls_config = NetworkingV1beta1IngressTLS(

View File

@ -7,7 +7,6 @@ from kubernetes.client import ApiextensionsV1Api, CustomObjectsApi
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import (
Disabled,
KubernetesObjectReconciler,
NeedsUpdate,
)
@ -70,6 +69,19 @@ class TraefikMiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware])
self.api_ex = ApiextensionsV1Api(controller.client)
self.api = CustomObjectsApi(controller.client)
@property
def noop(self) -> bool:
if not ProxyProvider.objects.filter(
outpost__in=[self.controller.outpost],
forward_auth_mode=True,
).exists():
self.logger.debug("No providers with forward auth enabled.")
return True
if not self._crd_exists():
self.logger.debug("CRD doesn't exist")
return True
return False
def _crd_exists(self) -> bool:
"""Check if the traefik middleware exists"""
return bool(
@ -87,15 +99,6 @@ class TraefikMiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware])
def get_reference_object(self) -> TraefikMiddleware:
"""Get deployment object for outpost"""
if not ProxyProvider.objects.filter(
outpost__in=[self.controller.outpost],
forward_auth_mode=True,
).exists():
self.logger.debug("No providers with forward auth enabled.")
raise Disabled()
if not self._crd_exists():
self.logger.debug("CRD doesn't exist")
raise Disabled()
return TraefikMiddleware(
apiVersion=f"{CRD_GROUP}/{CRD_VERSION}",
kind="Middleware",

View File

@ -248,6 +248,7 @@ DATABASES = {
"NAME": CONFIG.y("postgresql.name"),
"USER": CONFIG.y("postgresql.user"),
"PASSWORD": CONFIG.y("postgresql.password"),
"PORT": int(CONFIG.y("postgresql.port")),
}
}
@ -320,7 +321,8 @@ CELERY_RESULT_BACKEND = (
DBBACKUP_STORAGE = "django.core.files.storage.FileSystemStorage"
DBBACKUP_STORAGE_OPTIONS = {"location": "./backups" if DEBUG else "/backups"}
DBBACKUP_CONNECTOR_MAPPING = {
"django_prometheus.db.backends.postgresql": "dbbackup.db.postgresql.PgDumpConnector"
"django_prometheus.db.backends.postgresql": "authentik.lib.connector.PgCustom",
"django.db.backends.postgresql": "authentik.lib.connector.PgCustom",
}
if CONFIG.y("postgresql.s3_backup"):
DBBACKUP_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
@ -331,9 +333,10 @@ if CONFIG.y("postgresql.s3_backup"):
"region_name": CONFIG.y("postgresql.s3_backup.region", "eu-central-1"),
"default_acl": "private",
"endpoint_url": CONFIG.y("postgresql.s3_backup.host"),
"location": CONFIG.y("postgresql.s3_backup.location", ""),
}
j_print(
"Database backup to S3 is configured.",
"Database backup to S3 is configured",
host=CONFIG.y("postgresql.s3_backup.host"),
)
@ -355,7 +358,7 @@ if _ERROR_REPORTING:
send_default_pii=CONFIG.y_bool("error_reporting.send_pii", False),
)
j_print(
"Error reporting is enabled.",
"Error reporting is enabled",
env=CONFIG.y("error_reporting.environment", "customer"),
)

View File

@ -75,6 +75,7 @@ class OAuthSourceSerializer(SourceSerializer):
"callback_url",
"type",
]
extra_kwargs = {"consumer_secret": {"write_only": True}}
class OAuthSourceViewSet(ModelViewSet):

View File

@ -1,5 +1,7 @@
"""OAuth Source Serializer"""
from django_filters.rest_framework import DjangoFilterBackend
from guardian.utils import get_anonymous_user
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.sources import SourceSerializer
@ -25,6 +27,11 @@ class UserOAuthSourceConnectionViewSet(ModelViewSet):
queryset = UserOAuthSourceConnection.objects.all()
serializer_class = UserOAuthSourceConnectionSerializer
filterset_fields = ["source__slug"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()

View File

@ -33,6 +33,5 @@ class TestTypeGoogle(TestCase):
def test_enroll_context(self):
"""Test Google Enrollment context"""
ak_context = GoogleOAuth2Callback().get_user_enroll_context(GOOGLE_USER)
self.assertEqual(ak_context["username"], GOOGLE_USER["email"])
self.assertEqual(ak_context["email"], GOOGLE_USER["email"])
self.assertEqual(ak_context["name"], GOOGLE_USER["name"])

View File

@ -23,7 +23,6 @@ class GoogleOAuth2Callback(OAuthCallback):
info: dict[str, Any],
) -> dict[str, Any]:
return {
"username": info.get("email"),
"email": info.get("email"),
"name": info.get("name"),
}

View File

@ -1,6 +1,9 @@
"""AuthenticatorStaticStage API Views"""
from django_filters import OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from django_otp.plugins.otp_static.models import StaticDevice
from guardian.utils import get_anonymous_user
from rest_framework.filters import SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
@ -43,6 +46,11 @@ class StaticDeviceViewSet(ModelViewSet):
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()

View File

@ -1,6 +1,8 @@
"""AuthenticatorTOTPStage API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from django_otp.plugins.otp_totp.models import TOTPDevice
from guardian.utils import get_anonymous_user
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
@ -46,6 +48,11 @@ class TOTPDeviceViewSet(ModelViewSet):
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()

View File

@ -1,5 +1,7 @@
"""AuthenticateWebAuthnStage API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from guardian.utils import get_anonymous_user
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
@ -45,6 +47,11 @@ class WebAuthnDeviceViewSet(ModelViewSet):
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()

View File

@ -1,6 +1,8 @@
"""ConsentStage API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from guardian.utils import get_anonymous_user
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from authentik.core.api.applications import ApplicationSerializer
@ -49,6 +51,11 @@ class UserConsentViewSet(
serializer_class = UserConsentSerializer
filterset_fields = ["user", "application"]
ordering = ["application", "expires"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()

View File

@ -19,7 +19,7 @@ variables:
branchName: ${{ replace(variables['Build.SourceBranchName'], 'refs/heads/', '') }}
stages:
- stage: Lint
- stage: Lint_and_test
jobs:
- job: pylint
pool:
@ -118,8 +118,6 @@ stages:
- task: CmdLine@2
inputs:
script: pipenv run pyright e2e lifecycle
- stage: Test
jobs:
- job: migrations
pool:
vmImage: 'ubuntu-latest'

View File

@ -21,7 +21,7 @@ services:
networks:
- internal
server:
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.4.5}
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.5.1-rc7}
restart: unless-stopped
command: server
environment:
@ -52,7 +52,7 @@ services:
- "0.0.0.0:9000:9000"
- "0.0.0.0:9443:9443"
worker:
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.4.5}
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.5.1-rc7}
restart: unless-stopped
command: worker
networks:

View File

@ -1,3 +1,3 @@
package constants
const VERSION = "2021.4.5"
const VERSION = "2021.5.1-rc7"

View File

@ -41,11 +41,9 @@ while True:
while True:
try:
redis = Redis(
host=CONFIG.y("redis.host"),
port=6379,
db=CONFIG.y("redis.message_queue_db"),
password=CONFIG.y("redis.password"),
redis = Redis.from_url(
f"redis://:{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:6379"
f"/{CONFIG.y('redis.ws_db')}"
)
redis.ping()
break

View File

@ -90,6 +90,10 @@ func (a *APIController) Start() error {
a.logger.Debug("Starting WS Health notifier...")
a.startWSHealth()
}()
go func() {
a.logger.Debug("Starting Interval updater...")
a.startIntervalUpdater()
}()
go func() {
err := a.Server.Start()
if err != nil {

View File

@ -111,3 +111,14 @@ func (ac *APIController) startWSHealth() {
}
}
}
func (ac *APIController) startIntervalUpdater() {
logger := ac.logger.WithField("loop", "interval-updater")
ticker := time.NewTicker(time.Second * 150)
for ; true; <-ticker.C {
err := ac.Server.Refresh()
if err != nil {
logger.WithError(err).Debug("Failed to update")
}
}
}

View File

@ -20,6 +20,8 @@ func doGlobalSetup(config map[string]interface{}) {
},
})
switch config[ConfigLogLevel].(string) {
case "trace":
log.SetLevel(log.TraceLevel)
case "debug":
log.SetLevel(log.DebugLevel)
case "info":

View File

@ -344,7 +344,11 @@ func (p *OAuthProxy) AuthenticateOnly(rw http.ResponseWriter, req *http.Request)
}
if _, ok := req.URL.Query()["traefik"]; ok {
host := getHost(req)
http.Redirect(rw, req, fmt.Sprintf("//%s%s", host, p.OAuthStartPath), http.StatusTemporaryRedirect)
proto := req.Header.Get("X-Forwarded-Proto")
if proto != "" {
proto = proto + ":"
}
http.Redirect(rw, req, fmt.Sprintf("%s//%s%s", proto, host, p.OAuthStartPath), http.StatusTemporaryRedirect)
return
}
}

View File

@ -1,3 +1,3 @@
package pkg
const VERSION = "2021.4.5"
const VERSION = "2021.5.1-rc7"

View File

@ -531,11 +531,6 @@ paths:
description: ''
required: false
type: string
- name: ordering
in: query
description: Which field to use when ordering the results.
required: false
type: string
- name: search
in: query
description: A search term.
@ -16203,7 +16198,7 @@ definitions:
required:
- name
- providers
- _config
- config
type: object
properties:
pk:
@ -16242,8 +16237,8 @@ definitions:
title: Token identifier
type: string
readOnly: true
_config:
title: config
config:
title: Config
type: object
OutpostDefaultConfig:
type: object

View File

@ -81,7 +81,7 @@ http {
location /static/ {
expires 31d;
add_header Cache-Control "public, no-transform";
add_header X-authentik-version "2021.4.5";
add_header X-authentik-version "2021.5.1-rc7";
add_header Vary X-authentik-version;
}

485
web/package-lock.json generated
View File

@ -24,13 +24,13 @@
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-replace": "^2.4.2",
"@rollup/plugin-typescript": "^8.2.1",
"@sentry/browser": "^6.3.5",
"@sentry/tracing": "^6.3.5",
"@sentry/browser": "^6.3.6",
"@sentry/tracing": "^6.3.6",
"@types/chart.js": "^2.9.32",
"@types/codemirror": "5.60.0",
"@types/grecaptcha": "^3.0.2",
"@typescript-eslint/eslint-plugin": "^4.22.1",
"@typescript-eslint/parser": "^4.22.1",
"@typescript-eslint/eslint-plugin": "^4.23.0",
"@typescript-eslint/parser": "^4.23.0",
"@webcomponents/webcomponentsjs": "^2.5.0",
"authentik-api": "file:api",
"babel-plugin-macros": "^3.1.0",
@ -39,10 +39,10 @@
"chartjs-adapter-moment": "^1.0.0",
"codemirror": "^5.61.0",
"construct-style-sheets-polyfill": "^2.4.16",
"eslint": "^7.25.0",
"eslint": "^7.26.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.2",
"eslint-plugin-lit": "^1.3.0",
"eslint-plugin-lit": "^1.4.0",
"flowchart.js": "^1.15.0",
"lit-element": "^2.5.1",
"lit-html": "^1.4.1",
@ -61,13 +61,12 @@
"typescript": "^4.2.4",
"webcomponent-qr-code": "^1.0.5",
"yaml": "^1.10.2"
},
"devDependencies": {}
}
},
"api": {
"name": "authentik-api",
"version": "1.0.0",
"devDependencies": {
"version": "0.0.1",
"dependencies": {
"typescript": "^3.6"
}
},
@ -75,7 +74,6 @@
"version": "3.9.9",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz",
"integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -1725,9 +1723,9 @@
}
},
"node_modules/@eslint/eslintrc": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
"integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==",
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz",
"integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==",
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.1.1",
@ -1752,6 +1750,9 @@
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@eslint/eslintrc/node_modules/ignore": {
@ -2337,33 +2338,13 @@
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg=="
},
"node_modules/@sentry/browser": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.3.5.tgz",
"integrity": "sha512-fjkhPR5gLCGVWhbWjEoN64hnmTvfTLRCgWmYTc9SiGchWFoFEmLqZyF2uJFyt27+qamLQ9fN58nnv4Ly2yyxqg==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.3.6.tgz",
"integrity": "sha512-l4323jxuBOArki6Wf+EHes39IEyJ2Zj/CIUaTY7GWh7CntpfHQAfFmZWQw3Ozq+ka1u8lVp25RPhb4Wng3azNA==",
"dependencies": {
"@sentry/core": "6.3.5",
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"tslib": "^1.9.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@sentry/browser/node_modules/@sentry/types": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz",
"integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ==",
"engines": {
"node": ">=6"
}
},
"node_modules/@sentry/browser/node_modules/@sentry/utils": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz",
"integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==",
"dependencies": {
"@sentry/types": "6.3.5",
"@sentry/core": "6.3.6",
"@sentry/types": "6.3.6",
"@sentry/utils": "6.3.6",
"tslib": "^1.9.3"
},
"engines": {
@ -2376,60 +2357,14 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/core": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.3.5.tgz",
"integrity": "sha512-VR2ibDy33mryD0mT6d9fGhKjdNzS2FSwwZPe9GvmNOjkyjly/oV91BKVoYJneCqOeq8fyj2lvkJGKuupdJNDqg==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.3.6.tgz",
"integrity": "sha512-w6BRizAqh7BaiM9oeKzO6aACXwRijUPacYaVLX/OfhqCSueF9uDxpMRT7+4D/eCeDVqgJYhBJ4Vsu2NSstkk4A==",
"dependencies": {
"@sentry/hub": "6.3.5",
"@sentry/minimal": "6.3.5",
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"tslib": "^1.9.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@sentry/core/node_modules/@sentry/hub": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.5.tgz",
"integrity": "sha512-ZYFo7VYKwdPVjuV9BDFiYn+MpANn6eZMz5QDBfZ2dugIvIVbuOyOOLx8PSa3ZXJoVTZZ7s2wD2fi/ZxKjNjZOQ==",
"dependencies": {
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"tslib": "^1.9.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@sentry/core/node_modules/@sentry/minimal": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.5.tgz",
"integrity": "sha512-4RqIGAU0+8iI/1sw0GYPTr4SUA88/i2+JPjFJ+qloh5ANVaNwhFPRChw+Ys9xpre8LV9JZrEsEf8AvQr4fkNbA==",
"dependencies": {
"@sentry/hub": "6.3.5",
"@sentry/types": "6.3.5",
"tslib": "^1.9.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@sentry/core/node_modules/@sentry/types": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz",
"integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ==",
"engines": {
"node": ">=6"
}
},
"node_modules/@sentry/core/node_modules/@sentry/utils": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz",
"integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==",
"dependencies": {
"@sentry/types": "6.3.5",
"@sentry/hub": "6.3.6",
"@sentry/minimal": "6.3.6",
"@sentry/types": "6.3.6",
"@sentry/utils": "6.3.6",
"tslib": "^1.9.3"
},
"engines": {
@ -2442,12 +2377,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/hub": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.5.tgz",
"integrity": "sha512-ZYFo7VYKwdPVjuV9BDFiYn+MpANn6eZMz5QDBfZ2dugIvIVbuOyOOLx8PSa3ZXJoVTZZ7s2wD2fi/ZxKjNjZOQ==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.6.tgz",
"integrity": "sha512-foBZ3ilMnm9Gf9OolrAxYHK8jrA6IF72faDdJ3Al+1H27qcpnBaMdrdEp2/jzwu/dgmwuLmbBaMjEPXaGH/0JQ==",
"dependencies": {
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"@sentry/types": "6.3.6",
"@sentry/utils": "6.3.6",
"tslib": "^1.9.3"
},
"engines": {
@ -2460,12 +2395,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/minimal": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.5.tgz",
"integrity": "sha512-4RqIGAU0+8iI/1sw0GYPTr4SUA88/i2+JPjFJ+qloh5ANVaNwhFPRChw+Ys9xpre8LV9JZrEsEf8AvQr4fkNbA==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.6.tgz",
"integrity": "sha512-uM2/dH0a6zfvI5f+vg+/mST+uTBdN6Jgpm585ipH84ckCYQwIIDRg6daqsen4S1sy/xgg1P1YyC3zdEC4G6b1Q==",
"dependencies": {
"@sentry/hub": "6.3.5",
"@sentry/types": "6.3.5",
"@sentry/hub": "6.3.6",
"@sentry/types": "6.3.6",
"tslib": "^1.9.3"
},
"engines": {
@ -2478,14 +2413,14 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/tracing": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.3.5.tgz",
"integrity": "sha512-TNKAST1ge2g24BlTfVxNp4gP5t3drbi0OVCh8h8ah+J7UjHSfdiqhd9W2h5qv1GO61gGlpWeN/TyioyQmOxu0Q==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.3.6.tgz",
"integrity": "sha512-dfyYY2eESJGt5Qbigmfmb2U9ntqbwPhLNAOcjKaVg9WQRV5q2RkHCVctPoYk7TEAvfNeNRXCD8SnuFOZhttt8g==",
"dependencies": {
"@sentry/hub": "6.3.5",
"@sentry/minimal": "6.3.5",
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"@sentry/hub": "6.3.6",
"@sentry/minimal": "6.3.6",
"@sentry/types": "6.3.6",
"@sentry/utils": "6.3.6",
"tslib": "^1.9.3"
},
"engines": {
@ -2498,19 +2433,19 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@sentry/types": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz",
"integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.6.tgz",
"integrity": "sha512-93cFJdJkWyCfyZeWFARSU11qnoHVOS/R2h5WIsEf+jbQmkqG2C+TXVz/19s6nHVsfDrwpvYpwALPv4/nrxfU7g==",
"engines": {
"node": ">=6"
}
},
"node_modules/@sentry/utils": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz",
"integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.6.tgz",
"integrity": "sha512-HnYlDBf8Dq8MEv7AulH7B6R1D/2LAooVclGdjg48tSrr9g+31kmtj+SAj2WWVHP9+bp29BWaC7i5nkfKrOibWw==",
"dependencies": {
"@sentry/types": "6.3.5",
"@sentry/types": "6.3.6",
"tslib": "^1.9.3"
},
"engines": {
@ -2668,12 +2603,12 @@
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.1.tgz",
"integrity": "sha512-kVTAghWDDhsvQ602tHBc6WmQkdaYbkcTwZu+7l24jtJiYvm9l+/y/b2BZANEezxPDiX5MK2ZecE+9BFi/YJryw==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.23.0.tgz",
"integrity": "sha512-tGK1y3KIvdsQEEgq6xNn1DjiFJtl+wn8JJQiETtCbdQxw1vzjXyAaIkEmO2l6Nq24iy3uZBMFQjZ6ECf1QdgGw==",
"dependencies": {
"@typescript-eslint/experimental-utils": "4.22.1",
"@typescript-eslint/scope-manager": "4.22.1",
"@typescript-eslint/experimental-utils": "4.23.0",
"@typescript-eslint/scope-manager": "4.23.0",
"debug": "^4.1.1",
"functional-red-black-tree": "^1.0.1",
"lodash": "^4.17.15",
@ -2699,14 +2634,14 @@
}
},
"node_modules/@typescript-eslint/experimental-utils": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.1.tgz",
"integrity": "sha512-svYlHecSMCQGDO2qN1v477ax/IDQwWhc7PRBiwAdAMJE7GXk5stF4Z9R/8wbRkuX/5e9dHqbIWxjeOjckK3wLQ==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.23.0.tgz",
"integrity": "sha512-WAFNiTDnQfrF3Z2fQ05nmCgPsO5o790vOhmWKXbbYQTO9erE1/YsFot5/LnOUizLzU2eeuz6+U/81KV5/hFTGA==",
"dependencies": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/scope-manager": "4.22.1",
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/typescript-estree": "4.22.1",
"@typescript-eslint/scope-manager": "4.23.0",
"@typescript-eslint/types": "4.23.0",
"@typescript-eslint/typescript-estree": "4.23.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
},
@ -2722,13 +2657,13 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.1.tgz",
"integrity": "sha512-l+sUJFInWhuMxA6rtirzjooh8cM/AATAe3amvIkqKFeMzkn85V+eLzb1RyuXkHak4dLfYzOmF6DXPyflJvjQnw==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.23.0.tgz",
"integrity": "sha512-wsvjksHBMOqySy/Pi2Q6UuIuHYbgAMwLczRl4YanEPKW5KVxI9ZzDYh3B5DtcZPQTGRWFJrfcbJ6L01Leybwug==",
"dependencies": {
"@typescript-eslint/scope-manager": "4.22.1",
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/typescript-estree": "4.22.1",
"@typescript-eslint/scope-manager": "4.23.0",
"@typescript-eslint/types": "4.23.0",
"@typescript-eslint/typescript-estree": "4.23.0",
"debug": "^4.1.1"
},
"engines": {
@ -2748,12 +2683,12 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.1.tgz",
"integrity": "sha512-d5bAiPBiessSmNi8Amq/RuLslvcumxLmyhf1/Xa9IuaoFJ0YtshlJKxhlbY7l2JdEk3wS0EnmnfeJWSvADOe0g==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.23.0.tgz",
"integrity": "sha512-ZZ21PCFxPhI3n0wuqEJK9omkw51wi2bmeKJvlRZPH5YFkcawKOuRMQMnI8mH6Vo0/DoHSeZJnHiIx84LmVQY+w==",
"dependencies": {
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/visitor-keys": "4.22.1"
"@typescript-eslint/types": "4.23.0",
"@typescript-eslint/visitor-keys": "4.23.0"
},
"engines": {
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
@ -2764,9 +2699,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.1.tgz",
"integrity": "sha512-2HTkbkdAeI3OOcWbqA8hWf/7z9c6gkmnWNGz0dKSLYLWywUlkOAQ2XcjhlKLj5xBFDf8FgAOF5aQbnLRvgNbCw==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.23.0.tgz",
"integrity": "sha512-oqkNWyG2SLS7uTWLZf6Sr7Dm02gA5yxiz1RP87tvsmDsguVATdpVguHr4HoGOcFOpCvx9vtCSCyQUGfzq28YCw==",
"engines": {
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
},
@ -2776,12 +2711,12 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.1.tgz",
"integrity": "sha512-p3We0pAPacT+onSGM+sPR+M9CblVqdA9F1JEdIqRVlxK5Qth4ochXQgIyb9daBomyQKAXbygxp1aXQRV0GC79A==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.23.0.tgz",
"integrity": "sha512-5Sty6zPEVZF5fbvrZczfmLCOcby3sfrSPu30qKoY1U3mca5/jvU5cwsPb/CO6Q3ByRjixTMIVsDkqwIxCf/dMw==",
"dependencies": {
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/visitor-keys": "4.22.1",
"@typescript-eslint/types": "4.23.0",
"@typescript-eslint/visitor-keys": "4.23.0",
"debug": "^4.1.1",
"globby": "^11.0.1",
"is-glob": "^4.0.1",
@ -2821,11 +2756,11 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.1.tgz",
"integrity": "sha512-WPkOrIRm+WCLZxXQHCi+WG8T2MMTUFR70rWjdWYddLT7cEfb2P4a3O/J2U1FBVsSFTocXLCoXWY6MZGejeStvQ==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.23.0.tgz",
"integrity": "sha512-5PNe5cmX9pSifit0H+nPoQBXdbNzi5tOEec+3riK+ku4e3er37pKxMKDH5Ct5Y4fhWxcD4spnlYjxi9vXbSpwg==",
"dependencies": {
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/types": "4.23.0",
"eslint-visitor-keys": "^2.0.0"
},
"engines": {
@ -2860,7 +2795,10 @@
"node_modules/acorn-jsx": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng=="
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
"peerDependencies": {
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/ajv": {
"version": "6.12.6",
@ -2871,6 +2809,10 @@
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ansi-colors": {
@ -3906,12 +3848,12 @@
}
},
"node_modules/eslint": {
"version": "7.25.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz",
"integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==",
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.26.0.tgz",
"integrity": "sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==",
"dependencies": {
"@babel/code-frame": "7.12.11",
"@eslint/eslintrc": "^0.4.0",
"@eslint/eslintrc": "^0.4.1",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@ -3953,6 +3895,9 @@
},
"engines": {
"node": "^10.12.0 || >=12.0.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint-config-google": {
@ -3972,13 +3917,16 @@
}
},
"node_modules/eslint-plugin-lit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.3.0.tgz",
"integrity": "sha512-fy6Lr5vYI3kvCYaDXA20lwyKAp1keS9UjR5ntj8U2TeV+1yUta3S7xxXe+rABKRPbcNzi1ZvQLE1LmNKc9yr4Q==",
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.4.0.tgz",
"integrity": "sha512-3PJCC1p4pvDBKtFmg1g2cGzAgJF4IDqhb9NJUh95nYc+QXExa/O/0fILF4WB6X7qdNQKm+gW6nYtSKTyYPHtXw==",
"dependencies": {
"parse5": "^6.0.1",
"parse5-htmlparser2-tree-adapter": "^6.0.1",
"requireindex": "^1.2.0"
},
"peerDependencies": {
"eslint": ">= 5"
}
},
"node_modules/eslint-rule-documentation": {
@ -7355,6 +7303,9 @@
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/supports-color": {
@ -9632,9 +9583,9 @@
}
},
"@eslint/eslintrc": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
"integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==",
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz",
"integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==",
"requires": {
"ajv": "^6.12.4",
"debug": "^4.1.1",
@ -10146,30 +10097,16 @@
}
},
"@sentry/browser": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.3.5.tgz",
"integrity": "sha512-fjkhPR5gLCGVWhbWjEoN64hnmTvfTLRCgWmYTc9SiGchWFoFEmLqZyF2uJFyt27+qamLQ9fN58nnv4Ly2yyxqg==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.3.6.tgz",
"integrity": "sha512-l4323jxuBOArki6Wf+EHes39IEyJ2Zj/CIUaTY7GWh7CntpfHQAfFmZWQw3Ozq+ka1u8lVp25RPhb4Wng3azNA==",
"requires": {
"@sentry/core": "6.3.5",
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"@sentry/core": "6.3.6",
"@sentry/types": "6.3.6",
"@sentry/utils": "6.3.6",
"tslib": "^1.9.3"
},
"dependencies": {
"@sentry/types": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz",
"integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ=="
},
"@sentry/utils": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz",
"integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==",
"requires": {
"@sentry/types": "6.3.5",
"tslib": "^1.9.3"
}
},
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
@ -10178,51 +10115,17 @@
}
},
"@sentry/core": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.3.5.tgz",
"integrity": "sha512-VR2ibDy33mryD0mT6d9fGhKjdNzS2FSwwZPe9GvmNOjkyjly/oV91BKVoYJneCqOeq8fyj2lvkJGKuupdJNDqg==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.3.6.tgz",
"integrity": "sha512-w6BRizAqh7BaiM9oeKzO6aACXwRijUPacYaVLX/OfhqCSueF9uDxpMRT7+4D/eCeDVqgJYhBJ4Vsu2NSstkk4A==",
"requires": {
"@sentry/hub": "6.3.5",
"@sentry/minimal": "6.3.5",
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"@sentry/hub": "6.3.6",
"@sentry/minimal": "6.3.6",
"@sentry/types": "6.3.6",
"@sentry/utils": "6.3.6",
"tslib": "^1.9.3"
},
"dependencies": {
"@sentry/hub": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.5.tgz",
"integrity": "sha512-ZYFo7VYKwdPVjuV9BDFiYn+MpANn6eZMz5QDBfZ2dugIvIVbuOyOOLx8PSa3ZXJoVTZZ7s2wD2fi/ZxKjNjZOQ==",
"requires": {
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"tslib": "^1.9.3"
}
},
"@sentry/minimal": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.5.tgz",
"integrity": "sha512-4RqIGAU0+8iI/1sw0GYPTr4SUA88/i2+JPjFJ+qloh5ANVaNwhFPRChw+Ys9xpre8LV9JZrEsEf8AvQr4fkNbA==",
"requires": {
"@sentry/hub": "6.3.5",
"@sentry/types": "6.3.5",
"tslib": "^1.9.3"
}
},
"@sentry/types": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz",
"integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ=="
},
"@sentry/utils": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz",
"integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==",
"requires": {
"@sentry/types": "6.3.5",
"tslib": "^1.9.3"
}
},
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
@ -10231,12 +10134,12 @@
}
},
"@sentry/hub": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.5.tgz",
"integrity": "sha512-ZYFo7VYKwdPVjuV9BDFiYn+MpANn6eZMz5QDBfZ2dugIvIVbuOyOOLx8PSa3ZXJoVTZZ7s2wD2fi/ZxKjNjZOQ==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.6.tgz",
"integrity": "sha512-foBZ3ilMnm9Gf9OolrAxYHK8jrA6IF72faDdJ3Al+1H27qcpnBaMdrdEp2/jzwu/dgmwuLmbBaMjEPXaGH/0JQ==",
"requires": {
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"@sentry/types": "6.3.6",
"@sentry/utils": "6.3.6",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10248,12 +10151,12 @@
}
},
"@sentry/minimal": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.5.tgz",
"integrity": "sha512-4RqIGAU0+8iI/1sw0GYPTr4SUA88/i2+JPjFJ+qloh5ANVaNwhFPRChw+Ys9xpre8LV9JZrEsEf8AvQr4fkNbA==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.6.tgz",
"integrity": "sha512-uM2/dH0a6zfvI5f+vg+/mST+uTBdN6Jgpm585ipH84ckCYQwIIDRg6daqsen4S1sy/xgg1P1YyC3zdEC4G6b1Q==",
"requires": {
"@sentry/hub": "6.3.5",
"@sentry/types": "6.3.5",
"@sentry/hub": "6.3.6",
"@sentry/types": "6.3.6",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10265,14 +10168,14 @@
}
},
"@sentry/tracing": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.3.5.tgz",
"integrity": "sha512-TNKAST1ge2g24BlTfVxNp4gP5t3drbi0OVCh8h8ah+J7UjHSfdiqhd9W2h5qv1GO61gGlpWeN/TyioyQmOxu0Q==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.3.6.tgz",
"integrity": "sha512-dfyYY2eESJGt5Qbigmfmb2U9ntqbwPhLNAOcjKaVg9WQRV5q2RkHCVctPoYk7TEAvfNeNRXCD8SnuFOZhttt8g==",
"requires": {
"@sentry/hub": "6.3.5",
"@sentry/minimal": "6.3.5",
"@sentry/types": "6.3.5",
"@sentry/utils": "6.3.5",
"@sentry/hub": "6.3.6",
"@sentry/minimal": "6.3.6",
"@sentry/types": "6.3.6",
"@sentry/utils": "6.3.6",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10284,16 +10187,16 @@
}
},
"@sentry/types": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz",
"integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ=="
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.6.tgz",
"integrity": "sha512-93cFJdJkWyCfyZeWFARSU11qnoHVOS/R2h5WIsEf+jbQmkqG2C+TXVz/19s6nHVsfDrwpvYpwALPv4/nrxfU7g=="
},
"@sentry/utils": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz",
"integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==",
"version": "6.3.6",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.6.tgz",
"integrity": "sha512-HnYlDBf8Dq8MEv7AulH7B6R1D/2LAooVclGdjg48tSrr9g+31kmtj+SAj2WWVHP9+bp29BWaC7i5nkfKrOibWw==",
"requires": {
"@sentry/types": "6.3.5",
"@sentry/types": "6.3.6",
"tslib": "^1.9.3"
},
"dependencies": {
@ -10450,12 +10353,12 @@
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
},
"@typescript-eslint/eslint-plugin": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.1.tgz",
"integrity": "sha512-kVTAghWDDhsvQ602tHBc6WmQkdaYbkcTwZu+7l24jtJiYvm9l+/y/b2BZANEezxPDiX5MK2ZecE+9BFi/YJryw==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.23.0.tgz",
"integrity": "sha512-tGK1y3KIvdsQEEgq6xNn1DjiFJtl+wn8JJQiETtCbdQxw1vzjXyAaIkEmO2l6Nq24iy3uZBMFQjZ6ECf1QdgGw==",
"requires": {
"@typescript-eslint/experimental-utils": "4.22.1",
"@typescript-eslint/scope-manager": "4.22.1",
"@typescript-eslint/experimental-utils": "4.23.0",
"@typescript-eslint/scope-manager": "4.23.0",
"debug": "^4.1.1",
"functional-red-black-tree": "^1.0.1",
"lodash": "^4.17.15",
@ -10465,50 +10368,50 @@
}
},
"@typescript-eslint/experimental-utils": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.1.tgz",
"integrity": "sha512-svYlHecSMCQGDO2qN1v477ax/IDQwWhc7PRBiwAdAMJE7GXk5stF4Z9R/8wbRkuX/5e9dHqbIWxjeOjckK3wLQ==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.23.0.tgz",
"integrity": "sha512-WAFNiTDnQfrF3Z2fQ05nmCgPsO5o790vOhmWKXbbYQTO9erE1/YsFot5/LnOUizLzU2eeuz6+U/81KV5/hFTGA==",
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/scope-manager": "4.22.1",
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/typescript-estree": "4.22.1",
"@typescript-eslint/scope-manager": "4.23.0",
"@typescript-eslint/types": "4.23.0",
"@typescript-eslint/typescript-estree": "4.23.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
}
},
"@typescript-eslint/parser": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.1.tgz",
"integrity": "sha512-l+sUJFInWhuMxA6rtirzjooh8cM/AATAe3amvIkqKFeMzkn85V+eLzb1RyuXkHak4dLfYzOmF6DXPyflJvjQnw==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.23.0.tgz",
"integrity": "sha512-wsvjksHBMOqySy/Pi2Q6UuIuHYbgAMwLczRl4YanEPKW5KVxI9ZzDYh3B5DtcZPQTGRWFJrfcbJ6L01Leybwug==",
"requires": {
"@typescript-eslint/scope-manager": "4.22.1",
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/typescript-estree": "4.22.1",
"@typescript-eslint/scope-manager": "4.23.0",
"@typescript-eslint/types": "4.23.0",
"@typescript-eslint/typescript-estree": "4.23.0",
"debug": "^4.1.1"
}
},
"@typescript-eslint/scope-manager": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.1.tgz",
"integrity": "sha512-d5bAiPBiessSmNi8Amq/RuLslvcumxLmyhf1/Xa9IuaoFJ0YtshlJKxhlbY7l2JdEk3wS0EnmnfeJWSvADOe0g==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.23.0.tgz",
"integrity": "sha512-ZZ21PCFxPhI3n0wuqEJK9omkw51wi2bmeKJvlRZPH5YFkcawKOuRMQMnI8mH6Vo0/DoHSeZJnHiIx84LmVQY+w==",
"requires": {
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/visitor-keys": "4.22.1"
"@typescript-eslint/types": "4.23.0",
"@typescript-eslint/visitor-keys": "4.23.0"
}
},
"@typescript-eslint/types": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.1.tgz",
"integrity": "sha512-2HTkbkdAeI3OOcWbqA8hWf/7z9c6gkmnWNGz0dKSLYLWywUlkOAQ2XcjhlKLj5xBFDf8FgAOF5aQbnLRvgNbCw=="
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.23.0.tgz",
"integrity": "sha512-oqkNWyG2SLS7uTWLZf6Sr7Dm02gA5yxiz1RP87tvsmDsguVATdpVguHr4HoGOcFOpCvx9vtCSCyQUGfzq28YCw=="
},
"@typescript-eslint/typescript-estree": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.1.tgz",
"integrity": "sha512-p3We0pAPacT+onSGM+sPR+M9CblVqdA9F1JEdIqRVlxK5Qth4ochXQgIyb9daBomyQKAXbygxp1aXQRV0GC79A==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.23.0.tgz",
"integrity": "sha512-5Sty6zPEVZF5fbvrZczfmLCOcby3sfrSPu30qKoY1U3mca5/jvU5cwsPb/CO6Q3ByRjixTMIVsDkqwIxCf/dMw==",
"requires": {
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/visitor-keys": "4.22.1",
"@typescript-eslint/types": "4.23.0",
"@typescript-eslint/visitor-keys": "4.23.0",
"debug": "^4.1.1",
"globby": "^11.0.1",
"is-glob": "^4.0.1",
@ -10532,11 +10435,11 @@
}
},
"@typescript-eslint/visitor-keys": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.1.tgz",
"integrity": "sha512-WPkOrIRm+WCLZxXQHCi+WG8T2MMTUFR70rWjdWYddLT7cEfb2P4a3O/J2U1FBVsSFTocXLCoXWY6MZGejeStvQ==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.23.0.tgz",
"integrity": "sha512-5PNe5cmX9pSifit0H+nPoQBXdbNzi5tOEec+3riK+ku4e3er37pKxMKDH5Ct5Y4fhWxcD4spnlYjxi9vXbSpwg==",
"requires": {
"@typescript-eslint/types": "4.22.1",
"@typescript-eslint/types": "4.23.0",
"eslint-visitor-keys": "^2.0.0"
}
},
@ -10558,7 +10461,8 @@
"acorn-jsx": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng=="
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
"requires": {}
},
"ajv": {
"version": "6.12.6",
@ -10685,8 +10589,7 @@
"typescript": {
"version": "3.9.9",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz",
"integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==",
"dev": true
"integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w=="
}
}
},
@ -11415,12 +11318,12 @@
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"eslint": {
"version": "7.25.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz",
"integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==",
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.26.0.tgz",
"integrity": "sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==",
"requires": {
"@babel/code-frame": "7.12.11",
"@eslint/eslintrc": "^0.4.0",
"@eslint/eslintrc": "^0.4.1",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@ -11535,9 +11438,9 @@
}
},
"eslint-plugin-lit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.3.0.tgz",
"integrity": "sha512-fy6Lr5vYI3kvCYaDXA20lwyKAp1keS9UjR5ntj8U2TeV+1yUta3S7xxXe+rABKRPbcNzi1ZvQLE1LmNKc9yr4Q==",
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.4.0.tgz",
"integrity": "sha512-3PJCC1p4pvDBKtFmg1g2cGzAgJF4IDqhb9NJUh95nYc+QXExa/O/0fILF4WB6X7qdNQKm+gW6nYtSKTyYPHtXw==",
"requires": {
"parse5": "^6.0.1",
"parse5-htmlparser2-tree-adapter": "^6.0.1",

View File

@ -50,13 +50,13 @@
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-replace": "^2.4.2",
"@rollup/plugin-typescript": "^8.2.1",
"@sentry/browser": "^6.3.5",
"@sentry/tracing": "^6.3.5",
"@sentry/browser": "^6.3.6",
"@sentry/tracing": "^6.3.6",
"@types/chart.js": "^2.9.32",
"@types/codemirror": "5.60.0",
"@types/grecaptcha": "^3.0.2",
"@typescript-eslint/eslint-plugin": "^4.22.1",
"@typescript-eslint/parser": "^4.22.1",
"@typescript-eslint/eslint-plugin": "^4.23.0",
"@typescript-eslint/parser": "^4.23.0",
"@webcomponents/webcomponentsjs": "^2.5.0",
"authentik-api": "file:api",
"babel-plugin-macros": "^3.1.0",
@ -65,10 +65,10 @@
"chartjs-adapter-moment": "^1.0.0",
"codemirror": "^5.61.0",
"construct-style-sheets-polyfill": "^2.4.16",
"eslint": "^7.25.0",
"eslint": "^7.26.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.2",
"eslint-plugin-lit": "^1.3.0",
"eslint-plugin-lit": "^1.4.0",
"flowchart.js": "^1.15.0",
"lit-element": "^2.5.1",
"lit-html": "^1.4.1",

View File

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

View File

@ -6,6 +6,7 @@ import { ArcElement, BarElement } from "chart.js";
import { TimeScale, LinearScale } from "chart.js";
import "chartjs-adapter-moment";
import { FONT_COLOUR_DARK_MODE, FONT_COLOUR_LIGHT_MODE } from "../../pages/flows/FlowDiagram";
import {EVENT_REFRESH} from "../../constants";
Chart.register(Legend, Tooltip);
Chart.register(LineController, BarController, DoughnutController);
@ -43,6 +44,13 @@ export abstract class AKChart<T> extends LitElement {
this.chart.resize();
}
});
window.addEventListener(EVENT_REFRESH, () => {
this.apiRequest().then((r: T) => {
if (!this.chart) return;
this.chart.data = this.getChartData(r);
this.chart.update();
});
});
const matcher = window.matchMedia("(prefers-color-scheme: light)");
const handler = (ev?: MediaQueryListEvent) => {
if (ev?.matches || matcher.matches) {
@ -56,6 +64,22 @@ export abstract class AKChart<T> extends LitElement {
handler();
}
firstUpdated(): void {
this.apiRequest().then((r) => {
const canvas = <HTMLCanvasElement>this.shadowRoot?.querySelector("canvas");
if (!canvas) {
console.warn("Failed to get canvas element");
return false;
}
const ctx = canvas.getContext("2d");
if (!ctx) {
console.warn("failed to get 2d context");
return false;
}
this.chart = this.configureChart(r, ctx);
});
}
getChartType(): string {
return "bar";
}
@ -129,23 +153,6 @@ export abstract class AKChart<T> extends LitElement {
return new Chart(ctx, config as ChartConfiguration);
}
firstUpdated(): void {
this.apiRequest().then((r) => {
const canvas = <HTMLCanvasElement>this.shadowRoot?.querySelector("canvas");
if (!canvas) {
console.warn("Failed to get canvas element");
return false;
}
const ctx = canvas.getContext("2d");
if (!ctx) {
console.warn("failed to get 2d context");
return false;
}
this.chart = this.configureChart(r, ctx);
});
}
render(): TemplateResult {
return html`
<div class="container">

View File

@ -102,18 +102,18 @@ export class OutpostForm extends Form<Outpost> {
</select>
<p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
</ak-form-element-horizontal>
${until(new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsDefaultSettings({}).then(config => {
let fc = config.config;
if (this.outpost) {
fc = this.outpost.config;
}
return html`<ak-form-element-horizontal
label=${t`Configuration`}
name="config">
<ak-codemirror mode="yaml" value="${YAML.stringify(fc)}"></ak-codemirror>
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
</ak-form-element-horizontal>`;
}))}
<ak-form-element-horizontal
label=${t`Configuration`}
name="config">
<ak-codemirror mode="yaml" value="${until(new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsDefaultSettings({}).then(config => {
let fc = config.config;
if (this.outpost) {
fc = this.outpost.config;
}
return YAML.stringify(fc);
}))}"></ak-codemirror>
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
</ak-form-element-horizontal>
</form>`;
}

View File

@ -17,10 +17,9 @@ import TabItem from '@theme/TabItem';
Add the following block to your `.env` file:
```shell
AUTHENTIK_IMAGE=docker.beryju.org/authentik/server
AUTHENTIK_IMAGE_STATIC=docker.beryju.org/authentik/static
AUTHENTIK_IMAGE=beryju.org/authentik/server
AUTHENTIK_TAG=gh-next
AUTHENTIK_OUTPOSTS__DOCKER_IMAGE_BASE=docker.beryju.org/authentik/outpost-%(type)s:gh-next
AUTHENTIK_OUTPOSTS__DOCKER_IMAGE_BASE=beryju.org/authentik/outpost-%(type)s:gh-next
```
Afterwards, run the upgrade commands from the latest releasae notes.
@ -30,9 +29,8 @@ Add the following block to your `values.yml` file:
```yaml
image:
name: docker.beryju.org/authentik/server
name_static: docker.beryju.org/authentik/static
name_outposts: docker.beryju.org/authentik/outpost-%(type)s:gh-next
name: beryju.org/authentik/server
name_outposts: beryju.org/authentik/outpost-%(type)s:gh-next
tag: gh-next
# pullPolicy: Always to ensure you always get the latest version
pullPolicy: Always

View File

@ -16,7 +16,7 @@ Download the latest `docker-compose.yml` from [here](https://raw.githubuserconte
To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env`
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.4.5 >> .env`
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.5.1-rc7 >> .env`
If this is a fresh authentik install run the following commands to generate a password:

View File

@ -22,9 +22,9 @@ See all configurable values on [artifacthub](https://artifacthub.io/packages/hel
Afterwards, run these commands to install authentik:
```
helm repo add authentik https://helm.goauthentik.io
helm repo add authentik https://charts.goauthentik.io
helm repo update
helm install authentik/authentik -f values.yaml
helm install authentik authentik/authentik -f values.yaml
```
This installation automatically applies database migrations on startup. After the installation is done, navigate to the `https://<ingress you've specified>/if/flow/initial-setup/`, to set a password for the akadmin user.

View File

@ -11,7 +11,7 @@ version: "3.5"
services:
authentik_proxy:
image: beryju/authentik-proxy:2021.4.5
image: beryju/authentik-proxy:2021.5.1-rc7
ports:
- 4180:4180
- 4443:4443

View File

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

View File

@ -72,7 +72,7 @@ The public port of the compose stack has been changed from 443 to 9000 and 9443
### Kubernetes
The helm chart has been rewritten by [@dirtycajunrice](https://github.com/dirtycajunrice) and now lives on `https://helm.goauthentik.io`.
The helm chart has been rewritten by [@dirtycajunrice](https://github.com/dirtycajunrice) and now lives on `https://charts.goauthentik.io`.
Please upgrade to the new chart using values from [ArtifactHub](https://artifacthub.io/packages/helm/goauthentik/authentik).

View File

@ -11,7 +11,7 @@
"@docusaurus/preset-classic": "2.0.0-alpha.75",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.1.1",
"postcss": "^8.2.14",
"postcss": "^8.2.15",
"rapidoc": "^9.0.0",
"react": "^17.0.2",
"react-before-after-slider": "^1.0.4",
@ -20,7 +20,7 @@
"react-toggle": "^4.1.2"
},
"devDependencies": {
"prettier": "2.2.1"
"prettier": "2.3.0"
}
},
"node_modules/@algolia/autocomplete-core": {
@ -8004,9 +8004,9 @@
"optional": true
},
"node_modules/nanoid": {
"version": "3.1.22",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
"integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==",
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@ -8823,12 +8823,12 @@
}
},
"node_modules/postcss": {
"version": "8.2.14",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.14.tgz",
"integrity": "sha512-+jD0ZijcvyCqPQo/m/CW0UcARpdFylq04of+Q7RKX6f/Tu+dvpUI/9Sp81+i6/vJThnOBX09Quw0ZLOVwpzX3w==",
"version": "8.2.15",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz",
"integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==",
"dependencies": {
"colorette": "^1.2.2",
"nanoid": "^3.1.22",
"nanoid": "^3.1.23",
"source-map": "^0.6.1"
},
"engines": {
@ -9306,9 +9306,9 @@
}
},
"node_modules/prettier": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
"integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz",
"integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
@ -20240,9 +20240,9 @@
"optional": true
},
"nanoid": {
"version": "3.1.22",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
"integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ=="
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw=="
},
"nanomatch": {
"version": "1.2.13",
@ -20895,12 +20895,12 @@
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
},
"postcss": {
"version": "8.2.14",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.14.tgz",
"integrity": "sha512-+jD0ZijcvyCqPQo/m/CW0UcARpdFylq04of+Q7RKX6f/Tu+dvpUI/9Sp81+i6/vJThnOBX09Quw0ZLOVwpzX3w==",
"version": "8.2.15",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz",
"integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==",
"requires": {
"colorette": "^1.2.2",
"nanoid": "^3.1.22",
"nanoid": "^3.1.23",
"source-map": "^0.6.1"
},
"dependencies": {
@ -21255,9 +21255,9 @@
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
},
"prettier": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
"integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz",
"integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==",
"dev": true
},
"pretty-error": {

View File

@ -14,7 +14,7 @@
"@docusaurus/preset-classic": "2.0.0-alpha.75",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.1.1",
"postcss": "^8.2.14",
"postcss": "^8.2.15",
"rapidoc": "^9.0.0",
"react": "^17.0.2",
"react-before-after-slider": "^1.0.4",
@ -35,6 +35,6 @@
]
},
"devDependencies": {
"prettier": "2.2.1"
"prettier": "2.3.0"
}
}

View File

@ -0,0 +1,102 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: authentik
namespace: ##NAMESPACE##
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: authentik
namespace: ##NAMESPACE##
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: authentik
subjects:
- kind: ServiceAccount
name: authentik
namespace: ##NAMESPACE##
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: authentik
namespace: ##NAMESPACE##
rules:
- apiGroups:
- ""
resources:
- secrets
- services
- configmaps
verbs:
- get
- create
- delete
- list
- patch
- apiGroups:
- extensions
- apps
resources:
- deployments
verbs:
- get
- create
- delete
- list
- patch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- create
- delete
- list
- patch
- apiGroups:
- traefik.containo.us
resources:
- middlewares
verbs:
- get
- create
- delete
- list
- patch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: authentik
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: authentik
subjects:
- kind: ServiceAccount
name: authentik
namespace: ingress
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: authentik
rules:
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- list