Merge branch 'main' into web/sidebar-with-live-content-3
* main: (47 commits) web: bump the wdio group in /tests/wdio with 2 updates (#7702) events: fix lint (#7700) events: add better fallback for sanitize_item to ensure everything can be saved as JSON (#7694) web: bump the wdio group in /tests/wdio with 4 updates (#7696) events: include user agent in events (#7693) web: fix labels on group view page (#7677) website/docs: Add OIDC auth integration with Nextcloud (#7406) web: fix locale (#7689) core: bump python from 3.11.5-bookworm to 3.12.0-bookworm (#7048) translate: Updates for file web/xliff/en.xlf in zh_TW (#7688) web: bump pyright from 1.1.336 to 1.1.337 in /web (#7681) core: bump sentry-sdk from 1.35.0 to 1.36.0 (#7683) website: bump prism-react-renderer from 2.2.0 to 2.3.0 in /website (#7685) web: bump the sentry group in /web with 2 updates (#7679) web: bump rollup from 4.5.0 to 4.5.1 in /web (#7680) web: bump @types/codemirror from 5.60.14 to 5.60.15 in /web (#7682) web: bump the wdio group in /tests/wdio with 2 updates (#7684) website: bump react-tooltip from 5.23.0 to 5.24.0 in /website (#7686) core: bump goauthentik.io/api/v3 from 3.2023103.4 to 3.2023104.1 (#7687) website/blog: Blog on security (#7671) ...
This commit is contained in:
commit
5b898bef01
|
@ -1,5 +1,5 @@
|
|||
[bumpversion]
|
||||
current_version = 2023.10.3
|
||||
current_version = 2023.10.4
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
|
||||
|
|
5
.github/actions/setup/action.yml
vendored
5
.github/actions/setup/action.yml
vendored
|
@ -2,7 +2,7 @@ name: "Setup authentik testing environment"
|
|||
description: "Setup authentik testing environment"
|
||||
|
||||
inputs:
|
||||
postgresql_tag:
|
||||
postgresql_version:
|
||||
description: "Optional postgresql image tag"
|
||||
default: "12"
|
||||
|
||||
|
@ -33,9 +33,8 @@ runs:
|
|||
- name: Setup dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
export PSQL_TAG=${{ inputs.postgresql_tag }}
|
||||
export PSQL_TAG=${{ inputs.postgresql_version }}
|
||||
docker-compose -f .github/actions/setup/docker-compose.yml up -d
|
||||
poetry env use python3.11
|
||||
poetry install
|
||||
cd web && npm ci
|
||||
- name: Generate config
|
||||
|
|
25
.github/workflows/ci-main.yml
vendored
25
.github/workflows/ci-main.yml
vendored
|
@ -48,25 +48,38 @@ jobs:
|
|||
- name: run migrations
|
||||
run: poetry run python -m lifecycle.migrate
|
||||
test-migrations-from-stable:
|
||||
name: test-migrations-from-stable - PostgreSQL ${{ matrix.psql }}
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
psql:
|
||||
- 12-alpine
|
||||
- 15-alpine
|
||||
- 16-alpine
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
postgresql_version: ${{ matrix.psql }}
|
||||
- name: checkout stable
|
||||
run: |
|
||||
# Delete all poetry envs
|
||||
rm -rf /home/runner/.cache/pypoetry
|
||||
# Copy current, latest config to local
|
||||
cp authentik/lib/default.yml local.env.yml
|
||||
cp -R .github ..
|
||||
cp -R scripts ..
|
||||
git checkout $(git describe --tags $(git rev-list --tags --max-count=1))
|
||||
git checkout version/$(python -c "from authentik import __version__; print(__version__)")
|
||||
rm -rf .github/ scripts/
|
||||
mv ../.github ../scripts .
|
||||
- name: Setup authentik env (ensure stable deps are installed)
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
postgresql_version: ${{ matrix.psql }}
|
||||
- name: run migrations to stable
|
||||
run: poetry run python -m lifecycle.migrate
|
||||
- name: checkout current code
|
||||
|
@ -76,9 +89,13 @@ jobs:
|
|||
git reset --hard HEAD
|
||||
git clean -d -fx .
|
||||
git checkout $GITHUB_SHA
|
||||
# Delete previous poetry env
|
||||
rm -rf $(poetry env info --path)
|
||||
poetry install
|
||||
- name: Setup authentik env (ensure latest deps are installed)
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
postgresql_version: ${{ matrix.psql }}
|
||||
- name: migrate to latest
|
||||
run: poetry run python -m lifecycle.migrate
|
||||
test-unittest:
|
||||
|
@ -97,7 +114,7 @@ jobs:
|
|||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
postgresql_tag: ${{ matrix.psql }}
|
||||
postgresql_version: ${{ matrix.psql }}
|
||||
- name: run unittest
|
||||
run: |
|
||||
poetry run make test
|
||||
|
@ -117,7 +134,7 @@ jobs:
|
|||
uses: helm/kind-action@v1.8.0
|
||||
- name: run integration
|
||||
run: |
|
||||
poetry run coverage run manage.py test --randomly-seed=2100196988 tests/integration
|
||||
poetry run coverage run manage.py test tests/integration
|
||||
poetry run coverage xml
|
||||
- if: ${{ always() }}
|
||||
uses: codecov/codecov-action@v3
|
||||
|
|
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
|
@ -14,6 +14,7 @@
|
|||
"ms-python.pylint",
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"ms-python.black-formatter",
|
||||
"redhat.vscode-yaml",
|
||||
"Tobermory.es6-string-html",
|
||||
"unifiedjs.vscode-mdx",
|
||||
|
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -19,10 +19,8 @@
|
|||
"slo",
|
||||
"scim",
|
||||
],
|
||||
"python.linting.pylintEnabled": true,
|
||||
"todo-tree.tree.showCountsInTree": true,
|
||||
"todo-tree.tree.showBadges": true,
|
||||
"python.formatting.provider": "black",
|
||||
"yaml.customTags": [
|
||||
"!Find sequence",
|
||||
"!KeyOf scalar",
|
||||
|
|
|
@ -81,7 +81,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
|
|||
/bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
|
||||
|
||||
# Stage 5: Python dependencies
|
||||
FROM docker.io/python:3.11.5-bookworm AS python-deps
|
||||
FROM docker.io/python:3.12.0-slim-bookworm AS python-deps
|
||||
|
||||
WORKDIR /ak-root/poetry
|
||||
|
||||
|
@ -104,7 +104,7 @@ RUN --mount=type=bind,target=./pyproject.toml,src=./pyproject.toml \
|
|||
poetry install --only=main --no-ansi --no-interaction
|
||||
|
||||
# Stage 6: Run
|
||||
FROM docker.io/python:3.11.5-slim-bookworm AS final-image
|
||||
FROM docker.io/python:3.12.0-slim-bookworm AS final-image
|
||||
|
||||
ARG GIT_BUILD_HASH
|
||||
ARG VERSION
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from os import environ
|
||||
from typing import Optional
|
||||
|
||||
__version__ = "2023.10.3"
|
||||
__version__ = "2023.10.4"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
||||
|
||||
|
|
|
@ -517,7 +517,7 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
|
|||
objects = InheritanceManager()
|
||||
|
||||
@property
|
||||
def get_icon(self) -> Optional[str]:
|
||||
def icon_url(self) -> Optional[str]:
|
||||
"""Get the URL to the Icon. If the name is /static or
|
||||
starts with http it is returned as-is"""
|
||||
if not self.icon:
|
||||
|
|
|
@ -217,6 +217,7 @@ class Event(SerializerModel, ExpiringModel):
|
|||
"path": request.path,
|
||||
"method": request.method,
|
||||
"args": cleanse_dict(QueryDict(request.META.get("QUERY_STRING", ""))),
|
||||
"user_agent": request.META.get("HTTP_USER_AGENT", ""),
|
||||
}
|
||||
# Special case for events created during flow execution
|
||||
# since they keep the http query within a wrapped query
|
||||
|
|
|
@ -53,7 +53,15 @@ class TestEvents(TestCase):
|
|||
"""Test plain from_http"""
|
||||
event = Event.new("unittest").from_http(self.factory.get("/"))
|
||||
self.assertEqual(
|
||||
event.context, {"http_request": {"args": {}, "method": "GET", "path": "/"}}
|
||||
event.context,
|
||||
{
|
||||
"http_request": {
|
||||
"args": {},
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"user_agent": "",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
def test_from_http_clean_querystring(self):
|
||||
|
@ -67,6 +75,7 @@ class TestEvents(TestCase):
|
|||
"args": {"token": SafeExceptionReporterFilter.cleansed_substitute},
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"user_agent": "",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -83,6 +92,7 @@ class TestEvents(TestCase):
|
|||
"args": {"token": SafeExceptionReporterFilter.cleansed_substitute},
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"user_agent": "",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
@ -5,12 +5,13 @@ from dataclasses import asdict, is_dataclass
|
|||
from datetime import date, datetime, time, timedelta
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from types import GeneratorType
|
||||
from types import GeneratorType, NoneType
|
||||
from typing import Any, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.db import models
|
||||
from django.db.models.base import Model
|
||||
from django.http.request import HttpRequest
|
||||
|
@ -159,7 +160,14 @@ def sanitize_item(value: Any) -> Any:
|
|||
"name": value.__name__,
|
||||
"module": value.__module__,
|
||||
}
|
||||
return value
|
||||
# List taken from the stdlib's JSON encoder (_make_iterencode, encoder.py:415)
|
||||
if isinstance(value, (bool, int, float, NoneType, list, tuple, dict)):
|
||||
return value
|
||||
try:
|
||||
return DjangoJSONEncoder().default(value)
|
||||
except TypeError:
|
||||
return str(value)
|
||||
return str(value)
|
||||
|
||||
|
||||
def sanitize_dict(source: dict[Any, Any]) -> dict[Any, Any]:
|
||||
|
|
187
authentik/providers/oauth2/tests/test_token_pkce.py
Normal file
187
authentik/providers/oauth2/tests/test_token_pkce.py
Normal file
|
@ -0,0 +1,187 @@
|
|||
"""Test token view"""
|
||||
from base64 import b64encode, urlsafe_b64encode
|
||||
from hashlib import sha256
|
||||
|
||||
from django.test import RequestFactory
|
||||
from django.urls import reverse
|
||||
|
||||
from authentik.core.models import Application
|
||||
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
|
||||
from authentik.flows.challenge import ChallengeTypes
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.providers.oauth2.constants import GRANT_TYPE_AUTHORIZATION_CODE
|
||||
from authentik.providers.oauth2.models import AuthorizationCode, OAuth2Provider
|
||||
from authentik.providers.oauth2.tests.utils import OAuthTestCase
|
||||
|
||||
|
||||
class TestTokenPKCE(OAuthTestCase):
|
||||
"""Test token view"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
self.factory = RequestFactory()
|
||||
self.app = Application.objects.create(name=generate_id(), slug="test")
|
||||
|
||||
def test_pkce_missing_in_token(self):
|
||||
"""Test full with pkce"""
|
||||
flow = create_test_flow()
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name=generate_id(),
|
||||
client_id="test",
|
||||
authorization_flow=flow,
|
||||
redirect_uris="foo://localhost",
|
||||
access_code_validity="seconds=100",
|
||||
)
|
||||
Application.objects.create(name="app", slug="app", provider=provider)
|
||||
state = generate_id()
|
||||
user = create_test_admin_user()
|
||||
self.client.force_login(user)
|
||||
challenge = generate_id()
|
||||
header = b64encode(f"{provider.client_id}:{provider.client_secret}".encode()).decode()
|
||||
# Step 1, initiate params and get redirect to flow
|
||||
self.client.get(
|
||||
reverse("authentik_providers_oauth2:authorize"),
|
||||
data={
|
||||
"response_type": "code",
|
||||
"client_id": "test",
|
||||
"state": state,
|
||||
"redirect_uri": "foo://localhost",
|
||||
"code_challenge": challenge,
|
||||
"code_challenge_method": "S256",
|
||||
},
|
||||
)
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
)
|
||||
code: AuthorizationCode = AuthorizationCode.objects.filter(user=user).first()
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{
|
||||
"component": "xak-flow-redirect",
|
||||
"type": ChallengeTypes.REDIRECT.value,
|
||||
"to": f"foo://localhost?code={code.code}&state={state}",
|
||||
},
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"grant_type": GRANT_TYPE_AUTHORIZATION_CODE,
|
||||
"code": code.code,
|
||||
# Missing the code_verifier here
|
||||
"redirect_uri": "foo://localhost",
|
||||
},
|
||||
HTTP_AUTHORIZATION=f"Basic {header}",
|
||||
)
|
||||
self.assertJSONEqual(
|
||||
response.content,
|
||||
{"error": "invalid_request", "error_description": "The request is otherwise malformed"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_pkce_correct_s256(self):
|
||||
"""Test full with pkce"""
|
||||
flow = create_test_flow()
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name=generate_id(),
|
||||
client_id="test",
|
||||
authorization_flow=flow,
|
||||
redirect_uris="foo://localhost",
|
||||
access_code_validity="seconds=100",
|
||||
)
|
||||
Application.objects.create(name="app", slug="app", provider=provider)
|
||||
state = generate_id()
|
||||
user = create_test_admin_user()
|
||||
self.client.force_login(user)
|
||||
verifier = generate_id()
|
||||
challenge = (
|
||||
urlsafe_b64encode(sha256(verifier.encode("ascii")).digest())
|
||||
.decode("utf-8")
|
||||
.replace("=", "")
|
||||
)
|
||||
header = b64encode(f"{provider.client_id}:{provider.client_secret}".encode()).decode()
|
||||
# Step 1, initiate params and get redirect to flow
|
||||
self.client.get(
|
||||
reverse("authentik_providers_oauth2:authorize"),
|
||||
data={
|
||||
"response_type": "code",
|
||||
"client_id": "test",
|
||||
"state": state,
|
||||
"redirect_uri": "foo://localhost",
|
||||
"code_challenge": challenge,
|
||||
"code_challenge_method": "S256",
|
||||
},
|
||||
)
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
)
|
||||
code: AuthorizationCode = AuthorizationCode.objects.filter(user=user).first()
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{
|
||||
"component": "xak-flow-redirect",
|
||||
"type": ChallengeTypes.REDIRECT.value,
|
||||
"to": f"foo://localhost?code={code.code}&state={state}",
|
||||
},
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"grant_type": GRANT_TYPE_AUTHORIZATION_CODE,
|
||||
"code": code.code,
|
||||
"code_verifier": verifier,
|
||||
"redirect_uri": "foo://localhost",
|
||||
},
|
||||
HTTP_AUTHORIZATION=f"Basic {header}",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_pkce_correct_plain(self):
|
||||
"""Test full with pkce"""
|
||||
flow = create_test_flow()
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name=generate_id(),
|
||||
client_id="test",
|
||||
authorization_flow=flow,
|
||||
redirect_uris="foo://localhost",
|
||||
access_code_validity="seconds=100",
|
||||
)
|
||||
Application.objects.create(name="app", slug="app", provider=provider)
|
||||
state = generate_id()
|
||||
user = create_test_admin_user()
|
||||
self.client.force_login(user)
|
||||
verifier = generate_id()
|
||||
header = b64encode(f"{provider.client_id}:{provider.client_secret}".encode()).decode()
|
||||
# Step 1, initiate params and get redirect to flow
|
||||
self.client.get(
|
||||
reverse("authentik_providers_oauth2:authorize"),
|
||||
data={
|
||||
"response_type": "code",
|
||||
"client_id": "test",
|
||||
"state": state,
|
||||
"redirect_uri": "foo://localhost",
|
||||
"code_challenge": verifier,
|
||||
},
|
||||
)
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
)
|
||||
code: AuthorizationCode = AuthorizationCode.objects.filter(user=user).first()
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{
|
||||
"component": "xak-flow-redirect",
|
||||
"type": ChallengeTypes.REDIRECT.value,
|
||||
"to": f"foo://localhost?code={code.code}&state={state}",
|
||||
},
|
||||
)
|
||||
response = self.client.post(
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"grant_type": GRANT_TYPE_AUTHORIZATION_CODE,
|
||||
"code": code.code,
|
||||
"code_verifier": verifier,
|
||||
"redirect_uri": "foo://localhost",
|
||||
},
|
||||
HTTP_AUTHORIZATION=f"Basic {header}",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
|
@ -222,7 +222,10 @@ class TokenParams:
|
|||
raise TokenError("invalid_grant")
|
||||
|
||||
# Validate PKCE parameters.
|
||||
if self.code_verifier:
|
||||
if self.authorization_code.code_challenge:
|
||||
# Authorization code had PKCE but we didn't get one
|
||||
if not self.code_verifier:
|
||||
raise TokenError("invalid_request")
|
||||
if self.authorization_code.code_challenge_method == PKCE_METHOD_S256:
|
||||
new_code_challenge = (
|
||||
urlsafe_b64encode(sha256(self.code_verifier.encode("ascii")).digest())
|
||||
|
|
|
@ -411,7 +411,7 @@ if DEBUG:
|
|||
CELERY["task_always_eager"] = True
|
||||
os.environ[ENV_GIT_HASH_KEY] = "dev"
|
||||
INSTALLED_APPS.append("silk")
|
||||
SILKY_PYTHON_PROFILER = True
|
||||
SILKY_PYTHON_PROFILER = False
|
||||
MIDDLEWARE = ["silk.middleware.SilkyMiddleware"] + MIDDLEWARE
|
||||
REST_FRAMEWORK["DEFAULT_RENDERER_CLASSES"].append(
|
||||
"rest_framework.renderers.BrowsableAPIRenderer"
|
||||
|
|
|
@ -74,7 +74,7 @@ class OAuthSource(Source):
|
|||
def ui_login_button(self, request: HttpRequest) -> UILoginButton:
|
||||
provider_type = self.source_type
|
||||
provider = provider_type()
|
||||
icon = self.get_icon
|
||||
icon = self.icon_url
|
||||
if not icon:
|
||||
icon = provider.icon_url()
|
||||
return UILoginButton(
|
||||
|
@ -85,7 +85,7 @@ class OAuthSource(Source):
|
|||
|
||||
def ui_user_settings(self) -> Optional[UserSettingSerializer]:
|
||||
provider_type = self.source_type
|
||||
icon = self.get_icon
|
||||
icon = self.icon_url
|
||||
if not icon:
|
||||
icon = provider_type().icon_url()
|
||||
return UserSettingSerializer(
|
||||
|
@ -232,7 +232,7 @@ class UserOAuthSourceConnection(UserSourceConnection):
|
|||
access_token = models.TextField(blank=True, null=True, default=None)
|
||||
|
||||
@property
|
||||
def serializer(self) -> Serializer:
|
||||
def serializer(self) -> type[Serializer]:
|
||||
from authentik.sources.oauth.api.source_connection import (
|
||||
UserOAuthSourceConnectionSerializer,
|
||||
)
|
||||
|
|
|
@ -62,7 +62,7 @@ class PlexSource(Source):
|
|||
return PlexSourceSerializer
|
||||
|
||||
def ui_login_button(self, request: HttpRequest) -> UILoginButton:
|
||||
icon = self.get_icon
|
||||
icon = self.icon_url
|
||||
if not icon:
|
||||
icon = static("authentik/sources/plex.svg")
|
||||
return UILoginButton(
|
||||
|
@ -79,7 +79,7 @@ class PlexSource(Source):
|
|||
)
|
||||
|
||||
def ui_user_settings(self) -> Optional[UserSettingSerializer]:
|
||||
icon = self.get_icon
|
||||
icon = self.icon_url
|
||||
if not icon:
|
||||
icon = static("authentik/sources/plex.svg")
|
||||
return UserSettingSerializer(
|
||||
|
|
|
@ -200,11 +200,11 @@ class SAMLSource(Source):
|
|||
}
|
||||
),
|
||||
name=self.name,
|
||||
icon_url=self.get_icon,
|
||||
icon_url=self.icon_url,
|
||||
)
|
||||
|
||||
def ui_user_settings(self) -> Optional[UserSettingSerializer]:
|
||||
icon = self.get_icon
|
||||
icon = self.icon_url
|
||||
if not icon:
|
||||
icon = static(f"authentik/sources/{self.slug}.svg")
|
||||
return UserSettingSerializer(
|
||||
|
|
|
@ -69,7 +69,6 @@ class AuthenticatorSMSStageView(ChallengeStageView):
|
|||
stage: AuthenticatorSMSStage = self.executor.current_stage
|
||||
hashed_number = hash_phone_number(phone_number)
|
||||
query = Q(phone_number=hashed_number) | Q(phone_number=phone_number)
|
||||
print(SMSDevice.objects.filter(query, stage=stage.pk))
|
||||
if SMSDevice.objects.filter(query, stage=stage.pk).exists():
|
||||
raise ValidationError(_("Invalid phone number"))
|
||||
# No code yet, but we have a phone number, so send a verification message
|
||||
|
|
|
@ -199,11 +199,9 @@ class AuthenticatorSMSStageTests(FlowTestCase):
|
|||
sms_send_mock,
|
||||
),
|
||||
):
|
||||
print(self.client.session[SESSION_KEY_PLAN])
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
)
|
||||
print(response.content.decode())
|
||||
self.assertStageResponse(
|
||||
response,
|
||||
self.flow,
|
||||
|
|
|
@ -184,6 +184,7 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase):
|
|||
"args": {},
|
||||
"method": "GET",
|
||||
"path": f"/api/v3/flows/executor/{flow.slug}/",
|
||||
"user_agent": "",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
|
@ -59,7 +59,6 @@ class EmailStageView(ChallengeStageView):
|
|||
query_params = QueryDict(self.request.GET.get(QS_QUERY), mutable=True)
|
||||
query_params.pop(QS_KEY_TOKEN, None)
|
||||
query_params.update(kwargs)
|
||||
print(query_params)
|
||||
full_url = base_url
|
||||
if len(query_params) > 0:
|
||||
full_url = f"{full_url}?{query_params.urlencode()}"
|
||||
|
|
|
@ -32,7 +32,7 @@ services:
|
|||
volumes:
|
||||
- redis:/data
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.3}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.4}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
|
@ -53,7 +53,7 @@ services:
|
|||
- postgresql
|
||||
- redis
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.3}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.4}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
|
|
2
go.mod
2
go.mod
|
@ -27,7 +27,7 @@ require (
|
|||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
goauthentik.io/api/v3 v3.2023103.4
|
||||
goauthentik.io/api/v3 v3.2023104.1
|
||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
|
||||
golang.org/x/oauth2 v0.14.0
|
||||
golang.org/x/sync v0.5.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -358,8 +358,8 @@ go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyK
|
|||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
goauthentik.io/api/v3 v3.2023103.4 h1:dysNzRSbZC2NYeIyk3x5o3kUSsz+Y2VhtfcnzRe8Wkk=
|
||||
goauthentik.io/api/v3 v3.2023103.4/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
||||
goauthentik.io/api/v3 v3.2023104.1 h1:cvAsgoKP/fmO4fzifx0OyICknauFeyN88C4Z1LdWXDs=
|
||||
goauthentik.io/api/v3 v3.2023104.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
|
|
|
@ -29,4 +29,4 @@ func UserAgent() string {
|
|||
return fmt.Sprintf("authentik@%s", FullVersion())
|
||||
}
|
||||
|
||||
const VERSION = "2023.10.3"
|
||||
const VERSION = "2023.10.4"
|
||||
|
|
1722
poetry.lock
generated
1722
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,7 @@ reportOptionalSubscript = false
|
|||
# so we have to disable those for now
|
||||
reportGeneralTypeIssues = false
|
||||
verboseOutput = false
|
||||
pythonVersion = "3.11"
|
||||
pythonVersion = "3.12"
|
||||
pythonPlatform = "All"
|
||||
|
||||
[tool.black]
|
||||
|
@ -97,7 +97,7 @@ const-rgx = "[a-zA-Z0-9_]{1,40}$"
|
|||
|
||||
ignored-modules = ["binascii", "socket", "zlib"]
|
||||
generated-members = ["xmlsec.constants.*", "xmlsec.tree.*", "xmlsec.template.*"]
|
||||
ignore = "migrations"
|
||||
ignore = ["migrations", "tests"]
|
||||
max-attributes = 12
|
||||
max-branches = 20
|
||||
|
||||
|
@ -113,7 +113,7 @@ filterwarnings = [
|
|||
|
||||
[tool.poetry]
|
||||
name = "authentik"
|
||||
version = "2023.10.3"
|
||||
version = "2023.10.4"
|
||||
description = ""
|
||||
authors = ["authentik Team <hello@goauthentik.io>"]
|
||||
|
||||
|
@ -154,7 +154,7 @@ pycryptodome = "*"
|
|||
pydantic = "*"
|
||||
pydantic-scim = "*"
|
||||
pyjwt = "*"
|
||||
python = "~3.11"
|
||||
python = "~3.12"
|
||||
pyyaml = "*"
|
||||
requests-oauthlib = "*"
|
||||
sentry-sdk = "*"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
openapi: 3.0.3
|
||||
info:
|
||||
title: authentik
|
||||
version: 2023.10.3
|
||||
version: 2023.10.4
|
||||
description: Making authentication simple.
|
||||
contact:
|
||||
email: hello@goauthentik.io
|
||||
|
|
|
@ -36,8 +36,8 @@ class TestProviderOAuth2Github(SeleniumTestCase):
|
|||
"auto_remove": True,
|
||||
"healthcheck": Healthcheck(
|
||||
test=["CMD", "wget", "--spider", "http://localhost:3000"],
|
||||
interval=5 * 100 * 1000000,
|
||||
start_period=1 * 100 * 1000000,
|
||||
interval=5 * 1_000 * 1_000_000,
|
||||
start_period=1 * 1_000 * 1_000_000,
|
||||
),
|
||||
"environment": {
|
||||
"GF_AUTH_GITHUB_ENABLED": "true",
|
||||
|
|
|
@ -42,8 +42,8 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
|
|||
"auto_remove": True,
|
||||
"healthcheck": Healthcheck(
|
||||
test=["CMD", "wget", "--spider", "http://localhost:3000"],
|
||||
interval=5 * 100 * 1000000,
|
||||
start_period=1 * 100 * 1000000,
|
||||
interval=5 * 1_000 * 1_000_000,
|
||||
start_period=1 * 1_000 * 1_000_000,
|
||||
),
|
||||
"environment": {
|
||||
"GF_AUTH_GENERIC_OAUTH_ENABLED": "true",
|
||||
|
|
|
@ -113,8 +113,8 @@ class TestSourceOAuth2(SeleniumTestCase):
|
|||
"command": "dex serve /config.yml",
|
||||
"healthcheck": Healthcheck(
|
||||
test=["CMD", "wget", "--spider", "http://localhost:5556/dex/healthz"],
|
||||
interval=5 * 100 * 1000000,
|
||||
start_period=1 * 100 * 1000000,
|
||||
interval=5 * 1_000 * 1_000_000,
|
||||
start_period=1 * 1_000 * 1_000_000,
|
||||
),
|
||||
"volumes": {str(Path(CONFIG_PATH).absolute()): {"bind": "/config.yml", "mode": "ro"}},
|
||||
}
|
||||
|
|
|
@ -83,8 +83,8 @@ class TestSourceSAML(SeleniumTestCase):
|
|||
"auto_remove": True,
|
||||
"healthcheck": Healthcheck(
|
||||
test=["CMD", "curl", "http://localhost:8080"],
|
||||
interval=5 * 100 * 1000000,
|
||||
start_period=1 * 100 * 1000000,
|
||||
interval=5 * 1_000 * 1_000_000,
|
||||
start_period=1 * 1_000 * 1_000_000,
|
||||
),
|
||||
"environment": {
|
||||
"SIMPLESAMLPHP_SP_ENTITY_ID": "entity-id",
|
||||
|
|
|
@ -35,8 +35,8 @@ class OutpostDockerTests(DockerTestCase, ChannelsLiveServerTestCase):
|
|||
privileged=True,
|
||||
healthcheck=Healthcheck(
|
||||
test=["CMD", "docker", "info"],
|
||||
interval=5 * 100 * 1000000,
|
||||
start_period=5 * 100 * 1000000,
|
||||
interval=5 * 1_000 * 1_000_000,
|
||||
start_period=5 * 1_000 * 1_000_000,
|
||||
),
|
||||
environment={"DOCKER_TLS_CERTDIR": "/ssl"},
|
||||
volumes={
|
||||
|
|
|
@ -35,8 +35,8 @@ class TestProxyDocker(DockerTestCase, ChannelsLiveServerTestCase):
|
|||
privileged=True,
|
||||
healthcheck=Healthcheck(
|
||||
test=["CMD", "docker", "info"],
|
||||
interval=5 * 100 * 1000000,
|
||||
start_period=5 * 100 * 1000000,
|
||||
interval=5 * 1_000 * 1_000_000,
|
||||
start_period=5 * 1_000 * 1_000_000,
|
||||
),
|
||||
environment={"DOCKER_TLS_CERTDIR": "/ssl"},
|
||||
volumes={
|
||||
|
|
295
tests/wdio/package-lock.json
generated
295
tests/wdio/package-lock.json
generated
|
@ -7,20 +7,20 @@
|
|||
"name": "@goauthentik/web-tests",
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"@wdio/cli": "^8.23.1",
|
||||
"@wdio/local-runner": "^8.23.1",
|
||||
"@wdio/mocha-framework": "^8.23.1",
|
||||
"@wdio/spec-reporter": "^8.23.1",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.12.0",
|
||||
"@wdio/cli": "^8.24.1",
|
||||
"@wdio/local-runner": "^8.24.1",
|
||||
"@wdio/mocha-framework": "^8.24.0",
|
||||
"@wdio/spec-reporter": "^8.24.0",
|
||||
"eslint": "^8.54.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-sonarjs": "^0.23.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2",
|
||||
"wdio-wait-for": "^3.0.8"
|
||||
"typescript": "^5.3.2",
|
||||
"wdio-wait-for": "^3.0.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
|
@ -652,10 +652,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@ljharb/through": {
|
||||
"version": "2.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.9.tgz",
|
||||
"integrity": "sha512-yN599ZBuMPPK4tdoToLlvgJB4CLK8fGl7ntfy0Wn7U6ttNvHYurd81bfUiK/6sMkiIwm65R6ck4L6+Y3DfVbNQ==",
|
||||
"version": "2.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.11.tgz",
|
||||
"integrity": "sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
|
@ -891,9 +894,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz",
|
||||
"integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==",
|
||||
"version": "7.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz",
|
||||
"integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/stack-utils": {
|
||||
|
@ -943,16 +946,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.11.0.tgz",
|
||||
"integrity": "sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz",
|
||||
"integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.5.1",
|
||||
"@typescript-eslint/scope-manager": "6.11.0",
|
||||
"@typescript-eslint/type-utils": "6.11.0",
|
||||
"@typescript-eslint/utils": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0",
|
||||
"@typescript-eslint/scope-manager": "6.12.0",
|
||||
"@typescript-eslint/type-utils": "6.12.0",
|
||||
"@typescript-eslint/utils": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0",
|
||||
"debug": "^4.3.4",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.2.4",
|
||||
|
@ -978,15 +981,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.11.0.tgz",
|
||||
"integrity": "sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz",
|
||||
"integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "6.11.0",
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/typescript-estree": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0",
|
||||
"@typescript-eslint/scope-manager": "6.12.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/typescript-estree": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1006,13 +1009,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz",
|
||||
"integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz",
|
||||
"integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0"
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
|
@ -1023,13 +1026,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.11.0.tgz",
|
||||
"integrity": "sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz",
|
||||
"integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "6.11.0",
|
||||
"@typescript-eslint/utils": "6.11.0",
|
||||
"@typescript-eslint/typescript-estree": "6.12.0",
|
||||
"@typescript-eslint/utils": "6.12.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
|
@ -1050,9 +1053,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz",
|
||||
"integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz",
|
||||
"integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
|
@ -1063,13 +1066,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz",
|
||||
"integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz",
|
||||
"integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
|
@ -1090,17 +1093,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz",
|
||||
"integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz",
|
||||
"integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@types/json-schema": "^7.0.12",
|
||||
"@types/semver": "^7.5.0",
|
||||
"@typescript-eslint/scope-manager": "6.11.0",
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/typescript-estree": "6.11.0",
|
||||
"@typescript-eslint/scope-manager": "6.12.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/typescript-estree": "6.12.0",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1115,12 +1118,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz",
|
||||
"integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz",
|
||||
"integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1138,18 +1141,18 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@wdio/cli": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.23.1.tgz",
|
||||
"integrity": "sha512-So8gl6iEoFtChJaOhE0vl0nJVoate1JfmGeMTLoKaeDf1PzSD9fj1Xvyp83elSjnSLV+QbJ07ew8c8+JEcsHRg==",
|
||||
"version": "8.24.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.24.1.tgz",
|
||||
"integrity": "sha512-3NB5LwPN5f1C8LPumlOHFfoCFfE7OmM0h7vN0/gzjcIlCXMrJ9igePyDQ6Af7u/jqfPk3SloBsG9DnxZBCcAxQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.1",
|
||||
"@wdio/config": "8.23.1",
|
||||
"@wdio/globals": "8.23.1",
|
||||
"@wdio/config": "8.24.0",
|
||||
"@wdio/globals": "8.24.1",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/protocols": "8.23.0",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/utils": "8.23.1",
|
||||
"@wdio/types": "8.24.0",
|
||||
"@wdio/utils": "8.24.0",
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"chalk": "^5.2.0",
|
||||
"chokidar": "^3.5.3",
|
||||
|
@ -1159,13 +1162,13 @@
|
|||
"ejs": "^3.1.9",
|
||||
"execa": "^8.0.1",
|
||||
"import-meta-resolve": "^3.0.0",
|
||||
"inquirer": "9.2.11",
|
||||
"inquirer": "9.2.12",
|
||||
"lodash.flattendeep": "^4.4.0",
|
||||
"lodash.pickby": "^4.6.0",
|
||||
"lodash.union": "^4.6.0",
|
||||
"read-pkg-up": "^10.0.0",
|
||||
"recursive-readdir": "^2.2.3",
|
||||
"webdriverio": "8.23.1",
|
||||
"webdriverio": "8.24.1",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
|
@ -1188,14 +1191,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/config": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.23.1.tgz",
|
||||
"integrity": "sha512-MljMBvMr+QYoy4/FytFHWorFE3CrBdEWuroOaGzC/0gkVOcHRO4nOy2rKahdcPXJAuxFwJNqqHhBPj+4tWiz9w==",
|
||||
"version": "8.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.24.0.tgz",
|
||||
"integrity": "sha512-n92MPtRCLH763ssS6f/r7uWhnFkIg072nqZK+YnXTlTVIED9SdlMXlyjp9e/1sRmXUc7LbVPwvEVa35lsO0S8w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/utils": "8.23.1",
|
||||
"@wdio/types": "8.24.0",
|
||||
"@wdio/utils": "8.24.0",
|
||||
"decamelize": "^6.0.0",
|
||||
"deepmerge-ts": "^5.0.0",
|
||||
"glob": "^10.2.2",
|
||||
|
@ -1206,29 +1209,29 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/globals": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.23.1.tgz",
|
||||
"integrity": "sha512-bh60QmqueSzqdE+UnNODSSl+w7ECaSQCIYqVs7td3/WM5T17AxQgsom0IapSBFsItHf0g7SQGInkrh3lJ0XclA==",
|
||||
"version": "8.24.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.24.1.tgz",
|
||||
"integrity": "sha512-r5JmeAZd9BiVwUesj8vTRPHybyEMAN/gkscVaawCXEWAm/+7pzLARv6e8PMrAayO4MkeviGBDYCm6d4+nYFOUQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"expect-webdriverio": "^4.5.1",
|
||||
"webdriverio": "8.23.1"
|
||||
"expect-webdriverio": "^4.6.1",
|
||||
"webdriverio": "8.24.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/local-runner": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.23.1.tgz",
|
||||
"integrity": "sha512-d/hnHj3omiAqUtcmAx42OhUTJIM2UU5HtG13gkXzI6NYd0cxicBAV3shkk9EzMFmvFiSDzYHO9Niddoo4IWPgw==",
|
||||
"version": "8.24.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.24.1.tgz",
|
||||
"integrity": "sha512-/KdUVZn7aY5l1SBWd+xiTKhuO/eSAoFgNDLOArbL98ED2TYDzCZ3QCTlebbMckHA4J4ZZW/Rvox75a9Ne6yRzw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/repl": "8.23.1",
|
||||
"@wdio/runner": "8.23.1",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/runner": "8.24.1",
|
||||
"@wdio/types": "8.24.0",
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"split2": "^4.1.0",
|
||||
"stream-buffers": "^3.0.2"
|
||||
|
@ -1265,16 +1268,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/mocha-framework": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.23.1.tgz",
|
||||
"integrity": "sha512-6PbALck8MuLnKhW5JGjCQrtfBivlX1fKqdin6clppVEI6LTqOxj5w8wmLhBbDV5oy68MzaSgc6hP141caWptuQ==",
|
||||
"version": "8.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.24.0.tgz",
|
||||
"integrity": "sha512-UqmvE5Z+KsD+u4mGuV5Y4GUDwrfmX1qIzD07idaLwidU/rHRy+Csn5mzyN38VIrIAuyMYdMGRyxEEieeu6a/4w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/mocha": "^10.0.0",
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/utils": "8.23.1",
|
||||
"@wdio/types": "8.24.0",
|
||||
"@wdio/utils": "8.24.0",
|
||||
"mocha": "^10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -1300,14 +1303,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/reporter": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.23.1.tgz",
|
||||
"integrity": "sha512-MQKImrjRZdiJC1n0mw+OjgroX7SZdFApJTPijAT3mJ0KLeIf5PA+jnW3TZueMcWvG1NB7ZTAzL8BTWInOoZtgA==",
|
||||
"version": "8.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.24.0.tgz",
|
||||
"integrity": "sha512-yQhUwV5W1oDnVzr1pPBaOOCDwAE0Iyri9sAzIHb4pF1ezdUNTVe8ZfoWZSD4i7oC3riK8MlH8hXfGNCfrFrWlg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/types": "8.24.0",
|
||||
"diff": "^5.0.0",
|
||||
"object-inspect": "^1.12.0"
|
||||
},
|
||||
|
@ -1316,35 +1319,35 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/runner": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.23.1.tgz",
|
||||
"integrity": "sha512-lENjpAEfhzCo5a06S+qB3r9wcdavC6BHHHxMmNYxdbH2Fuyt5OGzVB0iFquPnNxwajBn6O7YaIibIw2aLoXP/A==",
|
||||
"version": "8.24.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.24.1.tgz",
|
||||
"integrity": "sha512-IfbLFUM+/cZoEJCLPjesekQ9FjuH/+OnJPzDIcxEv4RLShZX8mQKmiUw/HNMlQlcOkeAzfTObzaT+f8Tt2ZYlQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/config": "8.23.1",
|
||||
"@wdio/globals": "8.23.1",
|
||||
"@wdio/config": "8.24.0",
|
||||
"@wdio/globals": "8.24.1",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/utils": "8.23.1",
|
||||
"@wdio/types": "8.24.0",
|
||||
"@wdio/utils": "8.24.0",
|
||||
"deepmerge-ts": "^5.0.0",
|
||||
"expect-webdriverio": "^4.5.1",
|
||||
"expect-webdriverio": "^4.6.1",
|
||||
"gaze": "^1.1.2",
|
||||
"webdriver": "8.23.1",
|
||||
"webdriverio": "8.23.1"
|
||||
"webdriver": "8.24.0",
|
||||
"webdriverio": "8.24.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/spec-reporter": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.23.1.tgz",
|
||||
"integrity": "sha512-Igc/vsa58xbklwz8vJ1He3tyuxeEP9TQvlT23HizG1QziBvvU1b6V5qnM9BPiDvTg+n3SByJI0Ce0jyn4J2wYQ==",
|
||||
"version": "8.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.24.0.tgz",
|
||||
"integrity": "sha512-L65ua0+lGkmiiElHWE1zD3EnzZzyJli5tLmwYcahh4LwJ3hEOL7ut/GOZ8LTMih87T1q+KttQiJVmgnOEjMH5w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@wdio/reporter": "8.23.1",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/reporter": "8.24.0",
|
||||
"@wdio/types": "8.24.0",
|
||||
"chalk": "^5.1.2",
|
||||
"easy-table": "^1.2.0",
|
||||
"pretty-ms": "^7.0.0"
|
||||
|
@ -1366,9 +1369,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/types": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.23.1.tgz",
|
||||
"integrity": "sha512-ym3tWSUGvmKwQ9vNPQfcKvJwGNK/Fh3e5WloNj3zoaUTKgD0aJeFQ0+Dz6KGlNowA0j5VkcqTTXo+UZ3l4Cx9A==",
|
||||
"version": "8.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.24.0.tgz",
|
||||
"integrity": "sha512-FXbJnQCS1b39RKqBlW9HTNEP4vukxjFc+GiwvPS+XPtY+3Vn7eOyBv3X3CiH1K7C+tzelqlio/HgP68pV5cXsQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0"
|
||||
|
@ -1378,14 +1381,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@wdio/utils": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.23.1.tgz",
|
||||
"integrity": "sha512-VA47MOpt+7svHj3W9r+DUl3t73tJbjF7+ZXL0Lk7QLe79xevd+mPk+YmuTEepn+0MljJWAuqRCEKFG/HK77RNw==",
|
||||
"version": "8.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.24.0.tgz",
|
||||
"integrity": "sha512-m0qsWx2U5ZBTS0vzg1gTBp9mTrcLQlDrOBVR28LJ93a/e0bj+4aQ4c5U2y9gUzV+lKH0wUJSZTLnhebQwapURQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "^1.6.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/types": "8.24.0",
|
||||
"decamelize": "^6.0.0",
|
||||
"deepmerge-ts": "^5.1.0",
|
||||
"edgedriver": "^5.3.5",
|
||||
|
@ -3275,9 +3278,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/expect-webdriverio": {
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/expect-webdriverio/-/expect-webdriverio-4.5.1.tgz",
|
||||
"integrity": "sha512-fwcMpPV/+e0bS+F7+bC1UoQsZYjJTcbA1XhU4VVB2pEZDhNmeuaPrCanA0tLVP8nDya75oegXK7LgPzP3zZR9w==",
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/expect-webdriverio/-/expect-webdriverio-4.6.1.tgz",
|
||||
"integrity": "sha512-w6ee91kN3BoxNGVKQheAqFpRGMehdDg7kDiErEk/oM7tbd/WUT4R4v9KYOUtjiaUFHWWCRW2FtcOOjcd0+1pvQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"expect": "^29.7.0",
|
||||
|
@ -3288,8 +3291,9 @@
|
|||
"node": ">=16 || >=18 || >=20"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@wdio/globals": "^8.22.1",
|
||||
"webdriverio": "^8.22.1"
|
||||
"@wdio/globals": "^8.23.1",
|
||||
"@wdio/logger": "^8.16.17",
|
||||
"webdriverio": "^8.23.1"
|
||||
}
|
||||
},
|
||||
"node_modules/external-editor": {
|
||||
|
@ -4302,12 +4306,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/inquirer": {
|
||||
"version": "9.2.11",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.11.tgz",
|
||||
"integrity": "sha512-B2LafrnnhbRzCWfAdOXisUzL89Kg8cVJlYmhqoi3flSiV/TveO+nsXwgKr9h9PIo+J1hz7nBSk6gegRIMBBf7g==",
|
||||
"version": "9.2.12",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz",
|
||||
"integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@ljharb/through": "^2.3.9",
|
||||
"@ljharb/through": "^2.3.11",
|
||||
"ansi-escapes": "^4.3.2",
|
||||
"chalk": "^5.3.0",
|
||||
"cli-cursor": "^3.1.0",
|
||||
|
@ -8242,6 +8246,19 @@
|
|||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/tshy/node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||
|
@ -8338,9 +8355,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz",
|
||||
"integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
|
@ -8581,9 +8598,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/wdio-wait-for": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/wdio-wait-for/-/wdio-wait-for-3.0.8.tgz",
|
||||
"integrity": "sha512-Lptqzqso57sia7q6BRG2M+4S0YysXobcj9gchZxJBqYewgoH4e6Rime6i4WseIW85zmDMJu8pMSWNK4efong8A==",
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/wdio-wait-for/-/wdio-wait-for-3.0.9.tgz",
|
||||
"integrity": "sha512-f7SZ916X9DpN1ZpY82wbwS0UwpRl8fOmT3v5TIfSn/XNLwDS1qZiGndayd5sNKhzYZFlDQDIIcfOcZDr7YBMcA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
|
@ -8599,18 +8616,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/webdriver": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.23.1.tgz",
|
||||
"integrity": "sha512-0PLN6cqP5cSorZBU2OBk2XKhxKpWWKzvClHBiGCqZIuofZ3kPTq7uYFapej0c4xFmKXHEiLIN7Qkt4H3gWTs8g==",
|
||||
"version": "8.24.0",
|
||||
"resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.24.0.tgz",
|
||||
"integrity": "sha512-zI1zw4lbP2cg1NPikIaUBHQU3+xdvEEBi0Jrydhtp3VVeIEqJWwUFxG/P9LwJpiQ0PYMb/5cxoQrSRhrEXyXHQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@types/ws": "^8.5.3",
|
||||
"@wdio/config": "8.23.1",
|
||||
"@wdio/config": "8.24.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/protocols": "8.23.0",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/utils": "8.23.1",
|
||||
"@wdio/types": "8.24.0",
|
||||
"@wdio/utils": "8.24.0",
|
||||
"deepmerge-ts": "^5.1.0",
|
||||
"got": "^ 12.6.1",
|
||||
"ky": "^0.33.0",
|
||||
|
@ -8658,18 +8675,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/webdriverio": {
|
||||
"version": "8.23.1",
|
||||
"resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.23.1.tgz",
|
||||
"integrity": "sha512-M5F7J3J0L7GpHbcgz5rZNAX5/JgsCggVg8AGY2pYISiS1eN3WJdXve8VVXB2GtcLy12qCZwjoowl91nWTqNclQ==",
|
||||
"version": "8.24.1",
|
||||
"resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.24.1.tgz",
|
||||
"integrity": "sha512-NMu5Y0EFjx7GK4K8uDDi14q8IdHdSQiqzJoyGjuzGy8mj5c04Ta1hoLG5KPag5LzIQNOtJmqwbTFL5PLqragOg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/config": "8.23.1",
|
||||
"@wdio/config": "8.24.0",
|
||||
"@wdio/logger": "8.16.17",
|
||||
"@wdio/protocols": "8.23.0",
|
||||
"@wdio/repl": "8.23.1",
|
||||
"@wdio/types": "8.23.1",
|
||||
"@wdio/utils": "8.23.1",
|
||||
"@wdio/types": "8.24.0",
|
||||
"@wdio/utils": "8.24.0",
|
||||
"archiver": "^6.0.0",
|
||||
"aria-query": "^5.0.0",
|
||||
"css-shorthand-properties": "^1.1.1",
|
||||
|
@ -8686,7 +8703,7 @@
|
|||
"resq": "^1.9.1",
|
||||
"rgb2hex": "0.2.5",
|
||||
"serialize-error": "^11.0.1",
|
||||
"webdriver": "8.23.1"
|
||||
"webdriver": "8.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
|
|
|
@ -4,20 +4,20 @@
|
|||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"@wdio/cli": "^8.23.1",
|
||||
"@wdio/local-runner": "^8.23.1",
|
||||
"@wdio/mocha-framework": "^8.23.1",
|
||||
"@wdio/spec-reporter": "^8.23.1",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.12.0",
|
||||
"@wdio/cli": "^8.24.1",
|
||||
"@wdio/local-runner": "^8.24.1",
|
||||
"@wdio/mocha-framework": "^8.24.0",
|
||||
"@wdio/spec-reporter": "^8.24.0",
|
||||
"eslint": "^8.54.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-sonarjs": "^0.23.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.1.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2",
|
||||
"wdio-wait-for": "^3.0.8"
|
||||
"typescript": "^5.3.2",
|
||||
"wdio-wait-for": "^3.0.9"
|
||||
},
|
||||
"scripts": {
|
||||
"wdio": "wdio run ./wdio.conf.ts",
|
||||
|
|
369
web/package-lock.json
generated
369
web/package-lock.json
generated
|
@ -15,18 +15,17 @@
|
|||
"@codemirror/lang-xml": "^6.0.2",
|
||||
"@codemirror/legacy-modes": "^6.3.3",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@esbuild/linux-arm64": "^0.19.6",
|
||||
"@formatjs/intl-listformat": "^7.5.3",
|
||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||
"@goauthentik/api": "^2023.10.3-1700268969",
|
||||
"@goauthentik/api": "^2023.10.4-1700591367",
|
||||
"@lit-labs/context": "^0.4.0",
|
||||
"@lit-labs/task": "^3.1.0",
|
||||
"@lit/localize": "^0.11.4",
|
||||
"@open-wc/lit-helpers": "^0.6.0",
|
||||
"@patternfly/elements": "^2.4.0",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@sentry/browser": "^7.80.1",
|
||||
"@sentry/tracing": "^7.80.1",
|
||||
"@sentry/browser": "^7.81.1",
|
||||
"@sentry/tracing": "^7.81.1",
|
||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"chart.js": "^4.4.0",
|
||||
|
@ -48,8 +47,8 @@
|
|||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.23.3",
|
||||
"@babel/plugin-transform-private-methods": "^7.23.3",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.23.3",
|
||||
"@babel/plugin-transform-runtime": "^7.23.3",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.23.4",
|
||||
"@babel/plugin-transform-runtime": "^7.23.4",
|
||||
"@babel/preset-env": "^7.23.3",
|
||||
"@babel/preset-typescript": "^7.23.3",
|
||||
"@hcaptcha/types": "^1.0.3",
|
||||
|
@ -68,11 +67,11 @@
|
|||
"@storybook/web-components": "^7.5.3",
|
||||
"@storybook/web-components-vite": "^7.5.3",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/chart.js": "^2.9.40",
|
||||
"@types/codemirror": "5.60.13",
|
||||
"@types/chart.js": "^2.9.41",
|
||||
"@types/codemirror": "5.60.15",
|
||||
"@types/grecaptcha": "^3.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.12.0",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"babel-plugin-tsconfig-paths": "^1.0.3",
|
||||
"cross-env": "^7.0.3",
|
||||
|
@ -86,10 +85,10 @@
|
|||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.1.0",
|
||||
"pseudolocale": "^2.0.0",
|
||||
"pyright": "^1.1.336",
|
||||
"pyright": "^1.1.337",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"rollup": "^4.5.0",
|
||||
"rollup": "^4.5.1",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"rollup-plugin-cssimport": "^1.0.3",
|
||||
"rollup-plugin-postcss-lit": "^2.1.0",
|
||||
|
@ -98,16 +97,16 @@
|
|||
"ts-lit-plugin": "^2.0.1",
|
||||
"tslib": "^2.6.2",
|
||||
"turnstile-types": "^1.1.3",
|
||||
"typescript": "^5.2.2",
|
||||
"typescript": "^5.3.2",
|
||||
"vite-tsconfig-paths": "^4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/darwin-arm64": "^0.19.6",
|
||||
"@esbuild/darwin-arm64": "^0.19.7",
|
||||
"@esbuild/linux-amd64": "^0.18.11",
|
||||
"@esbuild/linux-arm64": "^0.19.6"
|
||||
"@esbuild/linux-arm64": "^0.19.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@aashutoshrathi/word-wrap": {
|
||||
|
@ -1603,9 +1602,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-private-property-in-object": {
|
||||
"version": "7.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.3.tgz",
|
||||
"integrity": "sha512-a5m2oLNFyje2e/rGKjVfAELTVI5mbA0FeZpBnkOWWV7eSmKQ+T/XW0Vf+29ScLzSxX+rnsarvU0oie/4m6hkxA==",
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz",
|
||||
"integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-annotate-as-pure": "^7.22.5",
|
||||
|
@ -1667,9 +1666,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-runtime": {
|
||||
"version": "7.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.3.tgz",
|
||||
"integrity": "sha512-XcQ3X58CKBdBnnZpPaQjgVMePsXtSZzHoku70q9tUAQp02ggPQNM04BF3RvlW1GSM/McbSOQAzEK4MXbS7/JFg==",
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.4.tgz",
|
||||
"integrity": "sha512-ITwqpb6V4btwUG0YJR82o2QvmWrLgDnx/p2A3CTPYGaRgULkDiC0DRA2C4jlRB9uXGUEfaSS/IGHfVW+ohzYDw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.22.15",
|
||||
|
@ -2444,9 +2443,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.19.6",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.6.tgz",
|
||||
"integrity": "sha512-91LoRp/uZAKx6ESNspL3I46ypwzdqyDLXZH7x2QYCLgtnaU08+AXEbabY2yExIz03/am0DivsTtbdxzGejfXpA==",
|
||||
"version": "0.19.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.7.tgz",
|
||||
"integrity": "sha512-dr81gbmWN//3ZnBIm6YNCl4p3pjnabg1/ZVOgz2fJoUO1a3mq9WQ/1iuEluMs7mCL+Zwv7AY5e3g1hjXqQZ9Iw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2523,9 +2522,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.19.6",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.6.tgz",
|
||||
"integrity": "sha512-HQCOrk9XlH3KngASLaBfHpcoYEGUt829A9MyxaI8RMkfRA8SakG6YQEITAuwmtzFdEu5GU4eyhKcpv27dFaOBg==",
|
||||
"version": "0.19.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.7.tgz",
|
||||
"integrity": "sha512-inHqdOVCkUhHNvuQPT1oCB7cWz9qQ/Cz46xmVe0b7UXcuIJU3166aqSunsqkgSGMtUCWOZw3+KMwI6otINuC9g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2924,9 +2923,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@goauthentik/api": {
|
||||
"version": "2023.10.3-1700268969",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.10.3-1700268969.tgz",
|
||||
"integrity": "sha512-EwkNfFL8sgPzDRHQ+IlkYyFxlN9U79x3OaRgVR1GuEyKF2XXNm+ftdpqSmTSYeIrObEdOgvKItqKBGw5EYZXsg=="
|
||||
"version": "2023.10.4-1700591367",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.10.4-1700591367.tgz",
|
||||
"integrity": "sha512-ljC/SHH6ZgGC2qjvuA3gley8sRz9wVzr5FgRGKeqd1mi6G6TfnFYeA7tuuqgQc6WGN2MVMG17FnBraTI77Rl/A=="
|
||||
},
|
||||
"node_modules/@hcaptcha/types": {
|
||||
"version": "1.0.3",
|
||||
|
@ -3591,6 +3590,19 @@
|
|||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@lit/localize-tools/node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/@lit/reactive-element": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz",
|
||||
|
@ -4580,9 +4592,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.5.0.tgz",
|
||||
"integrity": "sha512-OINaBGY+Wc++U0rdr7BLuFClxcoWaVW3vQYqmQq6B3bqQ/2olkaoz+K8+af/Mmka/C2yN5j+L9scBkv4BtKsDA==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.5.1.tgz",
|
||||
"integrity": "sha512-YaN43wTyEBaMqLDYeze+gQ4ZrW5RbTEGtT5o1GVDkhpdNcsLTnLRcLccvwy3E9wiDKWg9RIhuoy3JQKDRBfaZA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
@ -4593,9 +4605,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.5.0.tgz",
|
||||
"integrity": "sha512-UdMf1pOQc4ZmUA/NTmKhgJTBimbSKnhPS2zJqucqFyBRFPnPDtwA8MzrGNTjDeQbIAWfpJVAlxejw+/lQyBK/w==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.5.1.tgz",
|
||||
"integrity": "sha512-n1bX+LCGlQVuPlCofO0zOKe1b2XkFozAVRoczT+yxWZPGnkEAKTTYVOGZz8N4sKuBnKMxDbfhUsB1uwYdup/sw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -4606,9 +4618,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.5.0.tgz",
|
||||
"integrity": "sha512-L0/CA5p/idVKI+c9PcAPGorH6CwXn6+J0Ys7Gg1axCbTPgI8MeMlhA6fLM9fK+ssFhqogMHFC8HDvZuetOii7w==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.5.1.tgz",
|
||||
"integrity": "sha512-QqJBumdvfBqBBmyGHlKxje+iowZwrHna7pokj/Go3dV1PJekSKfmjKrjKQ/e6ESTGhkfPNLq3VXdYLAc+UtAQw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -4619,9 +4631,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.5.0.tgz",
|
||||
"integrity": "sha512-QZCbVqU26mNlLn8zi/XDDquNmvcr4ON5FYAHQQsyhrHx8q+sQi/6xduoznYXwk/KmKIXG5dLfR0CvY+NAWpFYQ==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.5.1.tgz",
|
||||
"integrity": "sha512-RrkDNkR/P5AEQSPkxQPmd2ri8WTjSl0RYmuFOiEABkEY/FSg0a4riihWQGKDJ4LnV9gigWZlTMx2DtFGzUrYQw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -4632,9 +4644,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.5.0.tgz",
|
||||
"integrity": "sha512-VpSQ+xm93AeV33QbYslgf44wc5eJGYfYitlQzAi3OObu9iwrGXEnmu5S3ilkqE3Pr/FkgOiJKV/2p0ewf4Hrtg==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.5.1.tgz",
|
||||
"integrity": "sha512-ZFPxvUZmE+fkB/8D9y/SWl/XaDzNSaxd1TJUSE27XAKlRpQ2VNce/86bGd9mEUgL3qrvjJ9XTGwoX0BrJkYK/A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
@ -4645,9 +4657,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.5.0.tgz",
|
||||
"integrity": "sha512-OrEyIfpxSsMal44JpEVx9AEcGpdBQG1ZuWISAanaQTSMeStBW+oHWwOkoqR54bw3x8heP8gBOyoJiGg+fLY8qQ==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.5.1.tgz",
|
||||
"integrity": "sha512-FEuAjzVIld5WVhu+M2OewLmjmbXWd3q7Zcx+Rwy4QObQCqfblriDMMS7p7+pwgjZoo9BLkP3wa9uglQXzsB9ww==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -4658,9 +4670,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.5.0.tgz",
|
||||
"integrity": "sha512-1H7wBbQuE6igQdxMSTjtFfD+DGAudcYWhp106z/9zBA8OQhsJRnemO4XGavdzHpGhRtRxbgmUGdO3YQgrWf2RA==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.5.1.tgz",
|
||||
"integrity": "sha512-f5Gs8WQixqGRtI0Iq/cMqvFYmgFzMinuJO24KRfnv7Ohi/HQclwrBCYkzQu1XfLEEt3DZyvveq9HWo4bLJf1Lw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -4671,9 +4683,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.5.0.tgz",
|
||||
"integrity": "sha512-FVyFI13tXw5aE65sZdBpNjPVIi4Q5mARnL/39UIkxvSgRAIqCo5sCpCELk0JtXHGee2owZz5aNLbWNfBHzr71Q==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.5.1.tgz",
|
||||
"integrity": "sha512-CWPkPGrFfN2vj3mw+S7A/4ZaU3rTV7AkXUr08W9lNP+UzOvKLVf34tWCqrKrfwQ0NTk5GFqUr2XGpeR2p6R4gw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -4684,9 +4696,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.5.0.tgz",
|
||||
"integrity": "sha512-eBPYl2sLpH/o8qbSz6vPwWlDyThnQjJfcDOGFbNjmjb44XKC1F5dQfakOsADRVrXCNzM6ZsSIPDG5dc6HHLNFg==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.5.1.tgz",
|
||||
"integrity": "sha512-ZRETMFA0uVukUC9u31Ed1nx++29073goCxZtmZARwk5aF/ltuENaeTtRVsSQzFlzdd4J6L3qUm+EW8cbGt0CKQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -4697,9 +4709,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.5.0.tgz",
|
||||
"integrity": "sha512-xaOHIfLOZypoQ5U2I6rEaugS4IYtTgP030xzvrBf5js7p9WI9wik07iHmsKaej8Z83ZDxN5GyypfoyKV5O5TJA==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.5.1.tgz",
|
||||
"integrity": "sha512-ihqfNJNb2XtoZMSCPeoo0cYMgU04ksyFIoOw5S0JUVbOhafLot+KD82vpKXOurE2+9o/awrqIxku9MRR9hozHQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -4710,9 +4722,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.5.0.tgz",
|
||||
"integrity": "sha512-Al6quztQUrHwcOoU2TuFblUQ5L+/AmPBXFR6dUvyo4nRj2yQRK0WIUaGMF/uwKulvRcXkpHe3k9A8Vf93VDktA==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.5.1.tgz",
|
||||
"integrity": "sha512-zK9MRpC8946lQ9ypFn4gLpdwr5a01aQ/odiIJeL9EbgZDMgbZjjT/XzTqJvDfTmnE1kHdbG20sAeNlpc91/wbg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
|
@ -4723,9 +4735,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.5.0.tgz",
|
||||
"integrity": "sha512-8kdW+brNhI/NzJ4fxDufuJUjepzINqJKLGHuxyAtpPG9bMbn8P5mtaCcbOm0EzLJ+atg+kF9dwg8jpclkVqx5w==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.5.1.tgz",
|
||||
"integrity": "sha512-5I3Nz4Sb9TYOtkRwlH0ow+BhMH2vnh38tZ4J4mggE48M/YyJyp/0sPSxhw1UeS1+oBgQ8q7maFtSeKpeRJu41Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -4736,84 +4748,84 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@sentry-internal/tracing": {
|
||||
"version": "7.80.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.80.1.tgz",
|
||||
"integrity": "sha512-5gZ4LPIj2vpQl2/dHBM4uXMi9OI5E0VlOhJQt0foiuN6JJeiOjdpJFcfVqJk69wrc0deVENTtgKKktxqMwVeWQ==",
|
||||
"version": "7.81.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.81.1.tgz",
|
||||
"integrity": "sha512-E5xm27xrLXL10knH2EWDQsQYh5nb4SxxZzJ3sJwDGG9XGKzBdlp20UUhKqx00wixooVX9uCj3e4Jg8SvNB1hKg==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.80.1",
|
||||
"@sentry/types": "7.80.1",
|
||||
"@sentry/utils": "7.80.1"
|
||||
"@sentry/core": "7.81.1",
|
||||
"@sentry/types": "7.81.1",
|
||||
"@sentry/utils": "7.81.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "7.80.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.80.1.tgz",
|
||||
"integrity": "sha512-1dPR6vPJ9vOTzgXff9HGheb178XeEv5hyjBNhCO1f6rjCgnVj99XGNZIgO1Ee1ALJbqlfPWaeV+uSWbbcmgJMA==",
|
||||
"version": "7.81.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.81.1.tgz",
|
||||
"integrity": "sha512-DNtS7bZEnFPKVoGazKs5wHoWC0FwsOFOOMNeDvEfouUqKKbjO7+RDHbr7H6Bo83zX4qmZWRBf8V+3n3YPIiJFw==",
|
||||
"dependencies": {
|
||||
"@sentry-internal/tracing": "7.80.1",
|
||||
"@sentry/core": "7.80.1",
|
||||
"@sentry/replay": "7.80.1",
|
||||
"@sentry/types": "7.80.1",
|
||||
"@sentry/utils": "7.80.1"
|
||||
"@sentry-internal/tracing": "7.81.1",
|
||||
"@sentry/core": "7.81.1",
|
||||
"@sentry/replay": "7.81.1",
|
||||
"@sentry/types": "7.81.1",
|
||||
"@sentry/utils": "7.81.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "7.80.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.80.1.tgz",
|
||||
"integrity": "sha512-3Yh+O9Q86MxwIuJFYtuSSoUCpdx99P1xDAqL0FIPTJ+ekaVMiUJq9NmyaNh9uN2myPSmxvEXW6q3z37zta9ZHg==",
|
||||
"version": "7.81.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.81.1.tgz",
|
||||
"integrity": "sha512-tU37yAmckOGCw/moWKSwekSCWWJP15O6luIq+u7wal22hE88F3Vc5Avo8SeF3upnPR+4ejaOFH+BJTr6bgrs6Q==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.80.1",
|
||||
"@sentry/utils": "7.80.1"
|
||||
"@sentry/types": "7.81.1",
|
||||
"@sentry/utils": "7.81.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/replay": {
|
||||
"version": "7.80.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.80.1.tgz",
|
||||
"integrity": "sha512-yjpftIyybQeWD2i0Nd7C96tZwjNbSMRW515EL9jwlNxYbQtGtMs0HavP9Y7uQvQrzwSHY0Wp+ooe9PMuvzqbHw==",
|
||||
"version": "7.81.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.81.1.tgz",
|
||||
"integrity": "sha512-4ueT0C4bYjngN/9p0fEYH10dTMLovHyk9HxJ6zSTgePvGVexhg+cSEHXisoBDwHeRZVnbIvsVM0NA7rmEDXJJw==",
|
||||
"dependencies": {
|
||||
"@sentry-internal/tracing": "7.80.1",
|
||||
"@sentry/core": "7.80.1",
|
||||
"@sentry/types": "7.80.1",
|
||||
"@sentry/utils": "7.80.1"
|
||||
"@sentry-internal/tracing": "7.81.1",
|
||||
"@sentry/core": "7.81.1",
|
||||
"@sentry/types": "7.81.1",
|
||||
"@sentry/utils": "7.81.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/tracing": {
|
||||
"version": "7.80.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.80.1.tgz",
|
||||
"integrity": "sha512-sFkcxCBtLNVa3EyeCafZqhJHZ714f2+ryPWTBckAmxAsON4yjh/YLs2X1FJ2n6Rnv16TP6gWGt4SnhFT03WStA==",
|
||||
"version": "7.81.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.81.1.tgz",
|
||||
"integrity": "sha512-of9WMu0XgEBl9onTEk8SMaxj4BUadaUvHH96T1OpRMjdyuCM/3u2mjCkh3ekINr3Fu/uT2kJ/kO3goUxfcdXIQ==",
|
||||
"dependencies": {
|
||||
"@sentry-internal/tracing": "7.80.1"
|
||||
"@sentry-internal/tracing": "7.81.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "7.80.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.80.1.tgz",
|
||||
"integrity": "sha512-CVu4uPVTOI3U9kYiOdA085R7jX5H1oVODbs9y+A8opJ0dtJTMueCXgZyE8oXQ0NjGVs6HEeaLkOuiV0mj8X3yw==",
|
||||
"version": "7.81.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.81.1.tgz",
|
||||
"integrity": "sha512-dvJvGyctiaPMIQqa46k56Re5IODWMDxiHJ1UjBs/WYDLrmWFPGrEbyJ8w8CYLhYA+7qqrCyIZmHbWSTRIxstHw==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/utils": {
|
||||
"version": "7.80.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.80.1.tgz",
|
||||
"integrity": "sha512-bfFm2e/nEn+b9++QwjNEYCbS7EqmteT8uf0XUs7PljusSimIqqxDtK1pfD9zjynPgC8kW/fVBKv0pe2LufomeA==",
|
||||
"version": "7.81.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.81.1.tgz",
|
||||
"integrity": "sha512-gq+MDXIirHKxNZ+c9/lVvCXd6y2zaZANujwlFggRH2u9SRiPaIXVilLpvMm4uJqmqBMEcY81ArujExtHvkbCqg==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.80.1"
|
||||
"@sentry/types": "7.81.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
|
@ -10108,18 +10120,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/chart.js": {
|
||||
"version": "2.9.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.40.tgz",
|
||||
"integrity": "sha512-ApIH2LIDXzKTNtG4oTMmn2CIII6lvRvxyKnmLb1zYFlwXtE4lTOb2ywgXQJYVuhgWpqaCSHSYOlzO+5gs6hL+A==",
|
||||
"version": "2.9.41",
|
||||
"resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.41.tgz",
|
||||
"integrity": "sha512-3dvkDvueckY83UyUXtJMalYoH6faOLkWQoaTlJgB4Djde3oORmNP0Jw85HtzTuXyliUHcdp704s0mZFQKio/KQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"moment": "^2.10.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/codemirror": {
|
||||
"version": "5.60.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.13.tgz",
|
||||
"integrity": "sha512-qLWcKUwYDYB7mZpE++0Jn3i1TJ2GW8nlhALRAfjaKgb1HRnk2qcNqWxZ+BpPY1h4n4IQT0foThaOxWHxEL8MnQ==",
|
||||
"version": "5.60.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.15.tgz",
|
||||
"integrity": "sha512-dTOvwEQ+ouKJ/rE9LT1Ue2hmP6H1mZv5+CCnNWu2qtiOe2LQa9lCprEY20HxiDmV/Bxh+dXjywmy5aKvoGjULA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/tern": "*"
|
||||
|
@ -10493,16 +10505,16 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.11.0.tgz",
|
||||
"integrity": "sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz",
|
||||
"integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.5.1",
|
||||
"@typescript-eslint/scope-manager": "6.11.0",
|
||||
"@typescript-eslint/type-utils": "6.11.0",
|
||||
"@typescript-eslint/utils": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0",
|
||||
"@typescript-eslint/scope-manager": "6.12.0",
|
||||
"@typescript-eslint/type-utils": "6.12.0",
|
||||
"@typescript-eslint/utils": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0",
|
||||
"debug": "^4.3.4",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.2.4",
|
||||
|
@ -10561,15 +10573,15 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.11.0.tgz",
|
||||
"integrity": "sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz",
|
||||
"integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "6.11.0",
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/typescript-estree": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0",
|
||||
"@typescript-eslint/scope-manager": "6.12.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/typescript-estree": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -10589,13 +10601,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.11.0.tgz",
|
||||
"integrity": "sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz",
|
||||
"integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0"
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
|
@ -10606,13 +10618,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.11.0.tgz",
|
||||
"integrity": "sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz",
|
||||
"integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "6.11.0",
|
||||
"@typescript-eslint/utils": "6.11.0",
|
||||
"@typescript-eslint/typescript-estree": "6.12.0",
|
||||
"@typescript-eslint/utils": "6.12.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
|
@ -10633,9 +10645,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.11.0.tgz",
|
||||
"integrity": "sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz",
|
||||
"integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
|
@ -10646,13 +10658,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.11.0.tgz",
|
||||
"integrity": "sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz",
|
||||
"integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/visitor-keys": "6.11.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/visitor-keys": "6.12.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
|
@ -10706,17 +10718,17 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.11.0.tgz",
|
||||
"integrity": "sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz",
|
||||
"integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@types/json-schema": "^7.0.12",
|
||||
"@types/semver": "^7.5.0",
|
||||
"@typescript-eslint/scope-manager": "6.11.0",
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/typescript-estree": "6.11.0",
|
||||
"@typescript-eslint/scope-manager": "6.12.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"@typescript-eslint/typescript-estree": "6.12.0",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -10764,12 +10776,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.11.0.tgz",
|
||||
"integrity": "sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz",
|
||||
"integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.11.0",
|
||||
"@typescript-eslint/types": "6.12.0",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -18456,9 +18468,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/pyright": {
|
||||
"version": "1.1.336",
|
||||
"resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.336.tgz",
|
||||
"integrity": "sha512-PE/ArjnfS5dKon05zAX2eMzSQmu4ftCITzLqKgFKuwLIRnKJ+l4QGwkCKtYvWoXKm1fWr+TjqYpdRejrYkolyg==",
|
||||
"version": "1.1.337",
|
||||
"resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.337.tgz",
|
||||
"integrity": "sha512-iZcID/OX5rjiToKCb3DShygOC21Zx8GvSwei+ApyTfK2C2xdRWyV+yJCrUUF75/qVkTZy8ZCDwQc4aYDqD8Scg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"pyright": "index.js",
|
||||
|
@ -19158,9 +19170,9 @@
|
|||
"integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.5.0.tgz",
|
||||
"integrity": "sha512-41xsWhzxqjMDASCxH5ibw1mXk+3c4TNI2UjKbLxe6iEzrSQnqOzmmK8/3mufCPbzHNJ2e04Fc1ddI35hHy+8zg==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.5.1.tgz",
|
||||
"integrity": "sha512-0EQribZoPKpb5z1NW/QYm3XSR//Xr8BeEXU49Lc/mQmpmVVG5jPUVrpc2iptup/0WMrY9mzas0fxH+TjYvG2CA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
|
@ -19170,18 +19182,18 @@
|
|||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.5.0",
|
||||
"@rollup/rollup-android-arm64": "4.5.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.5.0",
|
||||
"@rollup/rollup-darwin-x64": "4.5.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.5.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.5.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.5.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.5.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.5.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.5.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.5.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.5.0",
|
||||
"@rollup/rollup-android-arm-eabi": "4.5.1",
|
||||
"@rollup/rollup-android-arm64": "4.5.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.5.1",
|
||||
"@rollup/rollup-darwin-x64": "4.5.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.5.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.5.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.5.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.5.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.5.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.5.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.5.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.5.1",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
|
@ -20918,9 +20930,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz",
|
||||
"integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
|
@ -21492,6 +21504,19 @@
|
|||
"web-component-analyzer": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/web-component-analyzer/node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "4.0.0-beta.3",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
|
||||
|
|
|
@ -38,15 +38,15 @@
|
|||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@formatjs/intl-listformat": "^7.5.3",
|
||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||
"@goauthentik/api": "^2023.10.3-1700268969",
|
||||
"@goauthentik/api": "^2023.10.4-1700591367",
|
||||
"@lit-labs/context": "^0.4.0",
|
||||
"@lit-labs/task": "^3.1.0",
|
||||
"@lit/localize": "^0.11.4",
|
||||
"@open-wc/lit-helpers": "^0.6.0",
|
||||
"@patternfly/elements": "^2.4.0",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@sentry/browser": "^7.80.1",
|
||||
"@sentry/tracing": "^7.80.1",
|
||||
"@sentry/browser": "^7.81.1",
|
||||
"@sentry/tracing": "^7.81.1",
|
||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"chart.js": "^4.4.0",
|
||||
|
@ -68,8 +68,8 @@
|
|||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.23.3",
|
||||
"@babel/plugin-transform-private-methods": "^7.23.3",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.23.3",
|
||||
"@babel/plugin-transform-runtime": "^7.23.3",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.23.4",
|
||||
"@babel/plugin-transform-runtime": "^7.23.4",
|
||||
"@babel/preset-env": "^7.23.3",
|
||||
"@babel/preset-typescript": "^7.23.3",
|
||||
"@hcaptcha/types": "^1.0.3",
|
||||
|
@ -88,11 +88,11 @@
|
|||
"@storybook/web-components": "^7.5.3",
|
||||
"@storybook/web-components-vite": "^7.5.3",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/chart.js": "^2.9.40",
|
||||
"@types/codemirror": "5.60.13",
|
||||
"@types/chart.js": "^2.9.41",
|
||||
"@types/codemirror": "5.60.15",
|
||||
"@types/grecaptcha": "^3.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.12.0",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"babel-plugin-tsconfig-paths": "^1.0.3",
|
||||
"cross-env": "^7.0.3",
|
||||
|
@ -106,10 +106,10 @@
|
|||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.1.0",
|
||||
"pseudolocale": "^2.0.0",
|
||||
"pyright": "^1.1.336",
|
||||
"pyright": "^1.1.337",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"rollup": "^4.5.0",
|
||||
"rollup": "^4.5.1",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"rollup-plugin-cssimport": "^1.0.3",
|
||||
"rollup-plugin-postcss-lit": "^2.1.0",
|
||||
|
@ -118,13 +118,13 @@
|
|||
"ts-lit-plugin": "^2.0.1",
|
||||
"tslib": "^2.6.2",
|
||||
"turnstile-types": "^1.1.3",
|
||||
"typescript": "^5.2.2",
|
||||
"typescript": "^5.3.2",
|
||||
"vite-tsconfig-paths": "^4.2.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/darwin-arm64": "^0.19.6",
|
||||
"@esbuild/darwin-arm64": "^0.19.7",
|
||||
"@esbuild/linux-amd64": "^0.18.11",
|
||||
"@esbuild/linux-arm64": "^0.19.6"
|
||||
"@esbuild/linux-arm64": "^0.19.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
|
|
|
@ -160,14 +160,14 @@ export class AkAdminSidebar extends AKElement {
|
|||
[
|
||||
reload,
|
||||
msg(
|
||||
str`You're currently impersonating ${this.impersonation}. Click to stop.`,
|
||||
str`You're currently impersonating ${this.impersonation}. Click to stop.`
|
||||
),
|
||||
],
|
||||
]
|
||||
: [];
|
||||
|
||||
const enterpriseMenu: LocalSidebarEntry[] = this.config?.capabilities.includes(
|
||||
CapabilitiesEnum.IsEnterprise,
|
||||
CapabilitiesEnum.IsEnterprise
|
||||
)
|
||||
? [[null, msg("Enterprise"), null, [["/enterprise/licenses", msg("Licenses")]]]]
|
||||
: [];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import { Form } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import "@goauthentik/elements/forms/SearchSelect";
|
||||
|
@ -57,9 +57,7 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
|
|||
<div class="pf-c-form__group-label">
|
||||
<div class="c-form__horizontal-group">
|
||||
<span class="pf-c-form__label-text">
|
||||
<ak-label color=${this.result?.passing ? PFColor.Green : PFColor.Red}>
|
||||
${this.result?.passing ? msg("Yes") : msg("No")}
|
||||
</ak-label>
|
||||
<ak-status-label ?good=${this.result?.passing}></ak-status-label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@ import "@goauthentik/admin/blueprints/BlueprintForm";
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/buttons/ActionButton";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
|
@ -144,9 +144,7 @@ export class BlueprintListPage extends TablePage<BlueprintInstance> {
|
|||
${description ? html`<small>${description}</small>` : html``}`,
|
||||
html`${BlueprintStatus(item)}`,
|
||||
html`${item.lastApplied.toLocaleString()}`,
|
||||
html`<ak-label color=${item.enabled ? PFColor.Green : PFColor.Red}>
|
||||
${item.enabled ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-status-label ?good=${item.enabled}></ak-status-label>`,
|
||||
html`<ak-forms-modal>
|
||||
<span slot="submit"> ${msg("Update")} </span>
|
||||
<span slot="header"> ${msg("Update Blueprint")} </span>
|
||||
|
|
|
@ -2,6 +2,7 @@ import "@goauthentik/admin/crypto/CertificateGenerateForm";
|
|||
import "@goauthentik/admin/crypto/CertificateKeyPairForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
|
@ -117,11 +118,12 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
|
|||
return [
|
||||
html`<div>${item.name}</div>
|
||||
${item.managed ? html`<small>${managedSubText}</small>` : html``}`,
|
||||
html`<ak-label color=${item.privateKeyAvailable ? PFColor.Green : PFColor.Grey}>
|
||||
${item.privateKeyAvailable
|
||||
? msg(str`Yes (${item.privateKeyType?.toUpperCase()})`)
|
||||
: msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-status-label
|
||||
type="info"
|
||||
?good=${item.privateKeyAvailable}
|
||||
good-label=${msg(str`Yes (${item.privateKeyType?.toUpperCase()})`)}
|
||||
>
|
||||
</ak-status-label>`,
|
||||
html`<ak-label color=${color}> ${item.certExpiry?.toLocaleString()} </ak-label>`,
|
||||
html`<ak-forms-modal>
|
||||
<span slot="submit"> ${msg("Update")} </span>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { SentryIgnoredError } from "@goauthentik/common/errors";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import { Form } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
|
||||
|
@ -46,9 +46,7 @@ export class FlowImportForm extends Form<Flow> {
|
|||
<div class="pf-c-form__group-label">
|
||||
<div class="c-form__horizontal-group">
|
||||
<span class="pf-c-form__label-text">
|
||||
<ak-label color=${this.result?.success ? PFColor.Green : PFColor.Red}>
|
||||
${this.result?.success ? msg("Yes") : msg("No")}
|
||||
</ak-label>
|
||||
<ak-status-label ?good=${this.result?.success}></ak-status-label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import "@goauthentik/admin/groups/GroupForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import "@goauthentik/elements/forms/ModalForm";
|
||||
|
@ -81,10 +81,8 @@ export class GroupListPage extends TablePage<Group> {
|
|||
html`<a href="#/identity/groups/${item.pk}">${item.name}</a>`,
|
||||
html`${item.parentName || msg("-")}`,
|
||||
html`${Array.from(item.users || []).length}`,
|
||||
html`<ak-label color=${item.isSuperuser ? PFColor.Green : PFColor.Grey}>
|
||||
${item.isSuperuser ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html` <ak-forms-modal>
|
||||
html`<ak-label type="info" ?good=${item.isSuperuser}></ak-label>`,
|
||||
html`<ak-forms-modal>
|
||||
<span slot="submit"> ${msg("Update")} </span>
|
||||
<span slot="header"> ${msg("Update Group")} </span>
|
||||
<ak-group-form slot="form" .instancePk=${item.pk}> </ak-group-form>
|
||||
|
|
|
@ -3,10 +3,10 @@ import "@goauthentik/app/admin/groups/RelatedUserList";
|
|||
import "@goauthentik/app/elements/rbac/ObjectPermissionsPage";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/components/events/ObjectChangelog";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/CodeMirror";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/elements/PageHeader";
|
||||
import "@goauthentik/elements/Tabs";
|
||||
import "@goauthentik/elements/buttons/ActionButton";
|
||||
|
@ -116,11 +116,10 @@ export class GroupViewPage extends AKElement {
|
|||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">
|
||||
<ak-label
|
||||
color=${this.group.isSuperuser
|
||||
? PFColor.Green
|
||||
: PFColor.Orange}
|
||||
></ak-label>
|
||||
<ak-status-label
|
||||
type="warning"
|
||||
?good=${this.group.isSuperuser}
|
||||
></ak-status-label>
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { first } from "@goauthentik/common/utils";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
||||
import { TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
@ -48,9 +48,7 @@ export class MemberSelectTable extends TableModal<User> {
|
|||
return [
|
||||
html`<div>${item.username}</div>
|
||||
<small>${item.name}</small>`,
|
||||
html` <ak-label color=${item.isActive ? PFColor.Green : PFColor.Orange}>
|
||||
${item.isActive ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html` <ak-status-label type="warning" ?good=${item.isActive}></ak-status-label>`,
|
||||
html`${first(item.lastLogin?.toLocaleString(), msg("-"))}`,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import "@goauthentik/admin/groups/GroupForm";
|
|||
import "@goauthentik/admin/users/GroupSelectModal";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import { Form } from "@goauthentik/elements/forms/Form";
|
||||
|
@ -145,9 +145,7 @@ export class RelatedGroupList extends Table<Group> {
|
|||
return [
|
||||
html`<a href="#/identity/groups/${item.pk}">${item.name}</a>`,
|
||||
html`${item.parentName || msg("-")}`,
|
||||
html`<ak-label color=${item.isSuperuser ? PFColor.Green : PFColor.Grey}>
|
||||
${item.isSuperuser ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-label type="info" ?good=${item.isSuperuser}></ak-label>`,
|
||||
html` <ak-forms-modal>
|
||||
<span slot="submit"> ${msg("Update")} </span>
|
||||
<span slot="header"> ${msg("Update Group")} </span>
|
||||
|
|
|
@ -8,8 +8,8 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
|||
import { MessageLevel } from "@goauthentik/common/messages";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { first } from "@goauthentik/common/utils";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import { rootInterface } from "@goauthentik/elements/Base";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/elements/buttons/ActionButton";
|
||||
import "@goauthentik/elements/buttons/Dropdown";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
|
@ -195,9 +195,7 @@ export class RelatedUserList extends Table<User> {
|
|||
<div>${item.username}</div>
|
||||
<small>${item.name}</small>
|
||||
</a>`,
|
||||
html`<ak-label color=${item.isActive ? PFColor.Green : PFColor.Red}>
|
||||
${item.isActive ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-status-label ?good=${item.isActive}></ak-status-label>`,
|
||||
html`${first(item.lastLogin?.toLocaleString(), msg("-"))}`,
|
||||
html`<ak-forms-modal>
|
||||
<span slot="submit"> ${msg("Update")} </span>
|
||||
|
|
|
@ -4,6 +4,7 @@ import "@goauthentik/admin/outposts/ServiceConnectionKubernetesForm";
|
|||
import "@goauthentik/admin/outposts/ServiceConnectionWizard";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
|
@ -83,9 +84,7 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
|
|||
return [
|
||||
html`${item.name}`,
|
||||
html`${item.verboseName}`,
|
||||
html`<ak-label color=${item.local ? PFColor.Grey : PFColor.Green}>
|
||||
${item.local ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-status-label type="info" ?good=${item.local}></ak-status-label>`,
|
||||
html`${itemState?.healthy
|
||||
? html`<ak-label color=${PFColor.Green}>${ifDefined(itemState.version)}</ak-label>`
|
||||
: html`<ak-label color=${PFColor.Red}>${msg("Unhealthy")}</ak-label>`}`,
|
||||
|
|
|
@ -4,7 +4,7 @@ import "@goauthentik/admin/policies/PolicyWizard";
|
|||
import "@goauthentik/admin/users/UserForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import { PFSize } from "@goauthentik/elements/Spinner";
|
||||
import "@goauthentik/elements/Tabs";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
|
@ -147,9 +147,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
|
|||
return [
|
||||
html`<pre>${item.order}</pre>`,
|
||||
html`${this.getPolicyUserGroupRow(item)}`,
|
||||
html` <ak-label color=${item.enabled ? PFColor.Green : PFColor.Orange}>
|
||||
${item.enabled ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-status-label type="warning" ?good=${item.enabled}></ak-status-label>`,
|
||||
html`${item.timeout}`,
|
||||
html` ${this.getObjectEditButton(item)}
|
||||
<ak-forms-modal size=${PFSize.Medium}>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { first } from "@goauthentik/common/utils";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/CodeMirror";
|
||||
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import { Form } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import "@goauthentik/elements/forms/SearchSelect";
|
||||
|
@ -58,9 +58,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
|
|||
<div class="pf-c-form__group-label">
|
||||
<div class="c-form__horizontal-group">
|
||||
<span class="pf-c-form__label-text">
|
||||
<ak-label color=${this.result?.passing ? PFColor.Green : PFColor.Red}>
|
||||
${this.result?.passing ? msg("Yes") : msg("No")}
|
||||
</ak-label>
|
||||
<ak-status-label ?good=${this.result?.passing}></ak-status-label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,6 +4,7 @@ import "@goauthentik/app/elements/rbac/ObjectPermissionsPage";
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import { convertToSlug } from "@goauthentik/common/utils";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/components/events/ObjectChangelog";
|
||||
import MDCaddyStandalone from "@goauthentik/docs/providers/proxy/_caddy_standalone.md";
|
||||
import MDNginxIngress from "@goauthentik/docs/providers/proxy/_nginx_ingress.md";
|
||||
|
@ -15,7 +16,6 @@ import MDTraefikStandalone from "@goauthentik/docs/providers/proxy/_traefik_stan
|
|||
import MDHeaderAuthentication from "@goauthentik/docs/providers/proxy/header_authentication.md";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/CodeMirror";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/elements/Markdown";
|
||||
import "@goauthentik/elements/Markdown";
|
||||
import { Replacer } from "@goauthentik/elements/Markdown";
|
||||
|
@ -330,15 +330,10 @@ export class ProxyProviderViewPage extends AKElement {
|
|||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">
|
||||
<ak-label
|
||||
color=${this.provider.basicAuthEnabled
|
||||
? PFColor.Green
|
||||
: PFColor.Grey}
|
||||
>
|
||||
${this.provider.basicAuthEnabled
|
||||
? msg("Yes")
|
||||
: msg("No")}
|
||||
</ak-label>
|
||||
<ak-status-label
|
||||
type="info"
|
||||
?good=${this.provider.basicAuthEnabled}
|
||||
></ak-status-label>
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import "@goauthentik/admin/tenants/TenantForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import "@goauthentik/elements/forms/ModalForm";
|
||||
|
@ -82,9 +83,7 @@ export class TenantListPage extends TablePage<Tenant> {
|
|||
row(item: Tenant): TemplateResult[] {
|
||||
return [
|
||||
html`${item.domain}`,
|
||||
html`<ak-label color=${item._default ? PFColor.Green : PFColor.Red}>
|
||||
${item._default ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-status-label ?good=${item._default}></ak-status-label>`,
|
||||
html`<ak-forms-modal>
|
||||
<span slot="submit"> ${msg("Update")} </span>
|
||||
<span slot="header"> ${msg("Update Tenant")} </span>
|
||||
|
|
|
@ -2,7 +2,7 @@ import "@goauthentik/admin/tokens/TokenForm";
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { intentToLabel } from "@goauthentik/common/labels";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/buttons/Dropdown";
|
||||
import "@goauthentik/elements/buttons/TokenCopyButton";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
|
@ -109,9 +109,7 @@ export class TokenListPage extends TablePage<Token> {
|
|||
? html`<small>${msg("Token is managed by authentik.")}</small>`
|
||||
: html``}`,
|
||||
html`<a href="#/identity/users/${item.userObj?.pk}">${item.userObj?.username}</a>`,
|
||||
html` <ak-label color=${item.expiring ? PFColor.Green : PFColor.Orange}>
|
||||
${item.expiring ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-status-label type="warning" ?good=${item.expiring}></ak-status-label>`,
|
||||
html`${item.expiring ? item.expires?.toLocaleString() : msg("-")}`,
|
||||
html`${intentToLabel(item.intent ?? IntentEnum.Api)}`,
|
||||
html`
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
||||
import { TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
@ -54,9 +54,7 @@ export class GroupSelectModal extends TableModal<Group> {
|
|||
html`<div>
|
||||
<div>${item.name}</div>
|
||||
</div>`,
|
||||
html` <ak-label color=${item.isSuperuser ? PFColor.Green : PFColor.Grey}>
|
||||
${item.isSuperuser ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html` <ak-status-label type="info" ?good=${item.isSuperuser}></ak-status-label>`,
|
||||
html`${(item.users || []).length}`,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ export class UserDeviceTable extends Table<Device> {
|
|||
@property({ type: Number })
|
||||
userId?: number;
|
||||
|
||||
checkbox = true;
|
||||
|
||||
async apiEndpoint(): Promise<PaginatedResponse<Device>> {
|
||||
return new AuthenticatorsApi(DEFAULT_CONFIG)
|
||||
.authenticatorsAdminAllList({
|
||||
|
@ -64,6 +66,21 @@ export class UserDeviceTable extends Table<Device> {
|
|||
}
|
||||
}
|
||||
|
||||
renderToolbarSelected(): TemplateResult {
|
||||
const disabled = this.selectedElements.length < 1;
|
||||
return html`<ak-forms-delete-bulk
|
||||
objectLabel=${msg("Device(s)")}
|
||||
.objects=${this.selectedElements}
|
||||
.delete=${(item: Device) => {
|
||||
return this.deleteWrapper(item);
|
||||
}}
|
||||
>
|
||||
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
|
||||
${msg("Delete")}
|
||||
</button>
|
||||
</ak-forms-delete-bulk>`;
|
||||
}
|
||||
|
||||
renderToolbar(): TemplateResult {
|
||||
return html` <ak-spinner-button
|
||||
.callAction=${() => {
|
||||
|
|
|
@ -10,8 +10,8 @@ import { userTypeToLabel } from "@goauthentik/common/labels";
|
|||
import { MessageLevel } from "@goauthentik/common/messages";
|
||||
import { DefaultUIConfig, uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { first } from "@goauthentik/common/utils";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import { rootInterface } from "@goauthentik/elements/Base";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import { PFSize } from "@goauthentik/elements/Spinner";
|
||||
import "@goauthentik/elements/TreeView";
|
||||
import "@goauthentik/elements/buttons/ActionButton";
|
||||
|
@ -251,9 +251,7 @@ export class UserListPage extends TablePage<User> {
|
|||
<div>${item.username}</div>
|
||||
<small>${item.name === "" ? msg("<No name set>") : item.name}</small> </a
|
||||
> <small>${userTypeToLabel(item.type)}</small>`,
|
||||
html`<ak-label color=${item.isActive ? PFColor.Green : PFColor.Red}>
|
||||
${item.isActive ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-status-label ?good=${item.isActive}></ak-status-label>`,
|
||||
html`${first(item.lastLogin?.toLocaleString(), msg("-"))}`,
|
||||
html`<ak-forms-modal>
|
||||
<span slot="submit"> ${msg("Update")} </span>
|
||||
|
|
|
@ -14,11 +14,11 @@ import "@goauthentik/app/elements/rbac/ObjectPermissionsPage";
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import { userTypeToLabel } from "@goauthentik/common/labels";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/components/events/ObjectChangelog";
|
||||
import "@goauthentik/components/events/UserEvents";
|
||||
import { AKElement, rootInterface } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/CodeMirror";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/elements/PageHeader";
|
||||
import { PFSize } from "@goauthentik/elements/Spinner";
|
||||
import "@goauthentik/elements/Tabs";
|
||||
|
@ -185,9 +185,10 @@ export class UserViewPage extends AKElement {
|
|||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">
|
||||
<ak-label
|
||||
color=${user.isActive ? PFColor.Green : PFColor.Orange}
|
||||
></ak-label>
|
||||
<ak-status-label
|
||||
type="warning"
|
||||
?good=${user.isActive}
|
||||
></ak-status-label>
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
|
@ -207,9 +208,10 @@ export class UserViewPage extends AKElement {
|
|||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">
|
||||
<ak-label
|
||||
color=${user.isSuperuser ? PFColor.Green : PFColor.Orange}
|
||||
></ak-label>
|
||||
<ak-status-label
|
||||
type="warning"
|
||||
?good=${user.isSuperuser}
|
||||
></ak-status-label>
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
|
|||
export const ERROR_CLASS = "pf-m-danger";
|
||||
export const PROGRESS_CLASS = "pf-m-in-progress";
|
||||
export const CURRENT_CLASS = "pf-m-current";
|
||||
export const VERSION = "2023.10.3";
|
||||
export const VERSION = "2023.10.4";
|
||||
export const TITLE_DEFAULT = "authentik";
|
||||
export const ROUTE_SEPARATOR = ";";
|
||||
|
||||
|
|
116
web/src/components/ak-status-label.ts
Normal file
116
web/src/components/ak-status-label.ts
Normal file
|
@ -0,0 +1,116 @@
|
|||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { css, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { classMap } from "lit/directives/class-map.js";
|
||||
|
||||
import PFLabel from "@patternfly/patternfly/components/Label/label.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
const statusNames = ["error", "warning", "info"] as const;
|
||||
type StatusName = (typeof statusNames)[number];
|
||||
|
||||
const statusToDetails = new Map<StatusName, [string, string]>([
|
||||
["error", ["pf-m-red", "fa-times"]],
|
||||
["warning", ["pf-m-orange", "fa-exclamation-triangle"]],
|
||||
["info", ["pf-m-gray", "fa-info-circle"]],
|
||||
]);
|
||||
|
||||
const styles = css`
|
||||
:host {
|
||||
--pf-c-label--m-gray--BackgroundColor: var(--pf-global--palette--black-100);
|
||||
--pf-c-label--m-gray__icon--Color: var(--pf-global--primary-color--100);
|
||||
--pf-c-label--m-gray__content--Color: var(--pf-global--info-color--200);
|
||||
--pf-c-label--m-gray__content--before--BorderColor: var(--pf-global--palette--black-400);
|
||||
--pf-c-label--m-gray__content--link--hover--before--BorderColor: var(
|
||||
--pf-global--primary-color--100
|
||||
);
|
||||
--pf-c-label--m-gray__content--link--focus--before--BorderColor: var(
|
||||
--pf-global--primary-color--100
|
||||
);
|
||||
}
|
||||
|
||||
.pf-c-label.pf-m-gray {
|
||||
--pf-c-label--BackgroundColor: var(--pf-c-label--m-gray--BackgroundColor);
|
||||
--pf-c-label__icon--Color: var(--pf-c-label--m-gray__icon--Color);
|
||||
--pf-c-label__content--Color: var(--pf-c-label--m-gray__content--Color);
|
||||
--pf-c-label__content--before--BorderColor: var(
|
||||
--pf-c-label--m-gray__content--before--BorderColor
|
||||
);
|
||||
--pf-c-label__content--link--hover--before--BorderColor: var(
|
||||
--pf-c-label--m-gray__content--link--hover--before--BorderColor
|
||||
);
|
||||
--pf-c-label__content--link--focus--before--BorderColor: var(
|
||||
--pf-c-label--m-gray__content--link--focus--before--BorderColor
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* A boolean status indicator
|
||||
*
|
||||
* Based on the Patternfly "label" pattern, this component exists to display "Yes" or "No", but this
|
||||
* is configurable.
|
||||
*
|
||||
* When the boolean attribute `good` is present, the background will be green and the icon will be a
|
||||
* ✓. If the `good` attribute is not present, the background will be a warning color and an
|
||||
* alternative symbol. Which color and symbol depends on the `type` of the negative status we want
|
||||
* to show:
|
||||
*
|
||||
* - type="error" (default): A Red ✖
|
||||
* - type="warning" An orange ⚠
|
||||
* - type="info" A grey ⓘ
|
||||
*
|
||||
* By default, the messages for "good" and "other" are "Yes" and "No" respectively, but these can be
|
||||
* customized with the attributes `good-label` and `bad-label`.
|
||||
*/
|
||||
|
||||
@customElement("ak-status-label")
|
||||
export class AkStatusLabel extends AKElement {
|
||||
static get styles() {
|
||||
return [PFBase, PFLabel, styles];
|
||||
}
|
||||
|
||||
@property({ type: Boolean })
|
||||
good = false;
|
||||
|
||||
@property({ type: String, attribute: "good-label" })
|
||||
goodLabel = msg("Yes");
|
||||
|
||||
@property({ type: String, attribute: "bad-label" })
|
||||
badLabel = msg("No");
|
||||
|
||||
@property({ type: Boolean })
|
||||
compact = false;
|
||||
|
||||
@property({ type: String })
|
||||
type: StatusName = "error";
|
||||
|
||||
render() {
|
||||
const details = statusToDetails.get(this.type);
|
||||
if (!details) {
|
||||
throw new Error(`Bad status type [${this.type}] passed to ak-status-label`);
|
||||
}
|
||||
|
||||
const [label, color, icon] = this.good
|
||||
? [this.goodLabel, "pf-m-green", "fa-check"]
|
||||
: [this.badLabel, ...details];
|
||||
|
||||
const classes = {
|
||||
"pf-c-label": true,
|
||||
[color]: true,
|
||||
"pf-m-compact": this.compact,
|
||||
};
|
||||
|
||||
return html`<span class="${classMap(classes)}">
|
||||
<span class="pf-c-label__content">
|
||||
<span class="pf-c-label__icon">
|
||||
<i class="fas fa-fw ${icon}" aria-hidden="true"></i> </span
|
||||
>${label}
|
||||
</span>
|
||||
</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
export default AkStatusLabel;
|
101
web/src/components/stories/ak-status-label.stories.ts
Normal file
101
web/src/components/stories/ak-status-label.stories.ts
Normal file
|
@ -0,0 +1,101 @@
|
|||
import "@goauthentik/elements/messages/MessageContainer";
|
||||
import { Meta } from "@storybook/web-components";
|
||||
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
||||
import "../ak-status-label";
|
||||
import AkStatusLabel from "../ak-status-label";
|
||||
|
||||
const metadata: Meta<AkStatusLabel> = {
|
||||
title: "Components / App Status Label",
|
||||
component: "ak-status-label",
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: "A status label display",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default metadata;
|
||||
|
||||
const container = (testItem: TemplateResult) =>
|
||||
html` <div style="background: #fff; padding: 2em">
|
||||
<style>
|
||||
dl {
|
||||
display: grid;
|
||||
grid-template-columns: 22ch 1fr;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
${testItem}
|
||||
</div>`;
|
||||
|
||||
export const AppIcon = () => {
|
||||
// prettier-ignore
|
||||
return container(html`
|
||||
<dl>
|
||||
<dt>Good</dt><dd>
|
||||
|
||||
<ak-status-label good></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Bad (Default)</dt><dd>
|
||||
|
||||
<ak-status-label></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Programmatically Good</dt><dd>
|
||||
|
||||
<ak-status-label ?good=${true}></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Programmatically Bad</dt><dd>
|
||||
|
||||
<ak-status-label ?good=${false}></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Good Warning</dt><dd>
|
||||
|
||||
<ak-status-label type="warning" good></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Bad Warning</dt><dd>
|
||||
|
||||
<ak-status-label type="warning"></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Good Info</dt><dd>
|
||||
|
||||
<ak-status-label type="info" good></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Bad Info</dt><dd>
|
||||
|
||||
<ak-status-label type="info"></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Good With Alternative Message</dt><dd>
|
||||
|
||||
<ak-status-label good good-label="Hurray!" bad-label="Boo!"></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Bad with Alternative Message</dt><dd>
|
||||
|
||||
<ak-status-label good-label="Hurray!" bad-label="Boo!"></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Good, Compact</dt><dd>
|
||||
|
||||
<ak-status-label good compact></ak-status-label>
|
||||
|
||||
</dd>
|
||||
<dt>Bad, Compact</dt><dd>
|
||||
|
||||
<ak-status-label compact></ak-status-label>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
`);
|
||||
};
|
|
@ -6,19 +6,20 @@ import { customElement, property } from "lit/decorators.js";
|
|||
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import { ErrorDetail } from "@goauthentik/api";
|
||||
|
||||
/**
|
||||
* This is used in two places outside of Flow, and in both cases is used primarily to
|
||||
* display content, not take input. It displays the TOPT QR code, and the static
|
||||
* display content, not take input. It displays the TOTP QR code, and the static
|
||||
* recovery tokens. But it's used a lot in Flow.
|
||||
*/
|
||||
|
||||
@customElement("ak-form-element")
|
||||
export class FormElement extends AKElement {
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFForm, PFFormControl];
|
||||
return [PFBase, PFForm, PFFormControl];
|
||||
}
|
||||
|
||||
@property()
|
||||
|
@ -28,7 +29,16 @@ export class FormElement extends AKElement {
|
|||
required = false;
|
||||
|
||||
@property({ attribute: false })
|
||||
errors?: ErrorDetail[];
|
||||
set errors(value: ErrorDetail[] | undefined) {
|
||||
this._errors = value;
|
||||
const hasError = (value || []).length > 0;
|
||||
this.querySelectorAll("input").forEach((input) => {
|
||||
input.setAttribute("aria-invalid", hasError.toString());
|
||||
});
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
_errors?: ErrorDetail[];
|
||||
|
||||
updated(): void {
|
||||
this.querySelectorAll<HTMLInputElement>("input[autofocus]").forEach((input) => {
|
||||
|
@ -45,8 +55,12 @@ export class FormElement extends AKElement {
|
|||
: html``}
|
||||
</label>
|
||||
<slot></slot>
|
||||
${(this.errors || []).map((error) => {
|
||||
return html`<p class="pf-c-form__helper-text pf-m-error">${error.string}</p>`;
|
||||
${(this._errors || []).map((error) => {
|
||||
return html`<p class="pf-c-form__helper-text pf-m-error">
|
||||
<span class="pf-c-form__helper-text-icon">
|
||||
<i class="fas fa-exclamation-circle" aria-hidden="true"></i> </span
|
||||
>${error.string}
|
||||
</p>`;
|
||||
})}
|
||||
</div>`;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
||||
import { Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
@ -85,9 +85,7 @@ export class UserOAuthRefreshList extends Table<TokenModel> {
|
|||
row(item: TokenModel): TemplateResult[] {
|
||||
return [
|
||||
html`<a href="#/core/providers/${item.provider?.pk}"> ${item.provider?.name} </a>`,
|
||||
html`<ak-label color=${item.revoked ? PFColor.Orange : PFColor.Green}>
|
||||
${item.revoked ? msg("Yes") : msg("No")}
|
||||
</ak-label>`,
|
||||
html`<ak-status-label type="warning" ?good=${item.revoked}></ak-status-label>`,
|
||||
html`${item.expires?.toLocaleString()}`,
|
||||
html`${item.scope.join(", ")}`,
|
||||
];
|
||||
|
|
|
@ -28,6 +28,11 @@ export class PasswordStage extends BaseStage<PasswordChallenge, PasswordChalleng
|
|||
|
||||
timer?: number;
|
||||
|
||||
hasError(field: string): boolean {
|
||||
const errors = (this.challenge?.responseErrors || {})[field];
|
||||
return (errors || []).length > 0;
|
||||
}
|
||||
|
||||
renderInput(): HTMLInputElement {
|
||||
this.input = document.createElement("input");
|
||||
this.input.type = "password";
|
||||
|
@ -38,6 +43,7 @@ export class PasswordStage extends BaseStage<PasswordChallenge, PasswordChalleng
|
|||
this.input.classList.add("pf-c-form-control");
|
||||
this.input.required = true;
|
||||
this.input.value = PasswordManagerPrefill.password || "";
|
||||
this.input.setAttribute("aria-invalid", this.hasError("password").toString());
|
||||
// This is somewhat of a crude way to get autofocus, but in most cases the `autofocus` attribute
|
||||
// isn't enough, due to timing within shadow doms and such.
|
||||
this.timer = window.setInterval(() => {
|
||||
|
|
|
@ -2,7 +2,7 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
|||
import { intentToLabel } from "@goauthentik/common/labels";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { me } from "@goauthentik/common/users";
|
||||
import { PFColor } from "@goauthentik/elements/Label";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/elements/buttons/Dropdown";
|
||||
import "@goauthentik/elements/buttons/ModalButton";
|
||||
import "@goauthentik/elements/buttons/TokenCopyButton";
|
||||
|
@ -97,9 +97,7 @@ export class UserTokenList extends Table<Token> {
|
|||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">
|
||||
<ak-label color=${item.expiring ? PFColor.Green : PFColor.Red}>
|
||||
${item.expiring ? msg("Yes") : msg("No")}
|
||||
</ak-label>
|
||||
<ak-status-label ?good=${item.expiring}></ak-status-label>
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
|
|
|
@ -7953,30 +7953,39 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
|
|||
</trans-unit>
|
||||
<trans-unit id="sd94e99af8b41ff54">
|
||||
<source>0: Too guessable: risky password. (guesses &lt; 10^3)</source>
|
||||
<target>0: Trop prévisible: mot de passe risqué. (essais &lt; 10^3)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc926385d1a624c3a">
|
||||
<source>1: Very guessable: protection from throttled online attacks. (guesses &lt; 10^6)</source>
|
||||
<target>1: Très prévisible: protection contre les attaques en ligne limitées. (essais &lt; 10^6)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8aae61c41319602c">
|
||||
<source>2: Somewhat guessable: protection from unthrottled online attacks. (guesses &lt; 10^8)</source>
|
||||
<target>2: Quelque peu prévisible: protection contre les attaques en ligne non limitées. (essais &lt; 10^8)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc1f4b57e722a89d6">
|
||||
<source>3: Safely unguessable: moderate protection from offline slow-hash scenario. (guesses &lt; 10^10)</source>
|
||||
<target>3: Sûrement imprévisible: protection modérée contre les attaques de hash-lent hors ligne. (essais &lt; 10^10)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd47f3d3c9741343d">
|
||||
<source>4: Very unguessable: strong protection from offline slow-hash scenario. (guesses &gt;= 10^10)</source>
|
||||
<target>4: Très imprévisible: forte protection control les attaques de hash-lent hors ligne. (essais &gt;= 10^10)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s3d2a8b86a4f5a810">
|
||||
<source>Successfully created user and added to group <x id="0" equiv-text="${this.group.name}"/></source>
|
||||
<target>Utilisateur créé et ajouté au groupe <x id="0" equiv-text="${this.group.name}"/> avec succès</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s824e0943a7104668">
|
||||
<source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source>
|
||||
<target>Cet utilisateur sera ajouté au groupe &quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&quot;.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s62e7f6ed7d9cb3ca">
|
||||
<source>Pretend user exists</source>
|
||||
<target>Faire comme si l'utilisateur existe</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s52bdc80690a9a8dc">
|
||||
<source>When enabled, the stage will always accept the given user identifier and continue.</source>
|
||||
<target>Lorsqu'activé, l'étape acceptera toujours l'identifiant utilisateur donné et continuera.</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" ?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<?xml version="1.0"?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file target-language="zh-Hans" source-language="en" original="lit-localize-inputs" datatype="plaintext">
|
||||
<body>
|
||||
<trans-unit id="s4caed5b7a7e5d89b">
|
||||
|
@ -613,9 +613,9 @@
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="saa0e2675da69651b">
|
||||
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
|
||||
<target>未找到 URL "
|
||||
<x id="0" equiv-text="${this.url}"/>"。</target>
|
||||
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
|
||||
<target>未找到 URL "
|
||||
<x id="0" equiv-text="${this.url}"/>"。</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s58cd9c2fe836d9c6">
|
||||
|
@ -1057,8 +1057,8 @@
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="sa8384c9c26731f83">
|
||||
<source>To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.</source>
|
||||
<target>要允许任何重定向 URI,请将此值设置为 ".*"。请注意这可能带来的安全影响。</target>
|
||||
<source>To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.</source>
|
||||
<target>要允许任何重定向 URI,请将此值设置为 ".*"。请注意这可能带来的安全影响。</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s55787f4dfcdce52b">
|
||||
|
@ -1799,8 +1799,8 @@
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="sa90b7809586c35ce">
|
||||
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
|
||||
<target>输入完整 URL、相对路径,或者使用 'fa://fa-test' 来使用 Font Awesome 图标 "fa-test"。</target>
|
||||
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
|
||||
<target>输入完整 URL、相对路径,或者使用 'fa://fa-test' 来使用 Font Awesome 图标 "fa-test"。</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s0410779cb47de312">
|
||||
|
@ -2988,8 +2988,8 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s76768bebabb7d543">
|
||||
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
|
||||
<target>包含组成员的字段。请注意,如果使用 "memberUid" 字段,则假定该值包含相对可分辨名称。例如,'memberUid=some-user' 而不是 'memberUid=cn=some-user,ou=groups,...'</target>
|
||||
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
|
||||
<target>包含组成员的字段。请注意,如果使用 "memberUid" 字段,则假定该值包含相对可分辨名称。例如,'memberUid=some-user' 而不是 'memberUid=cn=some-user,ou=groups,...'</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s026555347e589f0e">
|
||||
|
@ -3781,8 +3781,8 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s7b1fba26d245cb1c">
|
||||
<source>When using an external logging solution for archiving, this can be set to "minutes=5".</source>
|
||||
<target>使用外部日志记录解决方案进行存档时,可以将其设置为 "minutes=5"。</target>
|
||||
<source>When using an external logging solution for archiving, this can be set to "minutes=5".</source>
|
||||
<target>使用外部日志记录解决方案进行存档时,可以将其设置为 "minutes=5"。</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s44536d20bb5c8257">
|
||||
|
@ -3791,8 +3791,8 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s3bb51cabb02b997e">
|
||||
<source>Format: "weeks=3;days=2;hours=3,seconds=2".</source>
|
||||
<target>格式:"weeks=3;days=2;hours=3,seconds=2"。</target>
|
||||
<source>Format: "weeks=3;days=2;hours=3,seconds=2".</source>
|
||||
<target>格式:"weeks=3;days=2;hours=3,seconds=2"。</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s04bfd02201db5ab8">
|
||||
|
@ -3988,10 +3988,10 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="sa95a538bfbb86111">
|
||||
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source>
|
||||
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source>
|
||||
<target>您确定要更新
|
||||
<x id="0" equiv-text="${this.objectLabel}"/>"
|
||||
<x id="1" equiv-text="${this.obj?.name}"/>" 吗?</target>
|
||||
<x id="0" equiv-text="${this.objectLabel}"/>"
|
||||
<x id="1" equiv-text="${this.obj?.name}"/>" 吗?</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sc92d7cfb6ee1fec6">
|
||||
|
@ -5077,7 +5077,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="sdf1d8edef27236f0">
|
||||
<source>A "roaming" authenticator, like a YubiKey</source>
|
||||
<source>A "roaming" authenticator, like a YubiKey</source>
|
||||
<target>像 YubiKey 这样的“漫游”身份验证器</target>
|
||||
|
||||
</trans-unit>
|
||||
|
@ -5412,10 +5412,10 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d5f69929bb7221d">
|
||||
<source><x id="0" equiv-text="${prompt.name}"/> ("<x id="1" equiv-text="${prompt.fieldKey}"/>", of type <x id="2" equiv-text="${prompt.type}"/>)</source>
|
||||
<source><x id="0" equiv-text="${prompt.name}"/> ("<x id="1" equiv-text="${prompt.fieldKey}"/>", of type <x id="2" equiv-text="${prompt.type}"/>)</source>
|
||||
<target>
|
||||
<x id="0" equiv-text="${prompt.name}"/>("
|
||||
<x id="1" equiv-text="${prompt.fieldKey}"/>",类型为
|
||||
<x id="0" equiv-text="${prompt.name}"/>("
|
||||
<x id="1" equiv-text="${prompt.fieldKey}"/>",类型为
|
||||
<x id="2" equiv-text="${prompt.type}"/>)</target>
|
||||
|
||||
</trans-unit>
|
||||
|
@ -5464,7 +5464,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
|||
|
||||
</trans-unit>
|
||||
<trans-unit id="s1608b2f94fa0dbd4">
|
||||
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source>
|
||||
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source>
|
||||
<target>如果设置时长大于 0,用户可以选择“保持登录”选项,这将使用户的会话延长此处设置的时间。</target>
|
||||
|
||||
</trans-unit>
|
||||
|
@ -7978,7 +7978,7 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
<target>成功创建用户并添加到组 <x id="0" equiv-text="${this.group.name}"/></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s824e0943a7104668">
|
||||
<source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source>
|
||||
<source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source>
|
||||
<target>此用户将会被添加到组 &quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&quot;。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s62e7f6ed7d9cb3ca">
|
||||
|
@ -7991,4 +7991,4 @@ Bindings to groups/users are checked against the user of the event.</source>
|
|||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
</xliff>
|
||||
|
|
4026
web/xliff/zh_TW.xlf
4026
web/xliff/zh_TW.xlf
File diff suppressed because it is too large
Load diff
BIN
website/blog/2023-11-22-building-an-oss-security-stack/icon.png
Normal file
BIN
website/blog/2023-11-22-building-an-oss-security-stack/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
152
website/blog/2023-11-22-building-an-oss-security-stack/item.md
Normal file
152
website/blog/2023-11-22-building-an-oss-security-stack/item.md
Normal file
|
@ -0,0 +1,152 @@
|
|||
---
|
||||
title: Building an OSS security stack with Loki, Wazuh, and CodeQL to save $100k
|
||||
description: “You don’t have to spend a lot developing a good security posture from the beginning. Here’s how we built Authentik Security’s stack with mostly free and open source tools.”
|
||||
slug: 2023-11-22-how-we-saved-over-100k
|
||||
authors:
|
||||
- name: authentik Security Team
|
||||
url: https://goauthentik.io
|
||||
image_url: ./icon.png
|
||||
tags:
|
||||
- authentik
|
||||
- FOSS
|
||||
- security budget
|
||||
- security stack
|
||||
- Red Team
|
||||
- Blue Team
|
||||
- SBOM
|
||||
- hardening
|
||||
- penetration testing
|
||||
- monitoring
|
||||
- SSO
|
||||
- insider threats
|
||||
- certifications
|
||||
- security
|
||||
- identity provider
|
||||
- authentication
|
||||
hide_table_of_contents: false
|
||||
---
|
||||
|
||||
> **_authentik is an open source Identity Provider that unifies your identity needs into a single platform, replacing Okta, Active Directory, and auth0. Authentik Security is a [public benefit company](https://github.com/OpenCoreVentures/ocv-public-benefit-company/blob/main/ocv-public-benefit-company-charter.md) building on top of the open source project._**
|
||||
|
||||
---
|
||||
|
||||
There was an article recently about nearly 20 well-known startups’ first 10 hires—security engineers didn’t feature at all. Our third hire at Authentik Security was a security engineer so we might be biased, but even startups without the resources for a full-time security hire should have someone on your founding team wearing the security hat, so you get started on the right foot.
|
||||
|
||||
As security departments are cost centers (not revenue generators) it’s not unusual for startups to take a tightwad mentality with security. The good news is that you don’t need a big budget to have a good security posture. There are plenty of free and open source tools at your disposal, and a lot of what makes good security is actually organizational practices—many of which don’t cost a thing to implement.
|
||||
|
||||
> We estimate that using mostly non-commercial security tools saves us approximately $100,000 annually, and the end-result is a robust stack of security tools and processes.
|
||||
|
||||
Here’s how we built out our security stack and processes using mostly free and open source software (FOSS).
|
||||
|
||||
<!--truncate-->
|
||||
|
||||
## Blue Team efforts
|
||||
|
||||
Security efforts can mostly be grouped into two categories: Blue Team and Red Team. Your Blue Team is defensive, meaning guarding against potential attacks. The Red Team is offensive, actively seeking for weaknesses and potential vulnerabilities. Startups with scant resources should focus on Blue activities first.
|
||||
|
||||
### Visibility: Do you know what is happening in your environment?
|
||||
|
||||
The first step is to get eyes into your environment through SIEM (Security Information Event Monitoring). A security person’s worst nightmare is things happening without them knowing about it. You can’t react to an attack that you don’t know is happening! You need a tool that monitors your team’s device logs and flags suspicious activity.
|
||||
|
||||
We’re an all-remote and globally distributed team, which makes monitoring both harder and more important; team members can log in from anywhere, at any time, and we don’t have a central headquarters to house a secure server for backups, for example. We needed something that’s available worldwide and compatible with our endpoint device architectures, cloud infrastructure, and SaaS solutions.
|
||||
|
||||
We settled on [Wazuh](https://wazuh.com/platform/siem/), which has been around for a long time, is open source and well supported. We’ll acknowledge that it is a bit harder to deploy than some other, proprietary solutions. This can often be the case with FOSS, and it’s a tradeoff you have to accept when you’re not paying for something.
|
||||
|
||||
If you don’t want to use something that’s tricky to stand up, you can of course pay for a tool with which you’ll get customer support and all those good things. Your first priority should be picking something that fits your company’s needs.
|
||||
|
||||
We also use Grafana’s [Loki](https://grafana.com/oss/loki/) (which is free for self-hosted environments) for certain types of log aggregation. Logging is still a staple for security awareness, so do your research for the best logging and analysis solution.
|
||||
|
||||
The general idea behind having good visibility is to gather as many data points as possible while minimizing ongoing maintenance overhead. Make no mistake, this step is not only crucial, but never-ending. Companies are always standing up and tearing down infrastructure, on- and off-boarding employees, etc. Without visibility and monitoring of these activities, it’s easy to leave something exposed to opportunistic attackers.
|
||||
|
||||
### Understand your dependencies: SBOMs for the win
|
||||
|
||||
If you’re a small, early-stage startup, you’re more likely to get caught in a large-scale, net-casting campaign than in any sophisticated, targeted attacks. That means it’s critical to have awareness of your dependencies, so you can quickly understand if a critical vulnerability affects any part of your software supply chain. When the [Log4Shell vulnerability](https://theconversation.com/what-is-log4j-a-cybersecurity-expert-explains-the-latest-internet-vulnerability-how-bad-it-is-and-whats-at-stake-173896) surfaced in December 2021, the companies that were aware of their dependencies were able to mitigate quickly and close the attack window.
|
||||
|
||||
This is where a Software Bill of Materials (SBOM) comes in handy. Your SBOM isn’t just a checkbox exercise for auditing and compliance requirements. We use OWASP’s [Dependency Track](https://dependencytrack.org/) (also free and open source) to ingest our SBOM and help identify parts of the codebase that may be at risk from new vulnerabilities. We also use [Semgrep](https://semgrep.dev/) for code scanning with pattern-based recognition. It’s open source and free to run locally.
|
||||
|
||||
It’s also worth mentioning that if your company’s product is open source, or you have an open core model (a proprietary product built on open source), you may qualify for access to free tooling from GitHub for your open source project: we use [Dependabot](https://github.com/dependabot) for automated dependency updates and [CodeQL](https://codeql.github.com/) for code analysis to identify vulnerable code.
|
||||
|
||||
### Hardening
|
||||
|
||||
Now that you’ve got visibility into your environment, your next step is hardening: reducing or eliminating potential threats. We can group these efforts into two categories: _organizational security_ and _product security_.
|
||||
|
||||
#### Organizational security
|
||||
|
||||
Raise your hand if you’ve worked at a small startup and have seen the following:
|
||||
|
||||
- Shared credentials
|
||||
- Spreadsheets for IT/People teams to create all logins for new employees on the day they join
|
||||
- Team members introducing new software/tooling at whim
|
||||
|
||||
It can be a free-for-all at small companies, and while the risk is low at that scale, it can be much harder to introduce more rigorous processes later. The team will be resistant because you’ve added friction where there wasn’t before.
|
||||
|
||||
Ideally, you want to introduce secure-by-default practices into your team and company early on:
|
||||
|
||||
- Multi-factor authentication
|
||||
- Single sign on
|
||||
- Just-in-time permissions
|
||||
- Evaluation of new tooling
|
||||
|
||||
In the case of open source software, you can inspect the code to check how data is being handled, how secure the databases are, what exact kind of data is being transferred, saved, etc. Another team best practice is around vetting the tools and dependencies that the team uses; even if you don’t have time or resources to do a full vet of every new piece of software your coworkers want to use, at least check for certifications.
|
||||
|
||||
Here at Authentik Security, we tackle a lot of risk factors with one shot: [authentik](https://goauthentik.io/). By using SSO, we can ensure every new employee has the correct credentials for accessing the appropriate workplace apps, and that every departing employee immediately has access revoked with one click. We can also quarantine suspect users, essentially cutting off access to all systems quickly. Ironically, one of the most common initial access points is ex-employee credentials.
|
||||
|
||||
These all contribute to ‘defense in depth’—adding layers of security and complications to make it as hard or annoying as possible for attackers to get around. These practices typically cost $0 to implement and will set you up for good security posture as you grow.
|
||||
|
||||
#### Product security
|
||||
|
||||
This layer is really anything to do with securing the actual product you’re building (not your company). This typically means getting third-party penetration testing (if you don’t have a dedicated Red Team—more on this below) and remediating vulnerabilities you’ve surfaced through your monitoring and dependency tracking efforts.
|
||||
|
||||
## Red Team efforts
|
||||
|
||||
As we mentioned above, the Red Team is offensive, meaning they attack the company (physically or remotely) to poke holes in your own defenses before the real bad actors can.
|
||||
|
||||
### Internal penetration testing
|
||||
|
||||
Now that we have implemented monitoring, and hardened a few things, it’s time to test how well we did. This is where we take the attacker’s point of view to try to break in and test our own controls over our systems, to expose weaknesses. Just recently we discovered that Authentik had a bunch of domains that we’d left open, unmonitored. It’s a constant, iterative loop of unearthing holes via your internal penetration testing (also called pentesting or white box testing) and finding ways to plug them.
|
||||
|
||||
There are a lot of tools to choose from here (everyone likes breaking into things!). You’re never done choosing your stack—the threat landscape evolves constantly and so does the tooling to keep up with it. You’ll want to pay attention to new developments by keeping an eye on discussions on Twitter, Reddit, Hacker News, etc. When a new way to attack something develops (and it always will), someone will go create the special automation tooling to address that threat. (Then your attackers are going to go grab that tool and see if they can hack their way in. It’s a constant wheel.)
|
||||
|
||||
At Authentik we use the [Kali Linux](https://www.kali.org/) distribution, which has a host of hacking tools on it, for penetration testing. It’s well known within the security world and is open source and free to use.
|
||||
|
||||
Testing can be a tough one for small startups, because you likely won’t have a dedicated Red Team and commercial pentesting doesn’t come cheap. If you can save on your tooling though, that can help to free up resources for contracting out this type of work. The main goal you’re after is trying to identify the low-hanging fruit that inexperienced actors may exploit.
|
||||
|
||||
### A note on insider threats
|
||||
|
||||
[Okta has been in the news](https://goauthentik.io/blog/2023-10-23-another-okta-breach) (again!) after its second major breach in two years. A team member [unknowingly uploaded a file containing sensitive information to Okta’s support management system](https://www.crn.com/news/security/okta-faces-potential-for-reputational-risk-after-second-major-breach-in-two-years-analysts), highlighting the risk of insider threats.
|
||||
|
||||
Your employees are a risk factor—whether through malice, ignorance, or carelessness. It’s not unheard of for someone to accidentally save a password publicly to the company’s cloud. It can be an honest mistake, but it’s very-low hanging fruit for a bad actor just watching your cloud assets.
|
||||
|
||||
With the rise of Ransomware as a Service, there’s also always the possibility that a disgruntled employee can act as an initial access broker: either accidentally or purposefully giving their credentials or their access to someone else. It’s obviously not possible to prevent all possible compromises, so it’s important that your tooling is set up to alert you to unusual activity and your processes are in place so you can react quickly.
|
||||
|
||||
## Do you really need certifications?
|
||||
|
||||
Apart from using security certifications like ISO/IEC 27001 and SOC 2 to evaluate vendors that make the software you are using, certifications can vouch for your organizational security, which might be important to your customers, depending on what your product does and who your customers are.
|
||||
|
||||
For us at Authentik Security, [our source code](https://github.com/goauthentik/authentik) is available for inspection, but that doesn’t tell people anything about how we handle emails, payment information, and so on. That’s where a third-party certification comes in: an auditor verifies your security practices, which in turn signals to your customers that you can be trusted.
|
||||
|
||||
Certifications can be expensive though, and as a cash-strapped startup, you may not want or be able to invest in a certification. However there’s nothing stopping you from ingraining some of those good security practices in your company’s culture anyway. That way, you’re already building a strong security posture and when the time comes, you’re not rushing to implement processes that feel unnatural to the team.
|
||||
|
||||
Again, it comes back to getting off on the right foot so that you’re not spending 10-20x the amount of money later in people time and resources to course correct later.
|
||||
|
||||
## Security doesn’t have to be a big-company luxury
|
||||
|
||||
People imagine that large corporations have security all figured out, but a large security department doesn’t guarantee that they have any idea what other teams are doing. As a small company, you do have one thing going for you: it’s much easier to have eyes on everything that’s happening. You’re more tightly knit and you can encompass more with fewer resources.
|
||||
|
||||
If you talk to a lot of security people, their happy place is when no one is doing anything. Then your job’s pretty easy. Unfortunately, if you want your company to succeed, you need your developers to develop, your salespeople to talk to prospects, your CEO to meet with whomever they need to meet with. These are standard operations that all put the company at risk, but it’s your job to mitigate that risk the best you can.
|
||||
|
||||
Our security engineer likes to say they work alongside teams, not blocking them. If security says it’s their job to make sure there are no vulnerabilities, and it’s the development team’s job to make new features, how do you get these two sides to work together?
|
||||
|
||||
Realistically, everything has vulnerabilities. You’re never going to have a completely safe, locked-down environment. So, you partner with other teams and find a compromise. Establish a minimum threshold people have to meet to keep going. If you’re too inflexible, those teams won’t want to work with you and they won’t tell you when they’re making new virtual machines or writing new code.
|
||||
|
||||
## Repercussions
|
||||
|
||||
You don’t need to be a security company for these things to matter. This advice applies no matter what type of product you’re building.
|
||||
|
||||
[Some 422 million individuals were impacted by data compromises in 2022](https://www.statista.com/statistics/273550/data-breaches-recorded-in-the-united-states-by-number-of-breaches-and-records-exposed/). As consumers we have almost become numb to news of new breaches. A company gets breached, they offer some sort of credit protection, cyber insurance might go up a bit, but life goes on.
|
||||
|
||||
If you’re still not motivated to invest in your security posture (or trying to win over teammates who prioritize feature shipping over everything), consider the [case of SolarWinds](https://www.sec.gov/news/press-release/2023-227). The company appears to have exaggerated their internal security posture, leading to an indictment from the SEC.
|
||||
|
||||
So not only is security important, it could actually keep you out of jail.
|
||||
|
||||
_What’s in your security stack? Let us know in the comments, or send us an email at hello@goauthentik.io!_
|
|
@ -160,7 +160,7 @@ While the prerequisites above must be satisfied prior to having your pull reques
|
|||
|
||||
All Python code is linted with [black](https://black.readthedocs.io/en/stable/), [PyLint](https://www.pylint.org/) and [isort](https://pycqa.github.io/isort/).
|
||||
|
||||
authentik runs on Python 3.11 at the time of writing this.
|
||||
authentik runs on Python 3.12 at the time of writing this.
|
||||
|
||||
- Use native type-annotations wherever possible.
|
||||
- Add meaningful docstrings when possible.
|
||||
|
|
|
@ -4,7 +4,7 @@ title: Full development environment
|
|||
|
||||
## Requirements
|
||||
|
||||
- Python 3.11
|
||||
- Python 3.12
|
||||
- Poetry, which is used to manage dependencies
|
||||
- Go 1.20
|
||||
- Node.js 20
|
||||
|
|
|
@ -140,16 +140,30 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2023.10
|
|||
## Fixed in 2023.10.3
|
||||
|
||||
- ci: explicitly give write permissions to packages (cherry-pick #7428) (#7430)
|
||||
- core: fix worker beat toggle inverted (cherry-pick #7508) (#7509)
|
||||
- events: fix gdpr compliance always running (cherry-pick #7491) (#7505)
|
||||
- providers/oauth2: set auth_via for token and other endpoints (cherry-pick #7417) (#7427)
|
||||
- providers/proxy: fix closed redis client (cherry-pick #7385) (#7429)
|
||||
- root: Improve multi arch Docker image build speed (cherry-pick #7355) (#7426)
|
||||
- sources/oauth: fix patreon (cherry-pick #7454) (#7456)
|
||||
- stages/email: fix duplicate querystring encoding (cherry-pick #7386) (#7425)
|
||||
- web: bugfix: broken backchannel selector (cherry-pick #7480) (#7507)
|
||||
- web/admin: fix html error on oauth2 provider page (cherry-pick #7384) (#7424)
|
||||
- web/flows: attempt to fix bitwareden android compatibility (cherry-pick #7455) (#7457)
|
||||
- events: fix gdpr compliance always running (cherry-pick #7491) (#7505)
|
||||
- Web: bugfix: broken backchannel selector (cherry-pick #7480) (#7507)
|
||||
- core: fix worker beat toggle inverted (cherry-pick #7508) (#7509)
|
||||
|
||||
## Fixed in 2023.10.4
|
||||
|
||||
- ci: fix permissions for release pipeline to publish binaries (cherry-pick #7512) (#7621)
|
||||
- core: bump golang from 1.21.3-bookworm to 1.21.4-bookworm (cherry-pick #7483) (#7622)
|
||||
- events: don't update internal service accounts unless needed (cherry-pick #7611) (#7640)
|
||||
- events: fix missing model\_\* events when not directly authenticated (cherry-pick #7588) (#7597)
|
||||
- events: sanitize functions (cherry-pick #7587) (#7589)
|
||||
- providers/proxy: Fix duplicate cookies when using file system store. (cherry-pick #7541) (#7544)
|
||||
- providers/scim: fix missing schemas attribute for User and Group (cherry-pick #7477) (#7596)
|
||||
- root: specify node and python versions in respective config files, deduplicate in CI (#7620)
|
||||
- security: fix [CVE-2023-48228](../../security/CVE-2023-48228.md), Reported by [@Sapd](https://github.com/Sapd) (#7666)
|
||||
- stages/email: use uuid for email confirmation token instead of username (cherry-pick #7581) (#7584)
|
||||
- web/admin: fix admins not able to delete MFA devices (#7660)
|
||||
|
||||
## API Changes
|
||||
|
||||
|
|
|
@ -157,7 +157,11 @@ image:
|
|||
|
||||
## Fixed in 2023.8.4
|
||||
|
||||
- \*: fix [GHSA-rjvp-29xq-f62w](../security/GHSA-rjvp-29xq-f62w), Reported by [@devSparkle](https://github.com/devSparkle)
|
||||
- security: fix [GHSA-rjvp-29xq-f62w](../security/GHSA-rjvp-29xq-f62w), Reported by [@devSparkle](https://github.com/devSparkle)
|
||||
|
||||
## Fixed in 2023.8.5
|
||||
|
||||
- security: fix [CVE-2023-48228](../../security/CVE-2023-48228.md), Reported by [@Sapd](https://github.com/Sapd) (#7666)
|
||||
|
||||
## API Changes
|
||||
|
||||
|
|
61
website/docs/security/CVE-2023-48228.md
Normal file
61
website/docs/security/CVE-2023-48228.md
Normal file
|
@ -0,0 +1,61 @@
|
|||
# CVE-2023-48228
|
||||
|
||||
_Reported by [@Sapd](https://github.com/Sapd)_
|
||||
|
||||
## OAuth2: Insufficient PKCE check
|
||||
|
||||
### Summary
|
||||
|
||||
When initialising a OAuth2 flow with a `code_challenge` and `code_method` (thus requesting PKCE), the SSO provider (authentik) **must** check if there is a matching **and** existing `code_verifier` during the token step.
|
||||
|
||||
authentik checks if the contents of code*verifier is matching \*\*\_ONLY*\*\* when it is provided. When it is left out completely, authentik simply accepts the token request with out it; even when the flow was started with a `code_challenge`.
|
||||
|
||||
### Patches
|
||||
|
||||
authentik 2023.8.5 and 2023.10.4 fix this issue.
|
||||
|
||||
### Details
|
||||
|
||||
The `code_verifier` is only checked when the user provides it. Note that in line 209 there is a check if the code_parameter is left out. But there is no check if the PKCE parameter simply was omitted WHEN the request was started with a `code_challenge_method`.
|
||||
|
||||
This oversight likely did not stem from a coding error but from a misinterpretation of the RFC, where the backward compatibility section may be somewhat confusing.
|
||||
https://datatracker.ietf.org/doc/html/rfc7636#section-4.5
|
||||
RFC7636 explicitly says in Section 4.5:
|
||||
|
||||
> The "code_challenge_method" is bound to the Authorization Code when
|
||||
> the Authorization Code is issued. That is the method that the token
|
||||
> endpoint MUST use to verify the "code_verifier".
|
||||
|
||||
Section 5, Compatibility
|
||||
|
||||
> Server implementations of this specification MAY accept OAuth2.0
|
||||
> clients that do not implement this extension. If the "code_verifier"
|
||||
> is not received from the client in the Authorization Request, servers
|
||||
> supporting backwards compatibility revert to the OAuth 2.0 [[RFC6749](https://datatracker.ietf.org/doc/html/rfc6749)]
|
||||
> protocol without this extension.
|
||||
|
||||
Section 5, Compatibility, allows server implementations of this specification to accept OAuth 2.0 clients that do not implement this extension. However, if a `code_verifier` is not received from the client in the Authorization Request, servers that support backward compatibility should revert to the standard OAuth 2.0 protocol sans this extension (including all steps).
|
||||
|
||||
It should be noted that this does not mean that the `code_verifier` check can be disregarded at any point if the initial request included `code_challenge` or `code_challenge_method`. Since Authentik supports PKCE, it **MUST** verify the code_verifier as described in Section 4.5 **AND** fail if it was not provided.
|
||||
|
||||
Ofc verification can be skipped if the original authorization request did not invoke PKCE (no `code_challenge_method` and no `code_challenge`).
|
||||
|
||||
Failure to check the `code_verifier` renders the PKCE flow ineffective. This vulnerability particularly endangers public or hybrid clients, as their `code` is deemed non-confidential.
|
||||
|
||||
While not explicitly stated in the standard, it is generally recommended that OAuth2 flows accepting public clients should enforce PKCE - at least when redirecting to a non HTTPS URL (like http or an app link).
|
||||
|
||||
### Impact
|
||||
|
||||
The vulnerability poses a high risk to both public and hybrid clients.
|
||||
When for example a mobile app implements oauth2, a malicious app can simply also register the same in-app-link (e.g. `mycoolapp://oauth2`) for the redirect callback URL, possibly receiving `code` during callback. With PKCE working, a malicious app would still receive a `code` but the `code` would not work without the correct unhashed code-challenge.
|
||||
This is especially problematic, because authentik claims to support PKCE, and a developer can expect that the proper checks are in place. Note that app-links cannot be protected by HTTPS or similar mechanisms.
|
||||
|
||||
Note also that this vulnerability poses a threat to confidential clients. Many confidential clients act as a proxy for OAuth2 API requests, typically from mobile apps or single-page applications. These proxies relay `code_challenge`, `code_challenge_method` (in auth request, which most libraries force and provide on default settings) and `code_verifier` in the token request unchanged and supplement the CLIENT_SECRET which only the relay knows. The relay can but does not have to check for an existing `code_verifier` as the standard does not define that PKCE can be ignored on confidential clients during the token request when the client requested PKCE during the authorization request.
|
||||
|
||||
An attacker could potentially gain full access to the application. If the code grants access to an admin account, the confidentiality, integrity, and availability of that application are compromised.
|
||||
|
||||
### For more information
|
||||
|
||||
If you have any questions or comments about this advisory:
|
||||
|
||||
- Email us at [security@goauthentik.io](mailto:security@goauthentik.io)
|
|
@ -18,7 +18,192 @@ This setup only works, when Nextcloud is running with HTTPS enabled. See [here](
|
|||
In case something goes wrong with the configuration, you can use the URL `http://nextcloud.company/login?direct=1` to log in using the built-in authentication.
|
||||
:::
|
||||
|
||||
## Preparation
|
||||
## Authentication
|
||||
|
||||
There are 2 ways to setup single sign on (SSO) for Nextcloud:
|
||||
|
||||
- [via OIDC Connect (OAuth)](#openid-connect-auth)
|
||||
- [via SAML](#saml-auth)
|
||||
|
||||
### OpenID Connect auth
|
||||
|
||||
#### Preparation
|
||||
|
||||
The following placeholders will be used:
|
||||
|
||||
- `nextcloud.company` is the FQDN of the Nextcloud install.
|
||||
- `authentik.company` is the FQDN of the authentik install.
|
||||
- `authentik.local` is the internal FQDN of the authentik install (only relevant when running authentik and Nextcloud behind a reverse proxy)
|
||||
|
||||
Lets start by thinking what user attributes need to be available in Nextcloud:
|
||||
|
||||
- name
|
||||
- email
|
||||
- unique user ID
|
||||
- storage quota (optional)
|
||||
- groups (optional)
|
||||
|
||||
authentik already provides some default _scopes_ with _claims_ inside them, such as:
|
||||
|
||||
- `email` scope: Has claims `email` and `email_verified`
|
||||
- `profile` scope: Has claims `name`, `given_name`, `preferred_username`, `nickname`, `groups`
|
||||
- `openid` scope: This is a default scope required by the OpenID spec. It contains no claims
|
||||
|
||||
##### Custom profile scope
|
||||
|
||||
If you do not need storage quota or group information in Nextcloud [skip to the next step](#provider-and-application).
|
||||
|
||||
However, if you want to be able to control how much storage users in Nextcloud can use, as well as which users are recognized as Nextcloud administrators, you would need to make this information available in Nextcloud. To achieve this you would need to create a custom `profile` scope. To do so, go to _Customisation_ -> _Property mappings_. Create a _Scope mapping_ with the following parameters:
|
||||
|
||||
- Name: Nextcloud Profile
|
||||
- Scope name: profile
|
||||
- Expression:
|
||||
|
||||
```python
|
||||
# Extract all groups the user is a member of
|
||||
groups = [group.name for group in user.ak_groups.all()]
|
||||
|
||||
# Nextcloud admins must be members of a group called "admin".
|
||||
# This is static and cannot be changed.
|
||||
# We append a fictional "admin" group to the user's groups if they are an admin in authentik.
|
||||
# This group would only be visible in Nextcloud and does not exist in authentik.
|
||||
if user.is_superuser and "admin" not in groups:
|
||||
groups.append("admin")
|
||||
|
||||
return {
|
||||
"name": request.user.name,
|
||||
"groups": groups,
|
||||
# To set a quota set the "nextcloud_quota" property in the user's attributes
|
||||
"quota": user.group_attributes().get("nextcloud_quota", None)
|
||||
}
|
||||
```
|
||||
|
||||
:::note
|
||||
To set a quota set the "nextcloud_quota" property in the user's attributes. This can be set for individual users or a group of users, as long as the target user is a member of a group which has this attribute set.
|
||||
|
||||
If set to a value, for example `1 GB`, user(s) will have 1GB storage quota. If the attribute is not set, user(s) will have unlimited storage.
|
||||
:::
|
||||
|
||||
##### Provider and Application
|
||||
|
||||
Create a provider for Nextcloud. In the Admin Interface, go to _Applications_ -> _Providers_. Create an _OAuth2/OpenID Provider_ with the following parameters:
|
||||
|
||||
- Name: Nextcloud
|
||||
- Client type: Confidential
|
||||
- Redirect URIs/Origins (RegEx): `https://nextcloud.company/apps/user_oidc/code`
|
||||
- Signing key: Any valid certificate
|
||||
- Under advanced settings:
|
||||
- Scopes:
|
||||
- `authentik default Oauth Mapping email`
|
||||
- `Nextcloud Profile` (or `authentik default Oauth Mapping profile` if you skipped the [custom profile scope](#custom-profile-scope) section)
|
||||
- Subject mode: Based on the User's UUID
|
||||
:::danger
|
||||
Nextcloud will use the UUID as username. However, mapping the subject mode to authentik usernames is **not recommended** due to their mutable nature. This can lead to security issues such as user impersonation. If you still wish to map the subject mode to an username, [disable username changing](../../../docs/installation/configuration#authentik_default_user_change_username) in authentik and set this to `Based on the User's username`.
|
||||
:::
|
||||
- Include claims in ID token: ✔️
|
||||
|
||||
Before continuing, make sure to take note of your `client ID` and `secret ID`. Don't worry you can go back to see/change them at any time.
|
||||
|
||||
:::warning
|
||||
Currently there is a bug in the Nextcloud OIDC app, that is [limiting the size of the secret ID](https://github.com/nextcloud/user_oidc/issues/405) token to 64 characters. Since authentik uses 128 characters for a secret ID by default, you will need to trim it down to 64 characters in order to be able to set it in Nextcloud. Don't worry, 64 characters is still sufficiently long and should not compromise security.
|
||||
:::
|
||||
|
||||
:::note
|
||||
Depending on your Nextcloud configuration, you might need to use `https://nextcloud.company/index.php/` instead of `https://nextcloud.company/`
|
||||
:::
|
||||
|
||||
After the provider is created, link it to an app. Go to _Applications_ -> _Applications_. Create an application and choose the provider you just created. Make sure to take note of the _application slug_. You will need this later.
|
||||
|
||||
#### Nextcloud
|
||||
|
||||
In Nextcloud, ensure that the `OpenID Connect user backend` app is installed. Navigate to `Settings`, then `OpenID Connect`.
|
||||
|
||||
Add a new provider using the `+` button and set the following values:
|
||||
|
||||
- Identifier: Authentik
|
||||
- Client ID: The client ID from the provider
|
||||
- Client secret: The secret ID from the provider
|
||||
- Discovery endpoint: `https://authentik.company/application/o/<nextcloud-app-slug>/.well-known/openid-configuration`
|
||||
:::tip
|
||||
If you are running both your authentik and Nextcloud instances behind a reverse proxy, you can go ahead and use your internal FQDN here (i.e. `http://authentik.local`, however, note that if you do so there is [extra configuration required](#extra-configuration-when-running-behind-a-reverse-proxy)).
|
||||
:::
|
||||
- Scope: `email`, `profile` (you can safely omit `openid` if you prefer)
|
||||
- Attribute mappings:
|
||||
- User ID mapping: sub
|
||||
- Display name mapping: name
|
||||
- Email mapping: email
|
||||
- Quota mapping: quota (leave empty if you have skipped the [custom profile scope](#custom-profile-scope) section)
|
||||
- Groups mapping: group (leave empty if you have skipped the [custom profile scope](#custom-profile-scope) section)
|
||||
:::tip
|
||||
You need to enable the "Use group provisioning" checkmark to be able to write to this field
|
||||
:::
|
||||
- Use unique user ID: If you only have one provider you can uncheck this if you prefer.
|
||||
|
||||
At this stage you should be able to login with SSO.
|
||||
|
||||
##### Making the OIDC provider the default login method
|
||||
|
||||
If you intend to only login to Nextcloud using your freshly configured authentik provider, you may wish to make it the default login method. This will allow your users to be automatically redirected to authentik when they attempt to access your Nextcloud instance, as opposed to having to manually click on "Log in with Authentik" every time they wish to login.
|
||||
|
||||
To achieve this, you will need to use the `occ` command of your Nextcloud instance:
|
||||
|
||||
```bash
|
||||
sudo -u www-data php var/www/nextcloud/occ config:app:set --value=0 user_oidc allow_multiple_user_backends
|
||||
```
|
||||
|
||||
##### Extra configuration when running behind a reverse proxy
|
||||
|
||||
The OpendID Connect discovery endpoint is queried by Nextcloud and contains a list of endpoints for use by both the relying party (Nextcloud) and the authenticating user.
|
||||
|
||||
:::note
|
||||
If you are configuring an insecure (http) discovery endpoint, Nextcloud will, by default, refuse to connect to it. To change this behaviour, you must add `allow_local_remote_servers => true` to your `config.php`
|
||||
:::
|
||||
|
||||
:::note
|
||||
It is currently not possible force Nextcloud to connect to an https endpoint which uses an untrusted (selfsigned) certificate. If this is the case with your setup, you can do one of 3 things:
|
||||
|
||||
- switch to using a trusted certificate
|
||||
- add the selfsigned certificate to Nextcloud's trust store
|
||||
- switch to using an http endpoint and add `allow_local_remote_servers => true` to your `config.php`
|
||||
|
||||
:::
|
||||
|
||||
Because authentik has no knowledge of where each endpoint is/can be accessed from, it will always return endpoints with domain names matching the one used to make the discovery endpoint request.
|
||||
|
||||
For example, if your Nextcloud instance queries the discovery endpoint using an internal domain name (`authentik.local`), all returned endpoints will have the same domain name. In this case:
|
||||
|
||||
- `http://authentik.local/application/o/<app-slug>/`
|
||||
- `http://authentik.local/application/o/authorize/`
|
||||
- `http://authentik.local/application/o/token/`
|
||||
- `http://authentik.local/application/o/userinfo/`
|
||||
- `http://authentik.local/application/o/<app-slug>/end-session/`
|
||||
- `http://authentik.local/application/o/introspect/`
|
||||
- `http://authentik.local/application/o/revoke/`
|
||||
- `http://authentik.local/application/o/device/`
|
||||
- `http://authentik.local/application/o/<app-slug>/jwks/`
|
||||
|
||||
This represents a problem, because Nextcloud will attempt to redirect the user to the received `authorization` and `end-session` endpoints during login and logout respectively. When that happens, the user will try to access an internal domain and fail.
|
||||
|
||||
The easiest way to fix this is to modify the redirect response's `Location` header coming back from Nextcloud during login and logout. Different proxies have different ways of achieving this. For example with Traefik, a 3rd party plugin called [Rewrite Header](https://plugins.traefik.io/plugins/628c9eb5108ecc83915d7758/rewrite-header) can be used.
|
||||
|
||||
At a minimum, the `authorize` and `end-session` endpoints must be edited in-flight like so:
|
||||
|
||||
- `http://authentik.local/application/o/authorize/` -> `https://authentik.company/application/o/authorize/`
|
||||
- `http://authentik.local/application/o/<app-slug>/end-session/` -> `https://authentik.company/application/o/<app-slug>/end-session/`
|
||||
|
||||
:::note
|
||||
HTTP headers are usually capitalised (e.g. **L**ocation), however, at least some versions of Nextcloud seem to return all lowercase headers (e.g. **l**ocation). To be safe, make sure to add header replacement rules for both cases.
|
||||
:::
|
||||
|
||||
If you prefer, you may also edit the rest of the endpoints, though that should not be necessary, as they should not be accessed by the user.
|
||||
|
||||
:::tip
|
||||
If you do not have any relying parties accessing authentik from the outside, you may also configure your proxy to only allow access to the `authorize` and `end-session` endpoints from the outside world.
|
||||
:::
|
||||
|
||||
### SAML auth
|
||||
|
||||
#### Preparation
|
||||
|
||||
The following placeholders will be used:
|
||||
|
||||
|
@ -40,7 +225,7 @@ Depending on your Nextcloud configuration, you might need to use `https://nextcl
|
|||
|
||||
You can of course use a custom signing certificate, and adjust durations.
|
||||
|
||||
## Nextcloud
|
||||
#### Nextcloud
|
||||
|
||||
In Nextcloud, ensure that the `SSO & SAML Authentication` app is installed. Navigate to `Settings`, then `SSO & SAML Authentication`.
|
||||
|
||||
|
@ -70,7 +255,7 @@ To do this you will need to add the line `'overwriteprotocol' => 'https'` to `co
|
|||
See https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/reverse_proxy_configuration.html#overwrite-parameters for additional information
|
||||
:::
|
||||
|
||||
## Group Quotas
|
||||
#### Group Quotas
|
||||
|
||||
Create a group for each different level of quota you want users to have. Set a custom attribute, for example called `nextcloud_quota`, to the quota you want, for example `15 GB`.
|
||||
|
||||
|
@ -91,7 +276,7 @@ In Nextcloud, go to `Settings`, then `SSO & SAML Authentication`Under `Attribute
|
|||
|
||||
- Attribute to map the quota to.: `nextcloud_quota`
|
||||
|
||||
## Admin Group
|
||||
#### Admin Group
|
||||
|
||||
To give authentik users admin access to your Nextcloud instance, you need to create a custom Property Mapping that maps an authentik group to "admin". It has to be mapped to "admin" as this is static in Nextcloud and cannot be changed.
|
||||
|
||||
|
|
45
website/package-lock.json
generated
45
website/package-lock.json
generated
|
@ -19,23 +19,26 @@
|
|||
"clsx": "^2.0.0",
|
||||
"disqus-react": "^1.1.5",
|
||||
"postcss": "^8.4.31",
|
||||
"prism-react-renderer": "^2.2.0",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"rapidoc": "^9.3.4",
|
||||
"react": "^18.2.0",
|
||||
"react-before-after-slider-component": "^1.1.8",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-toggle": "^4.1.3",
|
||||
"react-tooltip": "^5.23.0",
|
||||
"react-tooltip": "^5.24.0",
|
||||
"remark-github": "^12.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.0.0",
|
||||
"@docusaurus/tsconfig": "3.0.0",
|
||||
"@docusaurus/types": "3.0.0",
|
||||
"@types/react": "^18.2.37",
|
||||
"@types/react": "^18.2.38",
|
||||
"prettier": "3.1.0",
|
||||
"typescript": "~5.2.2"
|
||||
"typescript": "~5.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/autocomplete-core": {
|
||||
|
@ -4127,9 +4130,9 @@
|
|||
"integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.2.37",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.37.tgz",
|
||||
"integrity": "sha512-RGAYMi2bhRgEXT3f4B92WTohopH6bIXw05FuGlmJEnv/omEn190+QYEIYxIAuIBdKgboYYdVved2p1AxZVQnaw==",
|
||||
"version": "18.2.38",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.38.tgz",
|
||||
"integrity": "sha512-cBBXHzuPtQK6wNthuVMV6IjHAFkdl/FOPFIlkd81/Cd1+IqkHu/A+w4g43kaQQoYHik/ruaQBDL72HyCy1vuMw==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
|
@ -13614,25 +13617,17 @@
|
|||
}
|
||||
},
|
||||
"node_modules/prism-react-renderer": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.2.0.tgz",
|
||||
"integrity": "sha512-j4AN0VkEr72598+47xDvpzeYyeh/wPPRNTt9nJFZqIZUxwGKwYqYgt7RVigZ3ZICJWJWN84KEuMKPNyypyhNIw==",
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.3.0.tgz",
|
||||
"integrity": "sha512-UYRg2TkVIaI6tRVHC5OJ4/BxqPUxJkJvq/odLT/ykpt1zGYXooNperUxQcCvi87LyRnR4nCh81ceOA+e7nrydg==",
|
||||
"dependencies": {
|
||||
"@types/prismjs": "^1.26.0",
|
||||
"clsx": "^1.2.1"
|
||||
"clsx": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prism-react-renderer/node_modules/clsx": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/prismjs": {
|
||||
"version": "1.29.0",
|
||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
|
||||
|
@ -14235,9 +14230,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-tooltip": {
|
||||
"version": "5.23.0",
|
||||
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.23.0.tgz",
|
||||
"integrity": "sha512-MYqn6n+Af8NHHDL3zrSqzVSoK2LLqTNFp30CuuHCYlBEf+q88FWfg+8pSO+0GnDvOa5ZaryNDq9sAVQeNhnsgw==",
|
||||
"version": "5.24.0",
|
||||
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.24.0.tgz",
|
||||
"integrity": "sha512-HjstgpOrUwP4eN6mHU4EThpbxVuKO5SvqumRt1aAcPq0ya+pIVVxlwltndtdIIMBJ7w3jnN05vNfcfh2sxE2mQ==",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.0.0",
|
||||
"classnames": "^2.3.0"
|
||||
|
@ -16128,9 +16123,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz",
|
||||
"integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
|
|
@ -26,13 +26,13 @@
|
|||
"clsx": "^2.0.0",
|
||||
"disqus-react": "^1.1.5",
|
||||
"postcss": "^8.4.31",
|
||||
"prism-react-renderer": "^2.2.0",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"rapidoc": "^9.3.4",
|
||||
"react-before-after-slider-component": "^1.1.8",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-toggle": "^4.1.3",
|
||||
"react-tooltip": "^5.23.0",
|
||||
"react-tooltip": "^5.24.0",
|
||||
"react": "^18.2.0",
|
||||
"remark-github": "^12.0.0"
|
||||
},
|
||||
|
@ -52,9 +52,9 @@
|
|||
"@docusaurus/module-type-aliases": "3.0.0",
|
||||
"@docusaurus/tsconfig": "3.0.0",
|
||||
"@docusaurus/types": "3.0.0",
|
||||
"@types/react": "^18.2.37",
|
||||
"@types/react": "^18.2.38",
|
||||
"prettier": "3.1.0",
|
||||
"typescript": "~5.2.2"
|
||||
"typescript": "~5.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
|
|
|
@ -407,6 +407,7 @@ const docsSidebar = {
|
|||
},
|
||||
items: [
|
||||
"security/policy",
|
||||
"security/CVE-2023-48228",
|
||||
"security/GHSA-rjvp-29xq-f62w",
|
||||
"security/CVE-2023-39522",
|
||||
"security/CVE-2023-36456",
|
||||
|
|
Reference in a new issue