Compare commits
109 Commits
website/do
...
website/in
Author | SHA1 | Date | |
---|---|---|---|
05711546dd | |||
9c354a82cb | |||
6ab645e0f7 | |||
8a93af9100 | |||
a90297fae4 | |||
7aab9c571e | |||
90c5b5c475 | |||
adfbd1e0f2 | |||
caa5617ce6 | |||
d043dacece | |||
6a367d4ddf | |||
e802c536a5 | |||
39db9d9e6a | |||
f9ea4fc8e7 | |||
2320efc256 | |||
7b81cbbb43 | |||
2d480bffb4 | |||
e6e0e49535 | |||
31b90d5e1d | |||
e39f186e26 | |||
cdb1351cfb | |||
7b2c08073f | |||
9ad4dfb522 | |||
6b05195add | |||
2ae095bfeb | |||
cc68d8dd92 | |||
89a158f66c | |||
c56ee219a9 | |||
d596c08954 | |||
070cdba521 | |||
148d83c519 | |||
77146d2bac | |||
03d5cde5fa | |||
4af922165e | |||
c3e57a7566 | |||
423354fb09 | |||
f3fb064908 | |||
492ef54d55 | |||
8eaed2b2f4 | |||
092b6f7faf | |||
d145f91be7 | |||
36c9929e1f | |||
3fa6ce2e34 | |||
073c02cbb9 | |||
bc8971f19d | |||
104c116678 | |||
f025d0d1d5 | |||
52115f9345 | |||
b476551f13 | |||
f9563c25cd | |||
0067e6e155 | |||
7668b83a44 | |||
bad6d399a9 | |||
0d4401ad38 | |||
ce183929d4 | |||
2fdf345271 | |||
bbcf8418b4 | |||
dc57be46f4 | |||
d68b3ba516 | |||
a9c46cfcbd | |||
c50353ebf6 | |||
db6be9e1b6 | |||
a74892886d | |||
74cd4c2236 | |||
ef3bd7e77b | |||
3f5ad2baa4 | |||
24805f087b | |||
9464b422a3 | |||
da6d4ede51 | |||
cecad5bfd3 | |||
d671547183 | |||
bc4b07d57b | |||
e85d2d0096 | |||
be1dd3103b | |||
5dfde5e1d3 | |||
7cb1e6d81e | |||
d7c3129b1c | |||
2a1d33021b | |||
f273e49ae6 | |||
cc31957900 | |||
b1ccdecc8e | |||
34031003a4 | |||
055e1d1025 | |||
59a804273e | |||
bce70a1796 | |||
e86c40a00c | |||
20e07486ee | |||
0cb7cf2c96 | |||
07736a90b2 | |||
ec28a86259 | |||
260800c60b | |||
ee4780394d | |||
23b746941f | |||
3c2ce40afd | |||
2aceed285e | |||
81e5fef667 | |||
7aa6593760 | |||
c40a17beb9 | |||
335c9fbc10 | |||
51b53caf61 | |||
989100a900 | |||
8e1531d051 | |||
f6f37d6d92 | |||
5b6ca70f22 | |||
a74674c3d6 | |||
f46984dec4 | |||
c7963e4af7 | |||
6e30b11974 | |||
13bd4069e4 |
@ -1,5 +1,5 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 2025.6.1
|
current_version = 2025.6.2
|
||||||
tag = True
|
tag = True
|
||||||
commit = True
|
commit = True
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
||||||
|
@ -7,6 +7,9 @@ charset = utf-8
|
|||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.toml]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
[*.html]
|
[*.html]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
2
.github/workflows/ci-main.yml
vendored
2
.github/workflows/ci-main.yml
vendored
@ -202,7 +202,7 @@ jobs:
|
|||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: web/dist
|
path: web/dist
|
||||||
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b
|
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b
|
||||||
- name: prepare web ui
|
- name: prepare web ui
|
||||||
if: steps.cache-web.outputs.cache-hit != 'true'
|
if: steps.cache-web.outputs.cache-hit != 'true'
|
||||||
working-directory: web
|
working-directory: web
|
||||||
|
22
.github/workflows/ci-website.yml
vendored
22
.github/workflows/ci-website.yml
vendored
@ -41,6 +41,27 @@ jobs:
|
|||||||
- name: test
|
- name: test
|
||||||
working-directory: website/
|
working-directory: website/
|
||||||
run: npm test
|
run: npm test
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: ${{ matrix.job }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- build
|
||||||
|
- build:integrations
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: website/package.json
|
||||||
|
cache: "npm"
|
||||||
|
cache-dependency-path: website/package-lock.json
|
||||||
|
- working-directory: website/
|
||||||
|
run: npm ci
|
||||||
|
- name: build
|
||||||
|
working-directory: website/
|
||||||
|
run: npm run ${{ matrix.job }}
|
||||||
build-container:
|
build-container:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
@ -94,6 +115,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- lint
|
- lint
|
||||||
- test
|
- test
|
||||||
|
- build
|
||||||
- build-container
|
- build-container
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
@ -75,9 +75,9 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
|
|||||||
/bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
|
/bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
|
||||||
|
|
||||||
# Stage 4: Download uv
|
# Stage 4: Download uv
|
||||||
FROM ghcr.io/astral-sh/uv:0.7.12 AS uv
|
FROM ghcr.io/astral-sh/uv:0.7.13 AS uv
|
||||||
# Stage 5: Base python image
|
# Stage 5: Base python image
|
||||||
FROM ghcr.io/goauthentik/fips-python:3.13.4-slim-bookworm-fips AS python-base
|
FROM ghcr.io/goauthentik/fips-python:3.13.5-slim-bookworm-fips AS python-base
|
||||||
|
|
||||||
ENV VENV_PATH="/ak-root/.venv" \
|
ENV VENV_PATH="/ak-root/.venv" \
|
||||||
PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \
|
PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \
|
||||||
|
2
Makefile
2
Makefile
@ -94,7 +94,7 @@ gen-build: ## Extract the schema from the database
|
|||||||
AUTHENTIK_DEBUG=true \
|
AUTHENTIK_DEBUG=true \
|
||||||
AUTHENTIK_TENANTS__ENABLED=true \
|
AUTHENTIK_TENANTS__ENABLED=true \
|
||||||
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
||||||
uv run ak make_blueprint_schema > blueprints/schema.json
|
uv run ak make_blueprint_schema --file blueprints/schema.json
|
||||||
AUTHENTIK_DEBUG=true \
|
AUTHENTIK_DEBUG=true \
|
||||||
AUTHENTIK_TENANTS__ENABLED=true \
|
AUTHENTIK_TENANTS__ENABLED=true \
|
||||||
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
from os import environ
|
from os import environ
|
||||||
|
|
||||||
__version__ = "2025.6.1"
|
__version__ = "2025.6.2"
|
||||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,20 +72,33 @@ class Command(BaseCommand):
|
|||||||
"additionalProperties": True,
|
"additionalProperties": True,
|
||||||
},
|
},
|
||||||
"entries": {
|
"entries": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {"$ref": "#/$defs/blueprint_entry"},
|
||||||
"oneOf": [],
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {"$ref": "#/$defs/blueprint_entry"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
"$defs": {},
|
},
|
||||||
|
"$defs": {"blueprint_entry": {"oneOf": []}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument("--file", type=str)
|
||||||
|
|
||||||
@no_translations
|
@no_translations
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, file: str, **options):
|
||||||
"""Generate JSON Schema for blueprints"""
|
"""Generate JSON Schema for blueprints"""
|
||||||
self.build()
|
self.build()
|
||||||
self.stdout.write(dumps(self.schema, indent=4, default=Command.json_default))
|
with open(file, "w") as _schema:
|
||||||
|
_schema.write(dumps(self.schema, indent=4, default=Command.json_default))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def json_default(value: Any) -> Any:
|
def json_default(value: Any) -> Any:
|
||||||
@ -112,7 +125,7 @@ class Command(BaseCommand):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
model_path = f"{model._meta.app_label}.{model._meta.model_name}"
|
model_path = f"{model._meta.app_label}.{model._meta.model_name}"
|
||||||
self.schema["properties"]["entries"]["items"]["oneOf"].append(
|
self.schema["$defs"]["blueprint_entry"]["oneOf"].append(
|
||||||
self.template_entry(model_path, model, serializer)
|
self.template_entry(model_path, model, serializer)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -134,7 +147,7 @@ class Command(BaseCommand):
|
|||||||
"id": {"type": "string"},
|
"id": {"type": "string"},
|
||||||
"state": {
|
"state": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [s.value for s in BlueprintEntryDesiredState],
|
"enum": sorted([s.value for s in BlueprintEntryDesiredState]),
|
||||||
"default": "present",
|
"default": "present",
|
||||||
},
|
},
|
||||||
"conditions": {"type": "array", "items": {"type": "boolean"}},
|
"conditions": {"type": "array", "items": {"type": "boolean"}},
|
||||||
@ -205,7 +218,7 @@ class Command(BaseCommand):
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["permission"],
|
"required": ["permission"],
|
||||||
"properties": {
|
"properties": {
|
||||||
"permission": {"type": "string", "enum": perms},
|
"permission": {"type": "string", "enum": sorted(perms)},
|
||||||
"user": {"type": "integer"},
|
"user": {"type": "integer"},
|
||||||
"role": {"type": "string"},
|
"role": {"type": "string"},
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
version: 1
|
version: 1
|
||||||
entries:
|
entries:
|
||||||
|
foo:
|
||||||
- identifiers:
|
- identifiers:
|
||||||
name: "%(id)s"
|
name: "%(id)s"
|
||||||
slug: "%(id)s"
|
slug: "%(id)s"
|
||||||
|
@ -191,11 +191,18 @@ class Blueprint:
|
|||||||
"""Dataclass used for a full export"""
|
"""Dataclass used for a full export"""
|
||||||
|
|
||||||
version: int = field(default=1)
|
version: int = field(default=1)
|
||||||
entries: list[BlueprintEntry] = field(default_factory=list)
|
entries: list[BlueprintEntry] | dict[str, list[BlueprintEntry]] = field(default_factory=list)
|
||||||
context: dict = field(default_factory=dict)
|
context: dict = field(default_factory=dict)
|
||||||
|
|
||||||
metadata: BlueprintMetadata | None = field(default=None)
|
metadata: BlueprintMetadata | None = field(default=None)
|
||||||
|
|
||||||
|
def iter_entries(self) -> Iterable[BlueprintEntry]:
|
||||||
|
if isinstance(self.entries, dict):
|
||||||
|
for _section, entries in self.entries.items():
|
||||||
|
yield from entries
|
||||||
|
else:
|
||||||
|
yield from self.entries
|
||||||
|
|
||||||
|
|
||||||
class YAMLTag:
|
class YAMLTag:
|
||||||
"""Base class for all YAML Tags"""
|
"""Base class for all YAML Tags"""
|
||||||
@ -226,7 +233,7 @@ class KeyOf(YAMLTag):
|
|||||||
self.id_from = node.value
|
self.id_from = node.value
|
||||||
|
|
||||||
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
|
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
|
||||||
for _entry in blueprint.entries:
|
for _entry in blueprint.iter_entries():
|
||||||
if _entry.id == self.id_from and _entry._state.instance:
|
if _entry.id == self.id_from and _entry._state.instance:
|
||||||
# Special handling for PolicyBindingModels, as they'll have a different PK
|
# Special handling for PolicyBindingModels, as they'll have a different PK
|
||||||
# which is used when creating policy bindings
|
# which is used when creating policy bindings
|
||||||
|
@ -384,7 +384,7 @@ class Importer:
|
|||||||
def _apply_models(self, raise_errors=False) -> bool:
|
def _apply_models(self, raise_errors=False) -> bool:
|
||||||
"""Apply (create/update) models yaml"""
|
"""Apply (create/update) models yaml"""
|
||||||
self.__pk_map = {}
|
self.__pk_map = {}
|
||||||
for entry in self._import.entries:
|
for entry in self._import.iter_entries():
|
||||||
model_app_label, model_name = entry.get_model(self._import).split(".")
|
model_app_label, model_name = entry.get_model(self._import).split(".")
|
||||||
try:
|
try:
|
||||||
model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
|
model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
|
||||||
|
@ -47,7 +47,7 @@ class MetaModelRegistry:
|
|||||||
models = apps.get_models()
|
models = apps.get_models()
|
||||||
for _, value in self.models.items():
|
for _, value in self.models.items():
|
||||||
models.append(value)
|
models.append(value)
|
||||||
return models
|
return sorted(models, key=str)
|
||||||
|
|
||||||
def get_model(self, app_label: str, model_id: str) -> type[Model]:
|
def get_model(self, app_label: str, model_id: str) -> type[Model]:
|
||||||
"""Get model checks if any virtual models are registered, and falls back
|
"""Get model checks if any virtual models are registered, and falls back
|
||||||
|
@ -386,8 +386,23 @@ class UserViewSet(UsedByMixin, ModelViewSet):
|
|||||||
queryset = User.objects.none()
|
queryset = User.objects.none()
|
||||||
ordering = ["username"]
|
ordering = ["username"]
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
search_fields = ["username", "name", "is_active", "email", "uuid", "attributes"]
|
|
||||||
filterset_class = UsersFilter
|
filterset_class = UsersFilter
|
||||||
|
search_fields = ["username", "name", "is_active", "email", "uuid", "attributes"]
|
||||||
|
|
||||||
|
def get_ql_fields(self):
|
||||||
|
from djangoql.schema import BoolField, StrField
|
||||||
|
|
||||||
|
from authentik.enterprise.search.fields import ChoiceSearchField, JSONSearchField
|
||||||
|
|
||||||
|
return [
|
||||||
|
StrField(User, "username"),
|
||||||
|
StrField(User, "name"),
|
||||||
|
StrField(User, "email"),
|
||||||
|
StrField(User, "path"),
|
||||||
|
BoolField(User, "is_active", nullable=True),
|
||||||
|
ChoiceSearchField(User, "type"),
|
||||||
|
JSONSearchField(User, "attributes"),
|
||||||
|
]
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
base_qs = User.objects.all().exclude_anonymous()
|
base_qs = User.objects.all().exclude_anonymous()
|
||||||
|
@ -18,7 +18,7 @@ from django.http import HttpRequest
|
|||||||
from django.utils.functional import SimpleLazyObject, cached_property
|
from django.utils.functional import SimpleLazyObject, cached_property
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django_cte import CTEQuerySet, With
|
from django_cte import CTE, with_cte
|
||||||
from guardian.conf import settings
|
from guardian.conf import settings
|
||||||
from guardian.mixins import GuardianUserMixin
|
from guardian.mixins import GuardianUserMixin
|
||||||
from model_utils.managers import InheritanceManager
|
from model_utils.managers import InheritanceManager
|
||||||
@ -136,7 +136,7 @@ class AttributesMixin(models.Model):
|
|||||||
return instance, False
|
return instance, False
|
||||||
|
|
||||||
|
|
||||||
class GroupQuerySet(CTEQuerySet):
|
class GroupQuerySet(QuerySet):
|
||||||
def with_children_recursive(self):
|
def with_children_recursive(self):
|
||||||
"""Recursively get all groups that have the current queryset as parents
|
"""Recursively get all groups that have the current queryset as parents
|
||||||
or are indirectly related."""
|
or are indirectly related."""
|
||||||
@ -165,9 +165,9 @@ class GroupQuerySet(CTEQuerySet):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Build the recursive query, see above
|
# Build the recursive query, see above
|
||||||
cte = With.recursive(make_cte)
|
cte = CTE.recursive(make_cte)
|
||||||
# Return the result, as a usable queryset for Group.
|
# Return the result, as a usable queryset for Group.
|
||||||
return cte.join(Group, group_uuid=cte.col.group_uuid).with_cte(cte)
|
return with_cte(cte, select=cte.join(Group, group_uuid=cte.col.group_uuid))
|
||||||
|
|
||||||
|
|
||||||
class Group(SerializerModel, AttributesMixin):
|
class Group(SerializerModel, AttributesMixin):
|
||||||
|
@ -114,6 +114,7 @@ class TestApplicationsAPI(APITestCase):
|
|||||||
self.assertJSONEqual(
|
self.assertJSONEqual(
|
||||||
response.content.decode(),
|
response.content.decode(),
|
||||||
{
|
{
|
||||||
|
"autocomplete": {},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"next": 0,
|
"next": 0,
|
||||||
"previous": 0,
|
"previous": 0,
|
||||||
@ -167,6 +168,7 @@ class TestApplicationsAPI(APITestCase):
|
|||||||
self.assertJSONEqual(
|
self.assertJSONEqual(
|
||||||
response.content.decode(),
|
response.content.decode(),
|
||||||
{
|
{
|
||||||
|
"autocomplete": {},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"next": 0,
|
"next": 0,
|
||||||
"previous": 0,
|
"previous": 0,
|
||||||
|
@ -119,17 +119,17 @@ class TestTrimPasswordHistory(TestCase):
|
|||||||
[
|
[
|
||||||
UserPasswordHistory(
|
UserPasswordHistory(
|
||||||
user=self.user,
|
user=self.user,
|
||||||
old_password="hunter1", # nosec B106
|
old_password="hunter1", # nosec
|
||||||
created_at=_now - timedelta(days=3),
|
created_at=_now - timedelta(days=3),
|
||||||
),
|
),
|
||||||
UserPasswordHistory(
|
UserPasswordHistory(
|
||||||
user=self.user,
|
user=self.user,
|
||||||
old_password="hunter2", # nosec B106
|
old_password="hunter2", # nosec
|
||||||
created_at=_now - timedelta(days=2),
|
created_at=_now - timedelta(days=2),
|
||||||
),
|
),
|
||||||
UserPasswordHistory(
|
UserPasswordHistory(
|
||||||
user=self.user,
|
user=self.user,
|
||||||
old_password="hunter3", # nosec B106
|
old_password="hunter3", # nosec
|
||||||
created_at=_now,
|
created_at=_now,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
0
authentik/enterprise/search/__init__.py
Normal file
0
authentik/enterprise/search/__init__.py
Normal file
12
authentik/enterprise/search/apps.py
Normal file
12
authentik/enterprise/search/apps.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
"""Enterprise app config"""
|
||||||
|
|
||||||
|
from authentik.enterprise.apps import EnterpriseConfig
|
||||||
|
|
||||||
|
|
||||||
|
class AuthentikEnterpriseSearchConfig(EnterpriseConfig):
|
||||||
|
"""Enterprise app config"""
|
||||||
|
|
||||||
|
name = "authentik.enterprise.search"
|
||||||
|
label = "authentik_search"
|
||||||
|
verbose_name = "authentik Enterprise.Search"
|
||||||
|
default = True
|
128
authentik/enterprise/search/fields.py
Normal file
128
authentik/enterprise/search/fields.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
"""DjangoQL search"""
|
||||||
|
|
||||||
|
from collections import OrderedDict, defaultdict
|
||||||
|
from collections.abc import Generator
|
||||||
|
|
||||||
|
from django.db import connection
|
||||||
|
from django.db.models import Model, Q
|
||||||
|
from djangoql.compat import text_type
|
||||||
|
from djangoql.schema import StrField
|
||||||
|
|
||||||
|
|
||||||
|
class JSONSearchField(StrField):
|
||||||
|
"""JSON field for DjangoQL"""
|
||||||
|
|
||||||
|
model: Model
|
||||||
|
|
||||||
|
def __init__(self, model=None, name=None, nullable=None, suggest_nested=True):
|
||||||
|
# Set this in the constructor to not clobber the type variable
|
||||||
|
self.type = "relation"
|
||||||
|
self.suggest_nested = suggest_nested
|
||||||
|
super().__init__(model, name, nullable)
|
||||||
|
|
||||||
|
def get_lookup(self, path, operator, value):
|
||||||
|
search = "__".join(path)
|
||||||
|
op, invert = self.get_operator(operator)
|
||||||
|
q = Q(**{f"{search}{op}": self.get_lookup_value(value)})
|
||||||
|
return ~q if invert else q
|
||||||
|
|
||||||
|
def json_field_keys(self) -> Generator[tuple[str]]:
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute(
|
||||||
|
f"""
|
||||||
|
WITH RECURSIVE "{self.name}_keys" AS (
|
||||||
|
SELECT
|
||||||
|
ARRAY[jsonb_object_keys("{self.name}")] AS key_path_array,
|
||||||
|
"{self.name}" -> jsonb_object_keys("{self.name}") AS value
|
||||||
|
FROM {self.model._meta.db_table}
|
||||||
|
WHERE "{self.name}" IS NOT NULL
|
||||||
|
AND jsonb_typeof("{self.name}") = 'object'
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
ck.key_path_array || jsonb_object_keys(ck.value),
|
||||||
|
ck.value -> jsonb_object_keys(ck.value) AS value
|
||||||
|
FROM "{self.name}_keys" ck
|
||||||
|
WHERE jsonb_typeof(ck.value) = 'object'
|
||||||
|
),
|
||||||
|
|
||||||
|
unique_paths AS (
|
||||||
|
SELECT DISTINCT key_path_array
|
||||||
|
FROM "{self.name}_keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
SELECT key_path_array FROM unique_paths;
|
||||||
|
""" # nosec
|
||||||
|
)
|
||||||
|
return (x[0] for x in cursor.fetchall())
|
||||||
|
|
||||||
|
def get_nested_options(self) -> OrderedDict:
|
||||||
|
"""Get keys of all nested objects to show autocomplete"""
|
||||||
|
if not self.suggest_nested:
|
||||||
|
return OrderedDict()
|
||||||
|
base_model_name = f"{self.model._meta.app_label}.{self.model._meta.model_name}_{self.name}"
|
||||||
|
|
||||||
|
def recursive_function(parts: list[str], parent_parts: list[str] | None = None):
|
||||||
|
if not parent_parts:
|
||||||
|
parent_parts = []
|
||||||
|
path = parts.pop(0)
|
||||||
|
parent_parts.append(path)
|
||||||
|
relation_key = "_".join(parent_parts)
|
||||||
|
if len(parts) > 1:
|
||||||
|
out_dict = {
|
||||||
|
relation_key: {
|
||||||
|
parts[0]: {
|
||||||
|
"type": "relation",
|
||||||
|
"relation": f"{relation_key}_{parts[0]}",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
child_paths = recursive_function(parts.copy(), parent_parts.copy())
|
||||||
|
child_paths.update(out_dict)
|
||||||
|
return child_paths
|
||||||
|
else:
|
||||||
|
return {relation_key: {parts[0]: {}}}
|
||||||
|
|
||||||
|
relation_structure = defaultdict(dict)
|
||||||
|
|
||||||
|
for relations in self.json_field_keys():
|
||||||
|
result = recursive_function([base_model_name] + relations)
|
||||||
|
for relation_key, value in result.items():
|
||||||
|
for sub_relation_key, sub_value in value.items():
|
||||||
|
if not relation_structure[relation_key].get(sub_relation_key, None):
|
||||||
|
relation_structure[relation_key][sub_relation_key] = sub_value
|
||||||
|
else:
|
||||||
|
relation_structure[relation_key][sub_relation_key].update(sub_value)
|
||||||
|
|
||||||
|
final_dict = defaultdict(dict)
|
||||||
|
|
||||||
|
for key, value in relation_structure.items():
|
||||||
|
for sub_key, sub_value in value.items():
|
||||||
|
if not sub_value:
|
||||||
|
final_dict[key][sub_key] = {
|
||||||
|
"type": "str",
|
||||||
|
"nullable": True,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
final_dict[key][sub_key] = sub_value
|
||||||
|
return OrderedDict(final_dict)
|
||||||
|
|
||||||
|
def relation(self) -> str:
|
||||||
|
return f"{self.model._meta.app_label}.{self.model._meta.model_name}_{self.name}"
|
||||||
|
|
||||||
|
|
||||||
|
class ChoiceSearchField(StrField):
|
||||||
|
def __init__(self, model=None, name=None, nullable=None):
|
||||||
|
super().__init__(model, name, nullable, suggest_options=True)
|
||||||
|
|
||||||
|
def get_options(self, search):
|
||||||
|
result = []
|
||||||
|
choices = self._field_choices()
|
||||||
|
if choices:
|
||||||
|
search = search.lower()
|
||||||
|
for c in choices:
|
||||||
|
choice = text_type(c[0])
|
||||||
|
if search in choice.lower():
|
||||||
|
result.append(choice)
|
||||||
|
return result
|
53
authentik/enterprise/search/pagination.py
Normal file
53
authentik/enterprise/search/pagination.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from authentik.api.pagination import Pagination
|
||||||
|
from authentik.enterprise.search.ql import AUTOCOMPLETE_COMPONENT_NAME, QLSearch
|
||||||
|
|
||||||
|
|
||||||
|
class AutocompletePagination(Pagination):
|
||||||
|
|
||||||
|
def paginate_queryset(self, queryset, request, view=None):
|
||||||
|
self.view = view
|
||||||
|
return super().paginate_queryset(queryset, request, view)
|
||||||
|
|
||||||
|
def get_autocomplete(self):
|
||||||
|
schema = QLSearch().get_schema(self.request, self.view)
|
||||||
|
introspections = {}
|
||||||
|
if hasattr(self.view, "get_ql_fields"):
|
||||||
|
from authentik.enterprise.search.schema import AKQLSchemaSerializer
|
||||||
|
|
||||||
|
introspections = AKQLSchemaSerializer().serialize(
|
||||||
|
schema(self.page.paginator.object_list.model)
|
||||||
|
)
|
||||||
|
return introspections
|
||||||
|
|
||||||
|
def get_paginated_response(self, data):
|
||||||
|
previous_page_number = 0
|
||||||
|
if self.page.has_previous():
|
||||||
|
previous_page_number = self.page.previous_page_number()
|
||||||
|
next_page_number = 0
|
||||||
|
if self.page.has_next():
|
||||||
|
next_page_number = self.page.next_page_number()
|
||||||
|
return Response(
|
||||||
|
{
|
||||||
|
"pagination": {
|
||||||
|
"next": next_page_number,
|
||||||
|
"previous": previous_page_number,
|
||||||
|
"count": self.page.paginator.count,
|
||||||
|
"current": self.page.number,
|
||||||
|
"total_pages": self.page.paginator.num_pages,
|
||||||
|
"start_index": self.page.start_index(),
|
||||||
|
"end_index": self.page.end_index(),
|
||||||
|
},
|
||||||
|
"results": data,
|
||||||
|
"autocomplete": self.get_autocomplete(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_paginated_response_schema(self, schema):
|
||||||
|
final_schema = super().get_paginated_response_schema(schema)
|
||||||
|
final_schema["properties"]["autocomplete"] = {
|
||||||
|
"$ref": f"#/components/schemas/{AUTOCOMPLETE_COMPONENT_NAME}"
|
||||||
|
}
|
||||||
|
final_schema["required"].append("autocomplete")
|
||||||
|
return final_schema
|
78
authentik/enterprise/search/ql.py
Normal file
78
authentik/enterprise/search/ql.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
"""DjangoQL search"""
|
||||||
|
|
||||||
|
from django.apps import apps
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
from djangoql.ast import Name
|
||||||
|
from djangoql.exceptions import DjangoQLError
|
||||||
|
from djangoql.queryset import apply_search
|
||||||
|
from djangoql.schema import DjangoQLSchema
|
||||||
|
from rest_framework.filters import SearchFilter
|
||||||
|
from rest_framework.request import Request
|
||||||
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
|
from authentik.enterprise.search.fields import JSONSearchField
|
||||||
|
|
||||||
|
LOGGER = get_logger()
|
||||||
|
AUTOCOMPLETE_COMPONENT_NAME = "Autocomplete"
|
||||||
|
AUTOCOMPLETE_SCHEMA = {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class BaseSchema(DjangoQLSchema):
|
||||||
|
"""Base Schema which deals with JSON Fields"""
|
||||||
|
|
||||||
|
def resolve_name(self, name: Name):
|
||||||
|
model = self.model_label(self.current_model)
|
||||||
|
root_field = name.parts[0]
|
||||||
|
field = self.models[model].get(root_field)
|
||||||
|
# If the query goes into a JSON field, return the root
|
||||||
|
# field as the JSON field will do the rest
|
||||||
|
if isinstance(field, JSONSearchField):
|
||||||
|
# This is a workaround; build_filter will remove the right-most
|
||||||
|
# entry in the path as that is intended to be the same as the field
|
||||||
|
# however for JSON that is not the case
|
||||||
|
if name.parts[-1] != root_field:
|
||||||
|
name.parts.append(root_field)
|
||||||
|
return field
|
||||||
|
return super().resolve_name(name)
|
||||||
|
|
||||||
|
|
||||||
|
class QLSearch(SearchFilter):
|
||||||
|
"""rest_framework search filter which uses DjangoQL"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self):
|
||||||
|
return apps.get_app_config("authentik_enterprise").enabled()
|
||||||
|
|
||||||
|
def get_search_terms(self, request) -> str:
|
||||||
|
"""
|
||||||
|
Search terms are set by a ?search=... query parameter,
|
||||||
|
and may be comma and/or whitespace delimited.
|
||||||
|
"""
|
||||||
|
params = request.query_params.get(self.search_param, "")
|
||||||
|
params = params.replace("\x00", "") # strip null characters
|
||||||
|
return params
|
||||||
|
|
||||||
|
def get_schema(self, request: Request, view) -> BaseSchema:
|
||||||
|
ql_fields = []
|
||||||
|
if hasattr(view, "get_ql_fields"):
|
||||||
|
ql_fields = view.get_ql_fields()
|
||||||
|
|
||||||
|
class InlineSchema(BaseSchema):
|
||||||
|
def get_fields(self, model):
|
||||||
|
return ql_fields or []
|
||||||
|
|
||||||
|
return InlineSchema
|
||||||
|
|
||||||
|
def filter_queryset(self, request: Request, queryset: QuerySet, view) -> QuerySet:
|
||||||
|
search_query = self.get_search_terms(request)
|
||||||
|
schema = self.get_schema(request, view)
|
||||||
|
if len(search_query) == 0 or not self.enabled:
|
||||||
|
return super().filter_queryset(request, queryset, view)
|
||||||
|
try:
|
||||||
|
return apply_search(queryset, search_query, schema=schema)
|
||||||
|
except DjangoQLError as exc:
|
||||||
|
LOGGER.debug("Failed to parse search expression", exc=exc)
|
||||||
|
return super().filter_queryset(request, queryset, view)
|
29
authentik/enterprise/search/schema.py
Normal file
29
authentik/enterprise/search/schema.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from djangoql.serializers import DjangoQLSchemaSerializer
|
||||||
|
from drf_spectacular.generators import SchemaGenerator
|
||||||
|
|
||||||
|
from authentik.api.schema import create_component
|
||||||
|
from authentik.enterprise.search.fields import JSONSearchField
|
||||||
|
from authentik.enterprise.search.ql import AUTOCOMPLETE_COMPONENT_NAME, AUTOCOMPLETE_SCHEMA
|
||||||
|
|
||||||
|
|
||||||
|
class AKQLSchemaSerializer(DjangoQLSchemaSerializer):
|
||||||
|
def serialize(self, schema):
|
||||||
|
serialization = super().serialize(schema)
|
||||||
|
for _, fields in schema.models.items():
|
||||||
|
for _, field in fields.items():
|
||||||
|
if not isinstance(field, JSONSearchField):
|
||||||
|
continue
|
||||||
|
serialization["models"].update(field.get_nested_options())
|
||||||
|
return serialization
|
||||||
|
|
||||||
|
def serialize_field(self, field):
|
||||||
|
result = super().serialize_field(field)
|
||||||
|
if isinstance(field, JSONSearchField):
|
||||||
|
result["relation"] = field.relation()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def postprocess_schema_search_autocomplete(result, generator: SchemaGenerator, **kwargs):
|
||||||
|
create_component(generator, AUTOCOMPLETE_COMPONENT_NAME, AUTOCOMPLETE_SCHEMA)
|
||||||
|
|
||||||
|
return result
|
17
authentik/enterprise/search/settings.py
Normal file
17
authentik/enterprise/search/settings.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
SPECTACULAR_SETTINGS = {
|
||||||
|
"POSTPROCESSING_HOOKS": [
|
||||||
|
"authentik.api.schema.postprocess_schema_responses",
|
||||||
|
"authentik.enterprise.search.schema.postprocess_schema_search_autocomplete",
|
||||||
|
"drf_spectacular.hooks.postprocess_schema_enums",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
REST_FRAMEWORK = {
|
||||||
|
"DEFAULT_PAGINATION_CLASS": "authentik.enterprise.search.pagination.AutocompletePagination",
|
||||||
|
"DEFAULT_FILTER_BACKENDS": [
|
||||||
|
"authentik.enterprise.search.ql.QLSearch",
|
||||||
|
"authentik.rbac.filters.ObjectFilter",
|
||||||
|
"django_filters.rest_framework.DjangoFilterBackend",
|
||||||
|
"rest_framework.filters.OrderingFilter",
|
||||||
|
],
|
||||||
|
}
|
78
authentik/enterprise/search/tests.py
Normal file
78
authentik/enterprise/search/tests.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
from json import loads
|
||||||
|
from unittest.mock import PropertyMock, patch
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
|
from authentik.core.tests.utils import create_test_admin_user
|
||||||
|
|
||||||
|
|
||||||
|
@patch(
|
||||||
|
"authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
|
||||||
|
PropertyMock(return_value=True),
|
||||||
|
)
|
||||||
|
class QLTest(APITestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.user = create_test_admin_user()
|
||||||
|
# ensure we have more than 1 user
|
||||||
|
create_test_admin_user()
|
||||||
|
|
||||||
|
def test_search(self):
|
||||||
|
"""Test simple search query"""
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
query = f'username = "{self.user.username}"'
|
||||||
|
res = self.client.get(
|
||||||
|
reverse(
|
||||||
|
"authentik_api:user-list",
|
||||||
|
)
|
||||||
|
+ f"?{urlencode({"search": query})}"
|
||||||
|
)
|
||||||
|
self.assertEqual(res.status_code, 200)
|
||||||
|
content = loads(res.content)
|
||||||
|
self.assertEqual(content["pagination"]["count"], 1)
|
||||||
|
self.assertEqual(content["results"][0]["username"], self.user.username)
|
||||||
|
|
||||||
|
def test_no_search(self):
|
||||||
|
"""Ensure works with no search query"""
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
res = self.client.get(
|
||||||
|
reverse(
|
||||||
|
"authentik_api:user-list",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertEqual(res.status_code, 200)
|
||||||
|
content = loads(res.content)
|
||||||
|
self.assertNotEqual(content["pagination"]["count"], 1)
|
||||||
|
|
||||||
|
def test_search_no_ql(self):
|
||||||
|
"""Test simple search query (no QL)"""
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
res = self.client.get(
|
||||||
|
reverse(
|
||||||
|
"authentik_api:user-list",
|
||||||
|
)
|
||||||
|
+ f"?{urlencode({"search": self.user.username})}"
|
||||||
|
)
|
||||||
|
self.assertEqual(res.status_code, 200)
|
||||||
|
content = loads(res.content)
|
||||||
|
self.assertGreaterEqual(content["pagination"]["count"], 1)
|
||||||
|
self.assertEqual(content["results"][0]["username"], self.user.username)
|
||||||
|
|
||||||
|
def test_search_json(self):
|
||||||
|
"""Test search query with a JSON attribute"""
|
||||||
|
self.user.attributes = {"foo": {"bar": "baz"}}
|
||||||
|
self.user.save()
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
query = 'attributes.foo.bar = "baz"'
|
||||||
|
res = self.client.get(
|
||||||
|
reverse(
|
||||||
|
"authentik_api:user-list",
|
||||||
|
)
|
||||||
|
+ f"?{urlencode({"search": query})}"
|
||||||
|
)
|
||||||
|
self.assertEqual(res.status_code, 200)
|
||||||
|
content = loads(res.content)
|
||||||
|
self.assertEqual(content["pagination"]["count"], 1)
|
||||||
|
self.assertEqual(content["results"][0]["username"], self.user.username)
|
@ -18,6 +18,7 @@ TENANT_APPS = [
|
|||||||
"authentik.enterprise.providers.google_workspace",
|
"authentik.enterprise.providers.google_workspace",
|
||||||
"authentik.enterprise.providers.microsoft_entra",
|
"authentik.enterprise.providers.microsoft_entra",
|
||||||
"authentik.enterprise.providers.ssf",
|
"authentik.enterprise.providers.ssf",
|
||||||
|
"authentik.enterprise.search",
|
||||||
"authentik.enterprise.stages.authenticator_endpoint_gdtc",
|
"authentik.enterprise.stages.authenticator_endpoint_gdtc",
|
||||||
"authentik.enterprise.stages.mtls",
|
"authentik.enterprise.stages.mtls",
|
||||||
"authentik.enterprise.stages.source",
|
"authentik.enterprise.stages.source",
|
||||||
|
@ -132,6 +132,22 @@ class EventViewSet(ModelViewSet):
|
|||||||
]
|
]
|
||||||
filterset_class = EventsFilter
|
filterset_class = EventsFilter
|
||||||
|
|
||||||
|
def get_ql_fields(self):
|
||||||
|
from djangoql.schema import DateTimeField, StrField
|
||||||
|
|
||||||
|
from authentik.enterprise.search.fields import ChoiceSearchField, JSONSearchField
|
||||||
|
|
||||||
|
return [
|
||||||
|
ChoiceSearchField(Event, "action"),
|
||||||
|
StrField(Event, "event_uuid"),
|
||||||
|
StrField(Event, "app", suggest_options=True),
|
||||||
|
StrField(Event, "client_ip"),
|
||||||
|
JSONSearchField(Event, "user", suggest_nested=False),
|
||||||
|
JSONSearchField(Event, "brand", suggest_nested=False),
|
||||||
|
JSONSearchField(Event, "context", suggest_nested=False),
|
||||||
|
DateTimeField(Event, "created", suggest_options=True),
|
||||||
|
]
|
||||||
|
|
||||||
@extend_schema(
|
@extend_schema(
|
||||||
methods=["GET"],
|
methods=["GET"],
|
||||||
responses={200: EventTopPerUserSerializer(many=True)},
|
responses={200: EventTopPerUserSerializer(many=True)},
|
||||||
|
@ -11,7 +11,7 @@ from authentik.events.models import NotificationRule
|
|||||||
class NotificationRuleSerializer(ModelSerializer):
|
class NotificationRuleSerializer(ModelSerializer):
|
||||||
"""NotificationRule Serializer"""
|
"""NotificationRule Serializer"""
|
||||||
|
|
||||||
group_obj = GroupSerializer(read_only=True, source="group")
|
destination_group_obj = GroupSerializer(read_only=True, source="destination_group")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = NotificationRule
|
model = NotificationRule
|
||||||
@ -20,8 +20,9 @@ class NotificationRuleSerializer(ModelSerializer):
|
|||||||
"name",
|
"name",
|
||||||
"transports",
|
"transports",
|
||||||
"severity",
|
"severity",
|
||||||
"group",
|
"destination_group",
|
||||||
"group_obj",
|
"destination_group_obj",
|
||||||
|
"destination_event_user",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -30,6 +31,6 @@ class NotificationRuleViewSet(UsedByMixin, ModelViewSet):
|
|||||||
|
|
||||||
queryset = NotificationRule.objects.all()
|
queryset = NotificationRule.objects.all()
|
||||||
serializer_class = NotificationRuleSerializer
|
serializer_class = NotificationRuleSerializer
|
||||||
filterset_fields = ["name", "severity", "group__name"]
|
filterset_fields = ["name", "severity", "destination_group__name"]
|
||||||
ordering = ["name"]
|
ordering = ["name"]
|
||||||
search_fields = ["name", "group__name"]
|
search_fields = ["name", "destination_group__name"]
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 5.1.11 on 2025-06-16 23:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_events", "0009_remove_notificationtransport_webhook_mapping_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="notificationrule",
|
||||||
|
old_name="group",
|
||||||
|
new_name="destination_group",
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="notificationrule",
|
||||||
|
name="destination_event_user",
|
||||||
|
field=models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text="When enabled, notification will be sent to user the user that triggered the event.When destination_group is configured, notification is sent to both.",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -1,10 +1,12 @@
|
|||||||
"""authentik events models"""
|
"""authentik events models"""
|
||||||
|
|
||||||
|
from collections.abc import Generator
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from difflib import get_close_matches
|
from difflib import get_close_matches
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from inspect import currentframe
|
from inspect import currentframe
|
||||||
from smtplib import SMTPException
|
from smtplib import SMTPException
|
||||||
|
from typing import Any
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
@ -547,7 +549,7 @@ class NotificationRule(SerializerModel, PolicyBindingModel):
|
|||||||
default=NotificationSeverity.NOTICE,
|
default=NotificationSeverity.NOTICE,
|
||||||
help_text=_("Controls which severity level the created notifications will have."),
|
help_text=_("Controls which severity level the created notifications will have."),
|
||||||
)
|
)
|
||||||
group = models.ForeignKey(
|
destination_group = models.ForeignKey(
|
||||||
Group,
|
Group,
|
||||||
help_text=_(
|
help_text=_(
|
||||||
"Define which group of users this notification should be sent and shown to. "
|
"Define which group of users this notification should be sent and shown to. "
|
||||||
@ -557,6 +559,19 @@ class NotificationRule(SerializerModel, PolicyBindingModel):
|
|||||||
blank=True,
|
blank=True,
|
||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
)
|
)
|
||||||
|
destination_event_user = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text=_(
|
||||||
|
"When enabled, notification will be sent to user the user that triggered the event."
|
||||||
|
"When destination_group is configured, notification is sent to both."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def destination_users(self, event: Event) -> Generator[User, Any]:
|
||||||
|
if self.destination_event_user and event.user.get("pk"):
|
||||||
|
yield User(pk=event.user.get("pk"))
|
||||||
|
if self.destination_group:
|
||||||
|
yield from self.destination_group.users.all()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def serializer(self) -> type[Serializer]:
|
def serializer(self) -> type[Serializer]:
|
||||||
|
@ -68,14 +68,10 @@ def event_trigger_handler(event_uuid: str, trigger_name: str):
|
|||||||
if not result.passing:
|
if not result.passing:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not trigger.group:
|
|
||||||
LOGGER.debug("e(trigger): trigger has no group", trigger=trigger)
|
|
||||||
return
|
|
||||||
|
|
||||||
LOGGER.debug("e(trigger): event trigger matched", trigger=trigger)
|
LOGGER.debug("e(trigger): event trigger matched", trigger=trigger)
|
||||||
# Create the notification objects
|
# Create the notification objects
|
||||||
for transport in trigger.transports.all():
|
for transport in trigger.transports.all():
|
||||||
for user in trigger.group.users.all():
|
for user in trigger.destination_users(event):
|
||||||
LOGGER.debug("created notification")
|
LOGGER.debug("created notification")
|
||||||
notification_transport.apply_async(
|
notification_transport.apply_async(
|
||||||
args=[
|
args=[
|
||||||
|
@ -6,6 +6,7 @@ from django.urls import reverse
|
|||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from authentik.core.models import Group, User
|
from authentik.core.models import Group, User
|
||||||
|
from authentik.core.tests.utils import create_test_user
|
||||||
from authentik.events.models import (
|
from authentik.events.models import (
|
||||||
Event,
|
Event,
|
||||||
EventAction,
|
EventAction,
|
||||||
@ -34,7 +35,7 @@ class TestEventsNotifications(APITestCase):
|
|||||||
def test_trigger_empty(self):
|
def test_trigger_empty(self):
|
||||||
"""Test trigger without any policies attached"""
|
"""Test trigger without any policies attached"""
|
||||||
transport = NotificationTransport.objects.create(name=generate_id())
|
transport = NotificationTransport.objects.create(name=generate_id())
|
||||||
trigger = NotificationRule.objects.create(name=generate_id(), group=self.group)
|
trigger = NotificationRule.objects.create(name=generate_id(), destination_group=self.group)
|
||||||
trigger.transports.add(transport)
|
trigger.transports.add(transport)
|
||||||
trigger.save()
|
trigger.save()
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ class TestEventsNotifications(APITestCase):
|
|||||||
def test_trigger_single(self):
|
def test_trigger_single(self):
|
||||||
"""Test simple transport triggering"""
|
"""Test simple transport triggering"""
|
||||||
transport = NotificationTransport.objects.create(name=generate_id())
|
transport = NotificationTransport.objects.create(name=generate_id())
|
||||||
trigger = NotificationRule.objects.create(name=generate_id(), group=self.group)
|
trigger = NotificationRule.objects.create(name=generate_id(), destination_group=self.group)
|
||||||
trigger.transports.add(transport)
|
trigger.transports.add(transport)
|
||||||
trigger.save()
|
trigger.save()
|
||||||
matcher = EventMatcherPolicy.objects.create(
|
matcher = EventMatcherPolicy.objects.create(
|
||||||
@ -59,6 +60,25 @@ class TestEventsNotifications(APITestCase):
|
|||||||
Event.new(EventAction.CUSTOM_PREFIX).save()
|
Event.new(EventAction.CUSTOM_PREFIX).save()
|
||||||
self.assertEqual(execute_mock.call_count, 1)
|
self.assertEqual(execute_mock.call_count, 1)
|
||||||
|
|
||||||
|
def test_trigger_event_user(self):
|
||||||
|
"""Test trigger with event user"""
|
||||||
|
user = create_test_user()
|
||||||
|
transport = NotificationTransport.objects.create(name=generate_id())
|
||||||
|
trigger = NotificationRule.objects.create(name=generate_id(), destination_event_user=True)
|
||||||
|
trigger.transports.add(transport)
|
||||||
|
trigger.save()
|
||||||
|
matcher = EventMatcherPolicy.objects.create(
|
||||||
|
name="matcher", action=EventAction.CUSTOM_PREFIX
|
||||||
|
)
|
||||||
|
PolicyBinding.objects.create(target=trigger, policy=matcher, order=0)
|
||||||
|
|
||||||
|
execute_mock = MagicMock()
|
||||||
|
with patch("authentik.events.models.NotificationTransport.send", execute_mock):
|
||||||
|
Event.new(EventAction.CUSTOM_PREFIX).set_user(user).save()
|
||||||
|
self.assertEqual(execute_mock.call_count, 1)
|
||||||
|
notification: Notification = execute_mock.call_args[0][0]
|
||||||
|
self.assertEqual(notification.user, user)
|
||||||
|
|
||||||
def test_trigger_no_group(self):
|
def test_trigger_no_group(self):
|
||||||
"""Test trigger without group"""
|
"""Test trigger without group"""
|
||||||
trigger = NotificationRule.objects.create(name=generate_id())
|
trigger = NotificationRule.objects.create(name=generate_id())
|
||||||
@ -76,7 +96,7 @@ class TestEventsNotifications(APITestCase):
|
|||||||
"""Test Policy error which would cause recursion"""
|
"""Test Policy error which would cause recursion"""
|
||||||
transport = NotificationTransport.objects.create(name=generate_id())
|
transport = NotificationTransport.objects.create(name=generate_id())
|
||||||
NotificationRule.objects.filter(name__startswith="default").delete()
|
NotificationRule.objects.filter(name__startswith="default").delete()
|
||||||
trigger = NotificationRule.objects.create(name=generate_id(), group=self.group)
|
trigger = NotificationRule.objects.create(name=generate_id(), destination_group=self.group)
|
||||||
trigger.transports.add(transport)
|
trigger.transports.add(transport)
|
||||||
trigger.save()
|
trigger.save()
|
||||||
matcher = EventMatcherPolicy.objects.create(
|
matcher = EventMatcherPolicy.objects.create(
|
||||||
@ -99,7 +119,7 @@ class TestEventsNotifications(APITestCase):
|
|||||||
|
|
||||||
transport = NotificationTransport.objects.create(name=generate_id(), send_once=True)
|
transport = NotificationTransport.objects.create(name=generate_id(), send_once=True)
|
||||||
NotificationRule.objects.filter(name__startswith="default").delete()
|
NotificationRule.objects.filter(name__startswith="default").delete()
|
||||||
trigger = NotificationRule.objects.create(name=generate_id(), group=self.group)
|
trigger = NotificationRule.objects.create(name=generate_id(), destination_group=self.group)
|
||||||
trigger.transports.add(transport)
|
trigger.transports.add(transport)
|
||||||
trigger.save()
|
trigger.save()
|
||||||
matcher = EventMatcherPolicy.objects.create(
|
matcher = EventMatcherPolicy.objects.create(
|
||||||
@ -123,7 +143,7 @@ class TestEventsNotifications(APITestCase):
|
|||||||
name=generate_id(), webhook_mapping_body=mapping, mode=TransportMode.LOCAL
|
name=generate_id(), webhook_mapping_body=mapping, mode=TransportMode.LOCAL
|
||||||
)
|
)
|
||||||
NotificationRule.objects.filter(name__startswith="default").delete()
|
NotificationRule.objects.filter(name__startswith="default").delete()
|
||||||
trigger = NotificationRule.objects.create(name=generate_id(), group=self.group)
|
trigger = NotificationRule.objects.create(name=generate_id(), destination_group=self.group)
|
||||||
trigger.transports.add(transport)
|
trigger.transports.add(transport)
|
||||||
matcher = EventMatcherPolicy.objects.create(
|
matcher = EventMatcherPolicy.objects.create(
|
||||||
name="matcher", action=EventAction.CUSTOM_PREFIX
|
name="matcher", action=EventAction.CUSTOM_PREFIX
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
"""Websocket tests"""
|
"""Websocket tests"""
|
||||||
|
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from channels.routing import URLRouter
|
from channels.routing import URLRouter
|
||||||
from channels.testing import WebsocketCommunicator
|
from channels.testing import WebsocketCommunicator
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
from django.test import TransactionTestCase
|
from django.test import TransactionTestCase
|
||||||
|
|
||||||
from authentik import __version__
|
from authentik import __version__
|
||||||
@ -16,12 +14,6 @@ from authentik.providers.proxy.models import ProxyProvider
|
|||||||
from authentik.root import websocket
|
from authentik.root import websocket
|
||||||
|
|
||||||
|
|
||||||
def patched__get_ct_cached(app_label, codename):
|
|
||||||
"""Caches `ContentType` instances like its `QuerySet` does."""
|
|
||||||
return ContentType.objects.get(app_label=app_label, permission__codename=codename)
|
|
||||||
|
|
||||||
|
|
||||||
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
|
|
||||||
class TestOutpostWS(TransactionTestCase):
|
class TestOutpostWS(TransactionTestCase):
|
||||||
"""Websocket tests"""
|
"""Websocket tests"""
|
||||||
|
|
||||||
|
@ -387,8 +387,7 @@ class TestAuthorize(OAuthTestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
response.url,
|
response.url,
|
||||||
(
|
(
|
||||||
f"http://localhost#access_token={token.token}"
|
f"http://localhost#id_token={provider.encode(token.id_token.to_dict())}"
|
||||||
f"&id_token={provider.encode(token.id_token.to_dict())}"
|
|
||||||
f"&token_type={TOKEN_TYPE}"
|
f"&token_type={TOKEN_TYPE}"
|
||||||
f"&expires_in={int(expires)}&state={state}"
|
f"&expires_in={int(expires)}&state={state}"
|
||||||
),
|
),
|
||||||
@ -563,7 +562,6 @@ class TestAuthorize(OAuthTestCase):
|
|||||||
"url": "http://localhost",
|
"url": "http://localhost",
|
||||||
"title": f"Redirecting to {app.name}...",
|
"title": f"Redirecting to {app.name}...",
|
||||||
"attrs": {
|
"attrs": {
|
||||||
"access_token": token.token,
|
|
||||||
"id_token": provider.encode(token.id_token.to_dict()),
|
"id_token": provider.encode(token.id_token.to_dict()),
|
||||||
"token_type": TOKEN_TYPE,
|
"token_type": TOKEN_TYPE,
|
||||||
"expires_in": "3600",
|
"expires_in": "3600",
|
||||||
|
@ -150,12 +150,12 @@ class OAuthAuthorizationParams:
|
|||||||
self.check_redirect_uri()
|
self.check_redirect_uri()
|
||||||
self.check_grant()
|
self.check_grant()
|
||||||
self.check_scope(github_compat)
|
self.check_scope(github_compat)
|
||||||
self.check_nonce()
|
|
||||||
self.check_code_challenge()
|
|
||||||
if self.request:
|
if self.request:
|
||||||
raise AuthorizeError(
|
raise AuthorizeError(
|
||||||
self.redirect_uri, "request_not_supported", self.grant_type, self.state
|
self.redirect_uri, "request_not_supported", self.grant_type, self.state
|
||||||
)
|
)
|
||||||
|
self.check_nonce()
|
||||||
|
self.check_code_challenge()
|
||||||
|
|
||||||
def check_grant(self):
|
def check_grant(self):
|
||||||
"""Check grant"""
|
"""Check grant"""
|
||||||
@ -630,7 +630,6 @@ class OAuthFulfillmentStage(StageView):
|
|||||||
if self.params.response_type in [
|
if self.params.response_type in [
|
||||||
ResponseTypes.ID_TOKEN_TOKEN,
|
ResponseTypes.ID_TOKEN_TOKEN,
|
||||||
ResponseTypes.CODE_ID_TOKEN_TOKEN,
|
ResponseTypes.CODE_ID_TOKEN_TOKEN,
|
||||||
ResponseTypes.ID_TOKEN,
|
|
||||||
ResponseTypes.CODE_TOKEN,
|
ResponseTypes.CODE_TOKEN,
|
||||||
]:
|
]:
|
||||||
query_fragment["access_token"] = token.token
|
query_fragment["access_token"] = token.token
|
||||||
|
@ -49,6 +49,7 @@ class TestEndpointsAPI(APITestCase):
|
|||||||
self.assertJSONEqual(
|
self.assertJSONEqual(
|
||||||
response.content.decode(),
|
response.content.decode(),
|
||||||
{
|
{
|
||||||
|
"autocomplete": {},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"next": 0,
|
"next": 0,
|
||||||
"previous": 0,
|
"previous": 0,
|
||||||
@ -101,6 +102,7 @@ class TestEndpointsAPI(APITestCase):
|
|||||||
self.assertJSONEqual(
|
self.assertJSONEqual(
|
||||||
response.content.decode(),
|
response.content.decode(),
|
||||||
{
|
{
|
||||||
|
"autocomplete": {},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"next": 0,
|
"next": 0,
|
||||||
"previous": 0,
|
"previous": 0,
|
||||||
|
@ -20,6 +20,9 @@ from authentik.lib.utils.time import timedelta_from_string
|
|||||||
from authentik.policies.engine import PolicyEngine
|
from authentik.policies.engine import PolicyEngine
|
||||||
from authentik.policies.views import PolicyAccessView
|
from authentik.policies.views import PolicyAccessView
|
||||||
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
|
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
|
||||||
|
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
|
||||||
|
|
||||||
|
PLAN_CONNECTION_SETTINGS = "connection_settings"
|
||||||
|
|
||||||
|
|
||||||
class RACStartView(PolicyAccessView):
|
class RACStartView(PolicyAccessView):
|
||||||
@ -109,10 +112,15 @@ class RACFinalStage(RedirectStage):
|
|||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_challenge(self, *args, **kwargs) -> RedirectChallenge:
|
def get_challenge(self, *args, **kwargs) -> RedirectChallenge:
|
||||||
|
settings = self.executor.plan.context.get(PLAN_CONNECTION_SETTINGS)
|
||||||
|
if not settings:
|
||||||
|
settings = self.executor.plan.context.get(PLAN_CONTEXT_PROMPT, {}).get(
|
||||||
|
PLAN_CONNECTION_SETTINGS
|
||||||
|
)
|
||||||
token = ConnectionToken.objects.create(
|
token = ConnectionToken.objects.create(
|
||||||
provider=self.provider,
|
provider=self.provider,
|
||||||
endpoint=self.endpoint,
|
endpoint=self.endpoint,
|
||||||
settings=self.executor.plan.context.get("connection_settings", {}),
|
settings=settings or {},
|
||||||
session=self.request.session["authenticatedsession"],
|
session=self.request.session["authenticatedsession"],
|
||||||
expires=now() + timedelta_from_string(self.provider.connection_expiry),
|
expires=now() + timedelta_from_string(self.provider.connection_expiry),
|
||||||
expiring=True,
|
expiring=True,
|
||||||
|
@ -44,6 +44,7 @@ class TestRBACRoleAPI(APITestCase):
|
|||||||
self.assertJSONEqual(
|
self.assertJSONEqual(
|
||||||
res.content.decode(),
|
res.content.decode(),
|
||||||
{
|
{
|
||||||
|
"autocomplete": {},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"next": 0,
|
"next": 0,
|
||||||
"previous": 0,
|
"previous": 0,
|
||||||
|
@ -46,6 +46,7 @@ class TestRBACUserAPI(APITestCase):
|
|||||||
self.assertJSONEqual(
|
self.assertJSONEqual(
|
||||||
res.content.decode(),
|
res.content.decode(),
|
||||||
{
|
{
|
||||||
|
"autocomplete": {},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"next": 0,
|
"next": 0,
|
||||||
"previous": 0,
|
"previous": 0,
|
||||||
|
@ -38,6 +38,7 @@ class TestAPIPerms(APITestCase):
|
|||||||
self.assertJSONEqual(
|
self.assertJSONEqual(
|
||||||
res.content.decode(),
|
res.content.decode(),
|
||||||
{
|
{
|
||||||
|
"autocomplete": {},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"next": 0,
|
"next": 0,
|
||||||
"previous": 0,
|
"previous": 0,
|
||||||
@ -73,6 +74,7 @@ class TestAPIPerms(APITestCase):
|
|||||||
self.assertJSONEqual(
|
self.assertJSONEqual(
|
||||||
res.content.decode(),
|
res.content.decode(),
|
||||||
{
|
{
|
||||||
|
"autocomplete": {},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"next": 0,
|
"next": 0,
|
||||||
"previous": 0,
|
"previous": 0,
|
||||||
|
@ -9,13 +9,14 @@ https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
|
|||||||
|
|
||||||
import django
|
import django
|
||||||
from channels.routing import ProtocolTypeRouter, URLRouter
|
from channels.routing import ProtocolTypeRouter, URLRouter
|
||||||
from defusedxml import defuse_stdlib
|
|
||||||
from django.core.asgi import get_asgi_application
|
from django.core.asgi import get_asgi_application
|
||||||
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
|
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
|
||||||
|
|
||||||
|
from authentik.root.setup import setup
|
||||||
|
|
||||||
# DJANGO_SETTINGS_MODULE is set in gunicorn.conf.py
|
# DJANGO_SETTINGS_MODULE is set in gunicorn.conf.py
|
||||||
|
|
||||||
defuse_stdlib()
|
setup()
|
||||||
django.setup()
|
django.setup()
|
||||||
|
|
||||||
|
|
||||||
|
@ -446,6 +446,8 @@ _DISALLOWED_ITEMS = [
|
|||||||
"MIDDLEWARE",
|
"MIDDLEWARE",
|
||||||
"AUTHENTICATION_BACKENDS",
|
"AUTHENTICATION_BACKENDS",
|
||||||
"CELERY",
|
"CELERY",
|
||||||
|
"SPECTACULAR_SETTINGS",
|
||||||
|
"REST_FRAMEWORK",
|
||||||
]
|
]
|
||||||
|
|
||||||
SILENCED_SYSTEM_CHECKS = [
|
SILENCED_SYSTEM_CHECKS = [
|
||||||
@ -468,6 +470,8 @@ def _update_settings(app_path: str):
|
|||||||
TENANT_APPS.extend(getattr(settings_module, "TENANT_APPS", []))
|
TENANT_APPS.extend(getattr(settings_module, "TENANT_APPS", []))
|
||||||
MIDDLEWARE.extend(getattr(settings_module, "MIDDLEWARE", []))
|
MIDDLEWARE.extend(getattr(settings_module, "MIDDLEWARE", []))
|
||||||
AUTHENTICATION_BACKENDS.extend(getattr(settings_module, "AUTHENTICATION_BACKENDS", []))
|
AUTHENTICATION_BACKENDS.extend(getattr(settings_module, "AUTHENTICATION_BACKENDS", []))
|
||||||
|
SPECTACULAR_SETTINGS.update(getattr(settings_module, "SPECTACULAR_SETTINGS", {}))
|
||||||
|
REST_FRAMEWORK.update(getattr(settings_module, "REST_FRAMEWORK", {}))
|
||||||
CELERY["beat_schedule"].update(getattr(settings_module, "CELERY_BEAT_SCHEDULE", {}))
|
CELERY["beat_schedule"].update(getattr(settings_module, "CELERY_BEAT_SCHEDULE", {}))
|
||||||
for _attr in dir(settings_module):
|
for _attr in dir(settings_module):
|
||||||
if not _attr.startswith("__") and _attr not in _DISALLOWED_ITEMS:
|
if not _attr.startswith("__") and _attr not in _DISALLOWED_ITEMS:
|
||||||
|
26
authentik/root/setup.py
Normal file
26
authentik/root/setup.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import os
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
from cryptography.hazmat.backends.openssl.backend import backend
|
||||||
|
from defusedxml import defuse_stdlib
|
||||||
|
|
||||||
|
from authentik.lib.config import CONFIG
|
||||||
|
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
warnings.filterwarnings("ignore", "SelectableGroups dict interface")
|
||||||
|
warnings.filterwarnings(
|
||||||
|
"ignore",
|
||||||
|
"defusedxml.lxml is no longer supported and will be removed in a future release.",
|
||||||
|
)
|
||||||
|
warnings.filterwarnings(
|
||||||
|
"ignore",
|
||||||
|
"defusedxml.cElementTree is deprecated, import from defusedxml.ElementTree instead.",
|
||||||
|
)
|
||||||
|
|
||||||
|
defuse_stdlib()
|
||||||
|
|
||||||
|
if CONFIG.get_bool("compliance.fips.enabled", False):
|
||||||
|
backend._enable_fips()
|
||||||
|
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
|
@ -3,21 +3,38 @@
|
|||||||
import os
|
import os
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.test.runner import DiscoverRunner
|
from django.test.runner import DiscoverRunner
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
from authentik.lib.config import CONFIG
|
from authentik.lib.config import CONFIG
|
||||||
from authentik.lib.sentry import sentry_init
|
from authentik.lib.sentry import sentry_init
|
||||||
from authentik.root.signals import post_startup, pre_startup, startup
|
from authentik.root.signals import post_startup, pre_startup, startup
|
||||||
from tests.e2e.utils import get_docker_tag
|
|
||||||
|
|
||||||
# globally set maxDiff to none to show full assert error
|
# globally set maxDiff to none to show full assert error
|
||||||
TestCase.maxDiff = None
|
TestCase.maxDiff = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_docker_tag() -> str:
|
||||||
|
"""Get docker-tag based off of CI variables"""
|
||||||
|
env_pr_branch = "GITHUB_HEAD_REF"
|
||||||
|
default_branch = "GITHUB_REF"
|
||||||
|
branch_name = os.environ.get(default_branch, "main")
|
||||||
|
if os.environ.get(env_pr_branch, "") != "":
|
||||||
|
branch_name = os.environ[env_pr_branch]
|
||||||
|
branch_name = branch_name.replace("refs/heads/", "").replace("/", "-")
|
||||||
|
return f"gh-{branch_name}"
|
||||||
|
|
||||||
|
|
||||||
|
def patched__get_ct_cached(app_label, codename):
|
||||||
|
"""Caches `ContentType` instances like its `QuerySet` does."""
|
||||||
|
return ContentType.objects.get(app_label=app_label, permission__codename=codename)
|
||||||
|
|
||||||
|
|
||||||
class PytestTestRunner(DiscoverRunner): # pragma: no cover
|
class PytestTestRunner(DiscoverRunner): # pragma: no cover
|
||||||
"""Runs pytest to discover and run tests."""
|
"""Runs pytest to discover and run tests."""
|
||||||
|
|
||||||
@ -149,6 +166,7 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
self.logger.info("Running tests", test_files=self.args)
|
self.logger.info("Running tests", test_files=self.args)
|
||||||
|
with patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached):
|
||||||
try:
|
try:
|
||||||
return pytest.main(self.args)
|
return pytest.main(self.args)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
File diff suppressed because one or more lines are too long
12602
blueprints/schema.json
12602
blueprints/schema.json
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- redis:/data
|
- redis:/data
|
||||||
server:
|
server:
|
||||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.1}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.2}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: server
|
command: server
|
||||||
environment:
|
environment:
|
||||||
@ -55,7 +55,7 @@ services:
|
|||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
worker:
|
worker:
|
||||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.1}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.2}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: worker
|
command: worker
|
||||||
environment:
|
environment:
|
||||||
|
4
go.mod
4
go.mod
@ -18,7 +18,7 @@ require (
|
|||||||
github.com/gorilla/sessions v1.4.0
|
github.com/gorilla/sessions v1.4.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/grafana/pyroscope-go v1.2.2
|
github.com/grafana/pyroscope-go v1.2.2
|
||||||
github.com/jellydator/ttlcache/v3 v3.3.0
|
github.com/jellydator/ttlcache/v3 v3.4.0
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
|
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
|
||||||
github.com/pires/go-proxyproto v0.8.1
|
github.com/pires/go-proxyproto v0.8.1
|
||||||
@ -29,7 +29,7 @@ require (
|
|||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.9.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/wwt/guac v1.3.2
|
github.com/wwt/guac v1.3.2
|
||||||
goauthentik.io/api/v3 v3.2025061.2
|
goauthentik.io/api/v3 v3.2025062.3
|
||||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
|
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
|
||||||
golang.org/x/oauth2 v0.30.0
|
golang.org/x/oauth2 v0.30.0
|
||||||
golang.org/x/sync v0.15.0
|
golang.org/x/sync v0.15.0
|
||||||
|
8
go.sum
8
go.sum
@ -203,8 +203,8 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
|
|||||||
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
||||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||||
github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc=
|
github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP4mnWdTY=
|
||||||
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
|
github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
@ -298,8 +298,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
|
|||||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
goauthentik.io/api/v3 v3.2025061.2 h1:bKmrl82Gz6J8lz3f+QIH9g+MEkl3MvkMXF34GktesA0=
|
goauthentik.io/api/v3 v3.2025062.3 h1:syBOKigaHyX/8Rwmh9kOSF+TzsxOzmP5i7rsFwbemzA=
|
||||||
goauthentik.io/api/v3 v3.2025061.2/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
goauthentik.io/api/v3 v3.2025062.3/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
@ -33,4 +33,4 @@ func UserAgent() string {
|
|||||||
return fmt.Sprintf("authentik@%s", FullVersion())
|
return fmt.Sprintf("authentik@%s", FullVersion())
|
||||||
}
|
}
|
||||||
|
|
||||||
const VERSION = "2025.6.1"
|
const VERSION = "2025.6.2"
|
||||||
|
8
lifecycle/aws/package-lock.json
generated
8
lifecycle/aws/package-lock.json
generated
@ -9,7 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"aws-cdk": "^2.1018.0",
|
"aws-cdk": "^2.1018.1",
|
||||||
"cross-env": "^7.0.3"
|
"cross-env": "^7.0.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -17,9 +17,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/aws-cdk": {
|
"node_modules/aws-cdk": {
|
||||||
"version": "2.1018.0",
|
"version": "2.1018.1",
|
||||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1018.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1018.1.tgz",
|
||||||
"integrity": "sha512-sppVsNtFJTW4wawS/PBudHCSNHb8xwaZ2WX1mpsfwaPNyTWm0eSUVJsRbRiRBu9O/Us8pgrd4woUjfM1lgD7Kw==",
|
"integrity": "sha512-kFPRox5kSm+ktJ451o0ng9rD+60p5Kt1CZIWw8kXnvqbsxN2xv6qbmyWSXw7sGVXVwqrRKVj+71/JeDr+LMAZw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"aws-cdk": "^2.1018.0",
|
"aws-cdk": "^2.1018.1",
|
||||||
"cross-env": "^7.0.3"
|
"cross-env": "^7.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ Parameters:
|
|||||||
Description: authentik Docker image
|
Description: authentik Docker image
|
||||||
AuthentikVersion:
|
AuthentikVersion:
|
||||||
Type: String
|
Type: String
|
||||||
Default: 2025.6.1
|
Default: 2025.6.2
|
||||||
Description: authentik Docker image tag
|
Description: authentik Docker image tag
|
||||||
AuthentikServerCPU:
|
AuthentikServerCPU:
|
||||||
Type: Number
|
Type: Number
|
||||||
|
@ -7,8 +7,6 @@ from pathlib import Path
|
|||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from cryptography.hazmat.backends.openssl.backend import backend
|
|
||||||
from defusedxml import defuse_stdlib
|
|
||||||
from prometheus_client.values import MultiProcessValue
|
from prometheus_client.values import MultiProcessValue
|
||||||
|
|
||||||
from authentik import get_full_version
|
from authentik import get_full_version
|
||||||
@ -18,6 +16,7 @@ from authentik.lib.logging import get_logger_config
|
|||||||
from authentik.lib.utils.http import get_http_session
|
from authentik.lib.utils.http import get_http_session
|
||||||
from authentik.lib.utils.reflection import get_env
|
from authentik.lib.utils.reflection import get_env
|
||||||
from authentik.root.install_id import get_install_id_raw
|
from authentik.root.install_id import get_install_id_raw
|
||||||
|
from authentik.root.setup import setup
|
||||||
from lifecycle.migrate import run_migrations
|
from lifecycle.migrate import run_migrations
|
||||||
from lifecycle.wait_for_db import wait_for_db
|
from lifecycle.wait_for_db import wait_for_db
|
||||||
from lifecycle.worker import DjangoUvicornWorker
|
from lifecycle.worker import DjangoUvicornWorker
|
||||||
@ -28,10 +27,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
from authentik.root.asgi import AuthentikAsgi
|
from authentik.root.asgi import AuthentikAsgi
|
||||||
|
|
||||||
defuse_stdlib()
|
setup()
|
||||||
|
|
||||||
if CONFIG.get_bool("compliance.fips.enabled", False):
|
|
||||||
backend._enable_fips()
|
|
||||||
|
|
||||||
wait_for_db()
|
wait_for_db()
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-06-04 00:12+0000\n"
|
"POT-Creation-Date: 2025-06-19 00:10+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -763,6 +763,12 @@ msgid ""
|
|||||||
"If left empty, Notification won't ben sent."
|
"If left empty, Notification won't ben sent."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/events/models.py
|
||||||
|
msgid ""
|
||||||
|
"When enabled, notification will be sent to user the user that triggered the "
|
||||||
|
"event.When destination_group is configured, notification is sent to both."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/events/models.py
|
#: authentik/events/models.py
|
||||||
msgid "Notification Rule"
|
msgid "Notification Rule"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -6,18 +6,18 @@
|
|||||||
# Translators:
|
# Translators:
|
||||||
# jcamat, 2022
|
# jcamat, 2022
|
||||||
# Angel, 2024
|
# Angel, 2024
|
||||||
# Iamanaws, 2024
|
|
||||||
# Marcelo Elizeche Landó, 2025
|
# Marcelo Elizeche Landó, 2025
|
||||||
# Jens L. <jens@goauthentik.io>, 2025
|
# Jens L. <jens@goauthentik.io>, 2025
|
||||||
|
# Iamanaws, 2025
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
"POT-Creation-Date: 2025-06-04 00:12+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
"Last-Translator: Iamanaws, 2025\n"
|
||||||
"Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n"
|
"Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@ -111,7 +111,7 @@ msgstr "Certificado Web usado por el servidor web Core de authentik"
|
|||||||
|
|
||||||
#: authentik/brands/models.py
|
#: authentik/brands/models.py
|
||||||
msgid "Certificates used for client authentication."
|
msgid "Certificates used for client authentication."
|
||||||
msgstr ""
|
msgstr "Certificados utilizados para la autenticación del cliente."
|
||||||
|
|
||||||
#: authentik/brands/models.py
|
#: authentik/brands/models.py
|
||||||
msgid "Brand"
|
msgid "Brand"
|
||||||
@ -131,7 +131,7 @@ msgstr "Descripción adicional no disponible."
|
|||||||
|
|
||||||
#: authentik/core/api/groups.py
|
#: authentik/core/api/groups.py
|
||||||
msgid "Cannot set group as parent of itself."
|
msgid "Cannot set group as parent of itself."
|
||||||
msgstr "No se puede establecer el grupo como padre de sí mismo."
|
msgstr "No se puede establecer un grupo como su propio padre."
|
||||||
|
|
||||||
#: authentik/core/api/providers.py
|
#: authentik/core/api/providers.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -183,11 +183,11 @@ msgstr "Remueve usuario del grupo"
|
|||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Enable superuser status"
|
msgid "Enable superuser status"
|
||||||
msgstr "Habiliar estado de \"superusuario\""
|
msgstr "Habilitar el estado de superusuario"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Disable superuser status"
|
msgid "Disable superuser status"
|
||||||
msgstr "Deshabiliar estado de \"superusuario\""
|
msgstr "Deshabilitar el estado de superusuario"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "User's display name."
|
msgid "User's display name."
|
||||||
@ -241,7 +241,7 @@ msgstr "Flujo utilizado al autorizar a este proveedor."
|
|||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Flow used ending the session from a provider."
|
msgid "Flow used ending the session from a provider."
|
||||||
msgstr "Flujo usado para terminar la sesión de un proveedor."
|
msgstr "Flujo utilizado para finalizar la sesión desde un proveedor."
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -273,11 +273,11 @@ msgstr "Aplicaciones"
|
|||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Application Entitlement"
|
msgid "Application Entitlement"
|
||||||
msgstr ""
|
msgstr "Derecho de Aplicación"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Application Entitlements"
|
msgid "Application Entitlements"
|
||||||
msgstr ""
|
msgstr "Derechos de Aplicación"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Use the source-specific identifier"
|
msgid "Use the source-specific identifier"
|
||||||
@ -288,9 +288,9 @@ msgid ""
|
|||||||
"Link to a user with identical email address. Can have security implications "
|
"Link to a user with identical email address. Can have security implications "
|
||||||
"when a source doesn't validate email addresses."
|
"when a source doesn't validate email addresses."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Apunta a un usuario con una dirección de correo electrónico idéntica. Puede "
|
"Enlace a un usuario con la misma dirección de correo electrónico. Puede "
|
||||||
"tener implicaciones de seguridad cuando una fuente no valida la dirección de"
|
"tener implicaciones de seguridad cuando una fuente no valida las direcciones"
|
||||||
" correo electrónico."
|
" de correo electrónico."
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -305,8 +305,8 @@ msgid ""
|
|||||||
"Link to a user with identical username. Can have security implications when "
|
"Link to a user with identical username. Can have security implications when "
|
||||||
"a username is used with another source."
|
"a username is used with another source."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Enlace a un usuario con un nombre de usuario idéntico. Puede tener "
|
"Enlace a un usuario con el mismo nombre de usuario. Puede tener "
|
||||||
"implicaciones de seguridad cuando se usa un nombre de usuario con otra "
|
"implicaciones de seguridad cuando un nombre de usuario se utiliza con otra "
|
||||||
"fuente."
|
"fuente."
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
@ -322,8 +322,8 @@ msgid ""
|
|||||||
"Link to a group with identical name. Can have security implications when a "
|
"Link to a group with identical name. Can have security implications when a "
|
||||||
"group name is used with another source."
|
"group name is used with another source."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Enlace a un grupo con un nombre idéntico. Puede tener implicaciones de "
|
"Enlace a un grupo con el mismo nombre. Puede tener implicaciones de "
|
||||||
"seguridad cuando se utiliza un nombre de grupo con otra fuente."
|
"seguridad cuando un nombre de grupo se utiliza con otra fuente."
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Use the group name, but deny enrollment when the name already exists."
|
msgid "Use the group name, but deny enrollment when the name already exists."
|
||||||
@ -385,7 +385,7 @@ msgstr "Asignaciones de Propiedades"
|
|||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "session data"
|
msgid "session data"
|
||||||
msgstr ""
|
msgstr "datos de sesión"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Session"
|
msgid "Session"
|
||||||
@ -424,7 +424,7 @@ msgstr "¡Autenticado exitosamente con {source}!"
|
|||||||
#: authentik/core/sources/flow_manager.py
|
#: authentik/core/sources/flow_manager.py
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Successfully linked {source}!"
|
msgid "Successfully linked {source}!"
|
||||||
msgstr "¡{source} vinculado exitosamente!"
|
msgstr "¡{source} enlazado correctamente!"
|
||||||
|
|
||||||
#: authentik/core/sources/flow_manager.py
|
#: authentik/core/sources/flow_manager.py
|
||||||
msgid "Source is not configured for enrollment."
|
msgid "Source is not configured for enrollment."
|
||||||
@ -476,11 +476,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: authentik/crypto/models.py
|
#: authentik/crypto/models.py
|
||||||
msgid "Certificate-Key Pair"
|
msgid "Certificate-Key Pair"
|
||||||
msgstr "Par de claves de certificado"
|
msgstr "Par Certificado-Clave"
|
||||||
|
|
||||||
#: authentik/crypto/models.py
|
#: authentik/crypto/models.py
|
||||||
msgid "Certificate-Key Pairs"
|
msgid "Certificate-Key Pairs"
|
||||||
msgstr "Pares de claves de certificado"
|
msgstr "Pares Certificado-Clave"
|
||||||
|
|
||||||
#: authentik/enterprise/api.py
|
#: authentik/enterprise/api.py
|
||||||
msgid "Enterprise is required to create/update this object."
|
msgid "Enterprise is required to create/update this object."
|
||||||
@ -511,7 +511,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: authentik/enterprise/policies/unique_password/models.py
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
msgid "Number of passwords to check against."
|
msgid "Number of passwords to check against."
|
||||||
msgstr ""
|
msgstr "Número de contraseñas contra las que verificar."
|
||||||
|
|
||||||
#: authentik/enterprise/policies/unique_password/models.py
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
@ -521,18 +521,20 @@ msgstr "La contraseña no se ha establecido en contexto"
|
|||||||
#: authentik/enterprise/policies/unique_password/models.py
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
msgid "This password has been used previously. Please choose a different one."
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Esta contraseña se ha utilizado anteriormente. Por favor, elija una "
|
||||||
|
"diferente."
|
||||||
|
|
||||||
#: authentik/enterprise/policies/unique_password/models.py
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
msgid "Password Uniqueness Policy"
|
msgid "Password Uniqueness Policy"
|
||||||
msgstr ""
|
msgstr "Política de Unicidad de Contraseñas"
|
||||||
|
|
||||||
#: authentik/enterprise/policies/unique_password/models.py
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
msgid "Password Uniqueness Policies"
|
msgid "Password Uniqueness Policies"
|
||||||
msgstr ""
|
msgstr "Políticas de Unicidad de Contraseñas"
|
||||||
|
|
||||||
#: authentik/enterprise/policies/unique_password/models.py
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
msgid "User Password History"
|
msgid "User Password History"
|
||||||
msgstr ""
|
msgstr "Historial de Contraseñas del Usuario"
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
@ -617,39 +619,39 @@ msgstr "Clave de firma"
|
|||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
msgid "Key used to sign the SSF Events."
|
msgid "Key used to sign the SSF Events."
|
||||||
msgstr ""
|
msgstr "Clave utilizada para firmar los eventos SSF."
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
msgid "Shared Signals Framework Provider"
|
msgid "Shared Signals Framework Provider"
|
||||||
msgstr ""
|
msgstr "Proveedor del Marco de Señales Compartidas"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
msgid "Shared Signals Framework Providers"
|
msgid "Shared Signals Framework Providers"
|
||||||
msgstr ""
|
msgstr "Proveedores del Marco de Señales Compartidas"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
msgid "Add stream to SSF provider"
|
msgid "Add stream to SSF provider"
|
||||||
msgstr ""
|
msgstr "Agregar flujo de datos al proveedor SSF"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
msgid "SSF Stream"
|
msgid "SSF Stream"
|
||||||
msgstr ""
|
msgstr "Flujo de Datos SSF"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
msgid "SSF Streams"
|
msgid "SSF Streams"
|
||||||
msgstr ""
|
msgstr "Flujos de Datos SSF"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
msgid "SSF Stream Event"
|
msgid "SSF Stream Event"
|
||||||
msgstr ""
|
msgstr "Evento de Flujo de Datos SSF"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
msgid "SSF Stream Events"
|
msgid "SSF Stream Events"
|
||||||
msgstr ""
|
msgstr "Eventos de Flujos de Datos SSF"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/tasks.py
|
#: authentik/enterprise/providers/ssf/tasks.py
|
||||||
msgid "Failed to send request"
|
msgid "Failed to send request"
|
||||||
msgstr "Falló envio de petición"
|
msgstr "Error al enviar la solicitud"
|
||||||
|
|
||||||
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/models.py
|
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/models.py
|
||||||
msgid "Endpoint Authenticator Google Device Trust Connector Stage"
|
msgid "Endpoint Authenticator Google Device Trust Connector Stage"
|
||||||
@ -681,26 +683,29 @@ msgid ""
|
|||||||
"option has a higher priority than the `client_certificate` option on "
|
"option has a higher priority than the `client_certificate` option on "
|
||||||
"`Brand`."
|
"`Brand`."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Configura las autoridades certificadoras para validar el certificado. Esta "
|
||||||
|
"opción tiene una prioridad mayor que la opción `client_certificate` en "
|
||||||
|
"`Brand`."
|
||||||
|
|
||||||
#: authentik/enterprise/stages/mtls/models.py
|
#: authentik/enterprise/stages/mtls/models.py
|
||||||
msgid "Mutual TLS Stage"
|
msgid "Mutual TLS Stage"
|
||||||
msgstr ""
|
msgstr "Etapa de TLS mutuo"
|
||||||
|
|
||||||
#: authentik/enterprise/stages/mtls/models.py
|
#: authentik/enterprise/stages/mtls/models.py
|
||||||
msgid "Mutual TLS Stages"
|
msgid "Mutual TLS Stages"
|
||||||
msgstr ""
|
msgstr "Etapas de TLS mutuo"
|
||||||
|
|
||||||
#: authentik/enterprise/stages/mtls/models.py
|
#: authentik/enterprise/stages/mtls/models.py
|
||||||
msgid "Permissions to pass Certificates for outposts."
|
msgid "Permissions to pass Certificates for outposts."
|
||||||
msgstr ""
|
msgstr "Permisos para pasar Certificados a los puestos avanzados."
|
||||||
|
|
||||||
#: authentik/enterprise/stages/mtls/stage.py
|
#: authentik/enterprise/stages/mtls/stage.py
|
||||||
msgid "Certificate required but no certificate was given."
|
msgid "Certificate required but no certificate was given."
|
||||||
msgstr ""
|
msgstr "Se requiere certificado, pero no se proporcionó ninguno."
|
||||||
|
|
||||||
#: authentik/enterprise/stages/mtls/stage.py
|
#: authentik/enterprise/stages/mtls/stage.py
|
||||||
msgid "No user found for certificate."
|
msgid "No user found for certificate."
|
||||||
msgstr ""
|
msgstr "No se encontró usuario para el certificado."
|
||||||
|
|
||||||
#: authentik/enterprise/stages/source/models.py
|
#: authentik/enterprise/stages/source/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -753,12 +758,16 @@ msgid ""
|
|||||||
"Customize the body of the request. Mapping should return data that is JSON-"
|
"Customize the body of the request. Mapping should return data that is JSON-"
|
||||||
"serializable."
|
"serializable."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Personaliza el cuerpo de la solicitud. El mapeo debe devolver datos que sean"
|
||||||
|
" serializables en JSON."
|
||||||
|
|
||||||
#: authentik/events/models.py
|
#: authentik/events/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"Configure additional headers to be sent. Mapping should return a dictionary "
|
"Configure additional headers to be sent. Mapping should return a dictionary "
|
||||||
"of key-value pairs"
|
"of key-value pairs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Configura encabezados adicionales para enviar. El mapeo debe devolver un "
|
||||||
|
"diccionario de pares clave-valor"
|
||||||
|
|
||||||
#: authentik/events/models.py
|
#: authentik/events/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -786,7 +795,7 @@ msgstr "Transporte de notificaciones"
|
|||||||
|
|
||||||
#: authentik/events/models.py
|
#: authentik/events/models.py
|
||||||
msgid "Notification Transports"
|
msgid "Notification Transports"
|
||||||
msgstr "Transportes de notificación"
|
msgstr "Medios de Notificación"
|
||||||
|
|
||||||
#: authentik/events/models.py
|
#: authentik/events/models.py
|
||||||
msgid "Notice"
|
msgid "Notice"
|
||||||
@ -813,9 +822,9 @@ msgid ""
|
|||||||
"Select which transports should be used to notify the user. If none are "
|
"Select which transports should be used to notify the user. If none are "
|
||||||
"selected, the notification will only be shown in the authentik UI."
|
"selected, the notification will only be shown in the authentik UI."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Seleccione qué transportes se deben usar para notificar al usuario. Si no se"
|
"Selecciona qué medios se deben usar para notificar al usuario. Si no se "
|
||||||
"selecciona ninguno, la notificación solo se mostrará en la interfaz de "
|
"selecciona ninguno, la notificación solo se mostrará en la interfaz de "
|
||||||
"usuario de authentik."
|
"authentik."
|
||||||
|
|
||||||
#: authentik/events/models.py
|
#: authentik/events/models.py
|
||||||
msgid "Controls which severity level the created notifications will have."
|
msgid "Controls which severity level the created notifications will have."
|
||||||
@ -987,7 +996,7 @@ msgstr "Evalúa políticas durante el proceso de planeación del Flujo."
|
|||||||
|
|
||||||
#: authentik/flows/models.py
|
#: authentik/flows/models.py
|
||||||
msgid "Evaluate policies when the Stage is presented to the user."
|
msgid "Evaluate policies when the Stage is presented to the user."
|
||||||
msgstr ""
|
msgstr "Evaluar las políticas cuando la Etapa se presenta al usuario."
|
||||||
|
|
||||||
#: authentik/flows/models.py
|
#: authentik/flows/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -1034,6 +1043,8 @@ msgid ""
|
|||||||
"When enabled, provider will not modify or create objects in the remote "
|
"When enabled, provider will not modify or create objects in the remote "
|
||||||
"system."
|
"system."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Cuando está habilitado, el proveedor no modificará ni creará objetos en el "
|
||||||
|
"sistema remoto."
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
msgid "Starting full provider sync"
|
msgid "Starting full provider sync"
|
||||||
@ -1041,20 +1052,21 @@ msgstr "Iniciando sincronización completa de proveedor"
|
|||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
msgid "Syncing users"
|
msgid "Syncing users"
|
||||||
msgstr ""
|
msgstr "Sincronizando usuarios"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
msgid "Syncing groups"
|
msgid "Syncing groups"
|
||||||
msgstr ""
|
msgstr "Sincronizando grupos"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Syncing page {page} of groups"
|
msgid "Syncing page {page} of {object_type}"
|
||||||
msgstr "Sincronizando página {page} de grupos"
|
msgstr "Sincronizando página {page} de {object_type}"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
msgid "Dropping mutating request due to dry run"
|
msgid "Dropping mutating request due to dry run"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Descartando solicitud de mutación debido a ejecución en modo de simulación"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
@ -1233,7 +1245,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: authentik/policies/expiry/models.py
|
#: authentik/policies/expiry/models.py
|
||||||
msgid "Password has expired."
|
msgid "Password has expired."
|
||||||
msgstr "La contraseña ha caducado."
|
msgstr "La contraseña ha expirado."
|
||||||
|
|
||||||
#: authentik/policies/expiry/models.py
|
#: authentik/policies/expiry/models.py
|
||||||
msgid "Password Expiry Policy"
|
msgid "Password Expiry Policy"
|
||||||
@ -1271,7 +1283,7 @@ msgstr "La IP del cliente no está en un país permitido."
|
|||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
#: authentik/policies/geoip/models.py
|
||||||
msgid "Distance from previous authentication is larger than threshold."
|
msgid "Distance from previous authentication is larger than threshold."
|
||||||
msgstr "La distancia desde la autenticación previa es mayor que el límite."
|
msgstr "La distancia desde la autenticación anterior es mayor que el umbral."
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
#: authentik/policies/geoip/models.py
|
||||||
msgid "Distance is further than possible."
|
msgid "Distance is further than possible."
|
||||||
@ -1320,7 +1332,7 @@ msgstr "Vinculación de Políticas"
|
|||||||
|
|
||||||
#: authentik/policies/models.py
|
#: authentik/policies/models.py
|
||||||
msgid "Policy Bindings"
|
msgid "Policy Bindings"
|
||||||
msgstr "Vinculaciones de políticas"
|
msgstr "Vinculaciones de Políticas"
|
||||||
|
|
||||||
#: authentik/policies/models.py
|
#: authentik/policies/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -1594,11 +1606,11 @@ msgstr "ES256 (Encriptación Asimétrica)"
|
|||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "ES384 (Asymmetric Encryption)"
|
msgid "ES384 (Asymmetric Encryption)"
|
||||||
msgstr ""
|
msgstr "ES384 (Encriptación Asimétrica)"
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "ES512 (Asymmetric Encryption)"
|
msgid "ES512 (Asymmetric Encryption)"
|
||||||
msgstr ""
|
msgstr "ES512 (Encriptación Asimétrica)"
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "Scope used by the client"
|
msgid "Scope used by the client"
|
||||||
@ -1813,7 +1825,7 @@ msgstr "Valida Certificados SSL de servidores de origen"
|
|||||||
|
|
||||||
#: authentik/providers/proxy/models.py
|
#: authentik/providers/proxy/models.py
|
||||||
msgid "Internal host SSL Validation"
|
msgid "Internal host SSL Validation"
|
||||||
msgstr "Validación SSL de host interno"
|
msgstr "Validación SSL del host interno"
|
||||||
|
|
||||||
#: authentik/providers/proxy/models.py
|
#: authentik/providers/proxy/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -2027,7 +2039,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: authentik/providers/saml/models.py
|
#: authentik/providers/saml/models.py
|
||||||
msgid "AuthnContextClassRef Property Mapping"
|
msgid "AuthnContextClassRef Property Mapping"
|
||||||
msgstr ""
|
msgstr "Asignación de Propiedades de AuthnContextClassRef"
|
||||||
|
|
||||||
#: authentik/providers/saml/models.py
|
#: authentik/providers/saml/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -2035,6 +2047,9 @@ msgid ""
|
|||||||
"empty, the AuthnContextClassRef will be set based on which authentication "
|
"empty, the AuthnContextClassRef will be set based on which authentication "
|
||||||
"methods the user used to authenticate."
|
"methods the user used to authenticate."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Configura cómo se creará el valor de AuthnContextClassRef. Si se deja vacío,"
|
||||||
|
" el AuthnContextClassRef se establecerá según los métodos de autenticación "
|
||||||
|
"que el usuario haya utilizado para autenticarse."
|
||||||
|
|
||||||
#: authentik/providers/saml/models.py
|
#: authentik/providers/saml/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -2184,11 +2199,11 @@ msgstr "Predeterminado"
|
|||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "AWS"
|
msgid "AWS"
|
||||||
msgstr ""
|
msgstr "AWS"
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "Slack"
|
msgid "Slack"
|
||||||
msgstr ""
|
msgstr "Slack"
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "Base URL to SCIM requests, usually ends in /v2"
|
msgid "Base URL to SCIM requests, usually ends in /v2"
|
||||||
@ -2200,11 +2215,13 @@ msgstr "Token de Autenticación"
|
|||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "SCIM Compatibility Mode"
|
msgid "SCIM Compatibility Mode"
|
||||||
msgstr ""
|
msgstr "Modo de Compatibilidad SCIM"
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "Alter authentik behavior for vendor-specific SCIM implementations."
|
msgid "Alter authentik behavior for vendor-specific SCIM implementations."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Modificar el comportamiento de authentik para implementaciones SCIM "
|
||||||
|
"específicas de proveedores."
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "SCIM Provider"
|
msgid "SCIM Provider"
|
||||||
@ -2232,7 +2249,7 @@ msgstr "Roles"
|
|||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "Initial Permissions"
|
msgid "Initial Permissions"
|
||||||
msgstr ""
|
msgstr "Permisos Iniciales"
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
@ -2270,7 +2287,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: authentik/recovery/views.py
|
#: authentik/recovery/views.py
|
||||||
msgid "Used recovery-link to authenticate."
|
msgid "Used recovery-link to authenticate."
|
||||||
msgstr "Se usó el enlace de recuperación para autenticarse."
|
msgstr "Se utilizó un enlace de recuperación para autenticarse."
|
||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid "Kerberos realm"
|
msgid "Kerberos realm"
|
||||||
@ -2282,7 +2299,7 @@ msgstr "krb5.conf personalizado a usar. Usa el del sistema por defecto."
|
|||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid "KAdmin server type"
|
msgid "KAdmin server type"
|
||||||
msgstr ""
|
msgstr "Tipo de servidor KAdmin"
|
||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid "Sync users from Kerberos into authentik"
|
msgid "Sync users from Kerberos into authentik"
|
||||||
@ -2290,23 +2307,24 @@ msgstr "Sincronizar usuarios desde Kerberos hacia Authentik"
|
|||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid "When a user changes their password, sync it back to Kerberos"
|
msgid "When a user changes their password, sync it back to Kerberos"
|
||||||
msgstr "Cuando un usuario cambia su contraseña, sincronizarlo hacia Kerberos"
|
msgstr ""
|
||||||
|
"Cuando un usuario cambie su contraseña, sincronizarla de vuelta a Kerberos."
|
||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid "Principal to authenticate to kadmin for sync."
|
msgid "Principal to authenticate to kadmin for sync."
|
||||||
msgstr "Principal para autenticarse como kadmin para la sincronización."
|
msgstr "Principal para autenticarse en kadmin para la sincronización."
|
||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid "Password to authenticate to kadmin for sync"
|
msgid "Password to authenticate to kadmin for sync"
|
||||||
msgstr "Contraseña para autenticarse como kadmin para la sincronización"
|
msgstr "Contraseña para autenticarse en kadmin para la sincronización"
|
||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"Keytab to authenticate to kadmin for sync. Must be base64-encoded or in the "
|
"Keytab to authenticate to kadmin for sync. Must be base64-encoded or in the "
|
||||||
"form TYPE:residual"
|
"form TYPE:residual"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Keytab para autenticarse como kadmin para la sincronización. Debe estar "
|
"Keytab para autenticarse en kadmin para la sincronización. Debe estar "
|
||||||
"codificado en base64 o en el formato TIPO:residual"
|
"codificado en base64 o en el formato TIPO:residuo"
|
||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -2322,7 +2340,7 @@ msgid ""
|
|||||||
"HTTP@hostname"
|
"HTTP@hostname"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Forzar el uso de un nombre de servidor específico para SPNEGO. Debe estar en"
|
"Forzar el uso de un nombre de servidor específico para SPNEGO. Debe estar en"
|
||||||
" el formato HTTP@nombredelservidor"
|
" el formato HTTP@nombre_de_host"
|
||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid "SPNEGO keytab base64-encoded or path to keytab in the form FILE:path"
|
msgid "SPNEGO keytab base64-encoded or path to keytab in the form FILE:path"
|
||||||
@ -2339,8 +2357,8 @@ msgid ""
|
|||||||
"If enabled, the authentik-stored password will be updated upon login with "
|
"If enabled, the authentik-stored password will be updated upon login with "
|
||||||
"the Kerberos password backend"
|
"the Kerberos password backend"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Si está habilitado, la contraseña almacenada por authentik será actualizada "
|
"Si está habilitado, la contraseña almacenada en authentik se actualizará al "
|
||||||
"al iniciar sesión con el backend de contraseñas Kerberos"
|
"iniciar sesión con el backend de contraseñas de Kerberos."
|
||||||
|
|
||||||
#: authentik/sources/kerberos/models.py
|
#: authentik/sources/kerberos/models.py
|
||||||
msgid "Kerberos Source"
|
msgid "Kerberos Source"
|
||||||
@ -2388,7 +2406,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"\n"
|
"\n"
|
||||||
" Asegúrate de que tienes entradas válidas\n"
|
" Asegúrate de que tienes entradas válidas\n"
|
||||||
" (se obtienen a través de kinit) \n"
|
" (obtenibles mediante kinit) \n"
|
||||||
" y de haber configurado correctamente el navegador.\n"
|
" y de haber configurado correctamente el navegador.\n"
|
||||||
" Por favor, contacta a tu administrador.\n"
|
" Por favor, contacta a tu administrador.\n"
|
||||||
" "
|
" "
|
||||||
@ -2453,6 +2471,10 @@ msgstr "DN de grupo de adición"
|
|||||||
msgid "Consider Objects matching this filter to be Users."
|
msgid "Consider Objects matching this filter to be Users."
|
||||||
msgstr "Considere que los objetos que coinciden con este filtro son usuarios."
|
msgstr "Considere que los objetos que coinciden con este filtro son usuarios."
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Attribute which matches the value of `group_membership_field`."
|
||||||
|
msgstr "Atributo que coincide con el valor de `group_membership_field`."
|
||||||
|
|
||||||
#: authentik/sources/ldap/models.py
|
#: authentik/sources/ldap/models.py
|
||||||
msgid "Field which contains members of a group."
|
msgid "Field which contains members of a group."
|
||||||
msgstr "Campo que contiene los miembros de un grupo."
|
msgstr "Campo que contiene los miembros de un grupo."
|
||||||
@ -2485,12 +2507,17 @@ msgid ""
|
|||||||
"attribute. This allows nested group resolution on systems like FreeIPA and "
|
"attribute. This allows nested group resolution on systems like FreeIPA and "
|
||||||
"Active Directory"
|
"Active Directory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Buscar la pertenencia a grupos basándose en un atributo del usuario en lugar"
|
||||||
|
" de un atributo del grupo. Esto permite la resolución de grupos anidados en "
|
||||||
|
"sistemas como FreeIPA y Active Directory"
|
||||||
|
|
||||||
#: authentik/sources/ldap/models.py
|
#: authentik/sources/ldap/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"Delete authentik users and groups which were previously supplied by this "
|
"Delete authentik users and groups which were previously supplied by this "
|
||||||
"source, but are now missing from it."
|
"source, but are now missing from it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Eliminar usuarios y grupos de authentik que fueron proporcionados "
|
||||||
|
"previamente por esta fuente, pero que ahora están ausentes."
|
||||||
|
|
||||||
#: authentik/sources/ldap/models.py
|
#: authentik/sources/ldap/models.py
|
||||||
msgid "LDAP Source"
|
msgid "LDAP Source"
|
||||||
@ -2512,22 +2539,24 @@ msgstr "Asignaciones de Propiedades de Fuente de LDAP"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"Unique ID used while checking if this object still exists in the directory."
|
"Unique ID used while checking if this object still exists in the directory."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"ID único utilizado para verificar si este objeto aún existe en el "
|
||||||
|
"directorio."
|
||||||
|
|
||||||
#: authentik/sources/ldap/models.py
|
#: authentik/sources/ldap/models.py
|
||||||
msgid "User LDAP Source Connection"
|
msgid "User LDAP Source Connection"
|
||||||
msgstr ""
|
msgstr "Conexión de Fuente LDAP de Usuario"
|
||||||
|
|
||||||
#: authentik/sources/ldap/models.py
|
#: authentik/sources/ldap/models.py
|
||||||
msgid "User LDAP Source Connections"
|
msgid "User LDAP Source Connections"
|
||||||
msgstr ""
|
msgstr "Conexiones de Fuente LDAP de Usuario"
|
||||||
|
|
||||||
#: authentik/sources/ldap/models.py
|
#: authentik/sources/ldap/models.py
|
||||||
msgid "Group LDAP Source Connection"
|
msgid "Group LDAP Source Connection"
|
||||||
msgstr ""
|
msgstr "Conexión de Fuente LDAP de Grupo"
|
||||||
|
|
||||||
#: authentik/sources/ldap/models.py
|
#: authentik/sources/ldap/models.py
|
||||||
msgid "Group LDAP Source Connections"
|
msgid "Group LDAP Source Connections"
|
||||||
msgstr ""
|
msgstr "Conexiones de Fuente LDAP de Grupo"
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
@ -2539,11 +2568,11 @@ msgstr "No se recibió ningún token."
|
|||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "HTTP Basic Authentication"
|
msgid "HTTP Basic Authentication"
|
||||||
msgstr ""
|
msgstr "Autenticación Básica HTTP"
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Include the client ID and secret as request parameters"
|
msgid "Include the client ID and secret as request parameters"
|
||||||
msgstr ""
|
msgstr "Incluir el ID de cliente y el secreto como parámetros de la solicitud"
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
@ -2590,6 +2619,8 @@ msgid ""
|
|||||||
"How to perform authentication during an authorization_code token request "
|
"How to perform authentication during an authorization_code token request "
|
||||||
"flow"
|
"flow"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Cómo realizar la autenticación durante un flujo de solicitud de token con "
|
||||||
|
"authorization_code"
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
@ -2907,7 +2938,7 @@ msgstr "Conexiones de Fuente de SAML de Grupo"
|
|||||||
#: authentik/sources/saml/views.py
|
#: authentik/sources/saml/views.py
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Continue to {source_name}"
|
msgid "Continue to {source_name}"
|
||||||
msgstr ""
|
msgstr "Continuar a {source_name}"
|
||||||
|
|
||||||
#: authentik/sources/scim/models.py
|
#: authentik/sources/scim/models.py
|
||||||
msgid "SCIM Source"
|
msgid "SCIM Source"
|
||||||
@ -2943,7 +2974,7 @@ msgstr "Dispositivos Duo"
|
|||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
#: authentik/stages/authenticator_email/models.py
|
||||||
msgid "Email OTP"
|
msgid "Email OTP"
|
||||||
msgstr ""
|
msgstr "OTP por Correo Electrónico"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
#: authentik/stages/authenticator_email/models.py
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
@ -2964,11 +2995,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
#: authentik/stages/authenticator_email/models.py
|
||||||
msgid "Email Authenticator Setup Stage"
|
msgid "Email Authenticator Setup Stage"
|
||||||
msgstr ""
|
msgstr "Etapa de Configuración del Autenticador de Correo Electrónico"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
#: authentik/stages/authenticator_email/models.py
|
||||||
msgid "Email Authenticator Setup Stages"
|
msgid "Email Authenticator Setup Stages"
|
||||||
msgstr ""
|
msgstr "Etapas de Configuración del Autenticador de Correo Electrónico"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
#: authentik/stages/authenticator_email/models.py
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
#: authentik/stages/authenticator_email/stage.py
|
||||||
@ -2979,11 +3010,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
#: authentik/stages/authenticator_email/models.py
|
||||||
msgid "Email Device"
|
msgid "Email Device"
|
||||||
msgstr "Dispositivo de Email"
|
msgstr "Dispositivo de correo electrónico"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
#: authentik/stages/authenticator_email/models.py
|
||||||
msgid "Email Devices"
|
msgid "Email Devices"
|
||||||
msgstr "Dispositivos de Email"
|
msgstr "Dispositivos de correo electrónico"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
#: authentik/stages/authenticator_email/stage.py
|
||||||
#: authentik/stages/authenticator_sms/stage.py
|
#: authentik/stages/authenticator_sms/stage.py
|
||||||
@ -2993,7 +3024,7 @@ msgstr "El código no coincide"
|
|||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
#: authentik/stages/authenticator_email/stage.py
|
||||||
msgid "Invalid email"
|
msgid "Invalid email"
|
||||||
msgstr "Email Inválido"
|
msgstr "Correo electrónico inválido"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
||||||
#: authentik/stages/email/templates/email/password_reset.html
|
#: authentik/stages/email/templates/email/password_reset.html
|
||||||
@ -3013,6 +3044,9 @@ msgid ""
|
|||||||
" Email MFA code.\n"
|
" Email MFA code.\n"
|
||||||
" "
|
" "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
" Código MFA por correo electrónico.\n"
|
||||||
|
" "
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -3022,7 +3056,8 @@ msgid ""
|
|||||||
" "
|
" "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"\n"
|
"\n"
|
||||||
"Si no solicitaste este código, por favor ignora este correo. El código anterior es válido por %(expires)s."
|
" Si no solicitaste este código, por favor ignora este correo. El código anterior es válido por %(expires)s.\n"
|
||||||
|
" "
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
@ -3035,6 +3070,8 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"Email MFA code\n"
|
"Email MFA code\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
"Código MFA por correo electrónico\n"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -3276,8 +3313,8 @@ msgstr "No se pudo validar el token"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)."
|
"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Compensación después de la cual caduca el consentimiento. (Formato: horas = "
|
"Desfase después del cual expira el consentimiento. (Formato: "
|
||||||
"1; minutos = 2; segundos = 3)."
|
"hours=1;minutes=2;seconds=3)."
|
||||||
|
|
||||||
#: authentik/stages/consent/models.py
|
#: authentik/stages/consent/models.py
|
||||||
msgid "Consent Stage"
|
msgid "Consent Stage"
|
||||||
@ -3297,7 +3334,7 @@ msgstr "Consentimientos del usuario"
|
|||||||
|
|
||||||
#: authentik/stages/consent/stage.py
|
#: authentik/stages/consent/stage.py
|
||||||
msgid "Invalid consent token, re-showing prompt"
|
msgid "Invalid consent token, re-showing prompt"
|
||||||
msgstr ""
|
msgstr "Token de consentimiento inválido, mostrando el aviso nuevamente"
|
||||||
|
|
||||||
#: authentik/stages/deny/models.py
|
#: authentik/stages/deny/models.py
|
||||||
msgid "Deny Stage"
|
msgid "Deny Stage"
|
||||||
@ -3317,11 +3354,11 @@ msgstr "Etapas ficticias"
|
|||||||
|
|
||||||
#: authentik/stages/email/flow.py
|
#: authentik/stages/email/flow.py
|
||||||
msgid "Continue to confirm this email address."
|
msgid "Continue to confirm this email address."
|
||||||
msgstr ""
|
msgstr "Continúa para confirmar esta dirección de correo electrónico."
|
||||||
|
|
||||||
#: authentik/stages/email/flow.py
|
#: authentik/stages/email/flow.py
|
||||||
msgid "Link was already used, please request a new link."
|
msgid "Link was already used, please request a new link."
|
||||||
msgstr ""
|
msgstr "El enlace ya fue utilizado, por favor, solícita uno nuevo."
|
||||||
|
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
msgid "Password Reset"
|
msgid "Password Reset"
|
||||||
@ -3445,7 +3482,8 @@ msgid ""
|
|||||||
" "
|
" "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"\n"
|
"\n"
|
||||||
"Si no solicitaste un cambio de contraseña, por favor ignora este correo. El enlace anterior es válido por %(expires)s."
|
" Si no solicitaste un cambio de contraseña, por favor ignora este correo. El enlace anterior es válido por %(expires)s.\n"
|
||||||
|
" "
|
||||||
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -3529,24 +3567,26 @@ msgid ""
|
|||||||
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
" to skip straight to entering their password."
|
" to skip straight to entering their password."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Mostrar al usuario la opción \"Recordarme en este dispositivo\", permitiendo"
|
||||||
|
" que los usuarios recurrentes pasen directamente a ingresar su contraseña."
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Flujo de inscripción opcional, que está vinculado en la parte inferior de la"
|
"Flujo de inscripción opcional, que se enlaza en la parte inferior de la "
|
||||||
"página."
|
"página."
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional recovery flow, which is linked at the bottom of the page."
|
msgid "Optional recovery flow, which is linked at the bottom of the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Flujo de recuperación opcional, que está vinculado en la parte inferior de "
|
"Flujo de recuperación opcional, que se enlaza en la parte inferior de la "
|
||||||
"la página."
|
"página."
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional passwordless flow, which is linked at the bottom of the page."
|
msgid "Optional passwordless flow, which is linked at the bottom of the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Flujo sin contraseña opcional, el cual está vinculado en la parte inferior "
|
"Flujo opcional sin contraseña, que se enlaza en la parte inferior de la "
|
||||||
"de la página."
|
"página."
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Specify which sources should be shown."
|
msgid "Specify which sources should be shown."
|
||||||
@ -3780,11 +3820,11 @@ msgstr "Las contraseñas no coinciden."
|
|||||||
|
|
||||||
#: authentik/stages/redirect/api.py
|
#: authentik/stages/redirect/api.py
|
||||||
msgid "Target URL should be present when mode is Static."
|
msgid "Target URL should be present when mode is Static."
|
||||||
msgstr ""
|
msgstr "La URL de destino debe estar presente cuando el modo es Estático."
|
||||||
|
|
||||||
#: authentik/stages/redirect/api.py
|
#: authentik/stages/redirect/api.py
|
||||||
msgid "Target Flow should be present when mode is Flow."
|
msgid "Target Flow should be present when mode is Flow."
|
||||||
msgstr ""
|
msgstr "El Flujo de Destino debe estar presente cuando el modo es Flujo."
|
||||||
|
|
||||||
#: authentik/stages/redirect/models.py
|
#: authentik/stages/redirect/models.py
|
||||||
msgid "Redirect Stage"
|
msgid "Redirect Stage"
|
||||||
@ -3841,10 +3881,6 @@ msgstr "Etapas de inicio de"
|
|||||||
msgid "No Pending user to login."
|
msgid "No Pending user to login."
|
||||||
msgstr "Ningún usuario pendiente para iniciar sesión."
|
msgstr "Ningún usuario pendiente para iniciar sesión."
|
||||||
|
|
||||||
#: authentik/stages/user_login/stage.py
|
|
||||||
msgid "Successfully logged in!"
|
|
||||||
msgstr "¡Se ha iniciado sesión correctamente!"
|
|
||||||
|
|
||||||
#: authentik/stages/user_logout/models.py
|
#: authentik/stages/user_logout/models.py
|
||||||
msgid "User Logout Stage"
|
msgid "User Logout Stage"
|
||||||
msgstr "Etapa de cierre de sesión del usuario"
|
msgstr "Etapa de cierre de sesión del usuario"
|
||||||
@ -3920,10 +3956,12 @@ msgstr ""
|
|||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"La reputación no puede disminuir por debajo de este valor. Cero o negativo."
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"La reputación no puede aumentar por encima de este valor. Cero o positivo."
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
@ -3946,8 +3984,8 @@ msgstr "Personificación habilitada/deshabilitada globalmente."
|
|||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "Require administrators to provide a reason for impersonating a user."
|
msgid "Require administrators to provide a reason for impersonating a user."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Requerir a los administradores proporcionar una razón para suplantar un "
|
"Requerir que los administradores proporcionen una razón para personificar a "
|
||||||
"usuario."
|
"un usuario."
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "Default token duration"
|
msgid "Default token duration"
|
||||||
@ -3959,7 +3997,7 @@ msgstr "Longitud predeterminada del token"
|
|||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "Tenant"
|
msgid "Tenant"
|
||||||
msgstr "inquilino"
|
msgstr "Inquilino"
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "Tenants"
|
msgid "Tenants"
|
||||||
|
23
manage.py
23
manage.py
@ -1,35 +1,18 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""Django manage.py"""
|
"""Django manage.py"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
|
||||||
|
|
||||||
from authentik.lib.config import CONFIG
|
|
||||||
from cryptography.hazmat.backends.openssl.backend import backend
|
|
||||||
from defusedxml import defuse_stdlib
|
|
||||||
from django.utils.autoreload import DJANGO_AUTORELOAD_ENV
|
from django.utils.autoreload import DJANGO_AUTORELOAD_ENV
|
||||||
|
|
||||||
|
from authentik.root.setup import setup
|
||||||
from lifecycle.migrate import run_migrations
|
from lifecycle.migrate import run_migrations
|
||||||
from lifecycle.wait_for_db import wait_for_db
|
from lifecycle.wait_for_db import wait_for_db
|
||||||
|
|
||||||
warnings.filterwarnings("ignore", "SelectableGroups dict interface")
|
setup()
|
||||||
warnings.filterwarnings(
|
|
||||||
"ignore",
|
|
||||||
"defusedxml.lxml is no longer supported and will be removed in a future release.",
|
|
||||||
)
|
|
||||||
warnings.filterwarnings(
|
|
||||||
"ignore",
|
|
||||||
"defusedxml.cElementTree is deprecated, import from defusedxml.ElementTree instead.",
|
|
||||||
)
|
|
||||||
|
|
||||||
defuse_stdlib()
|
|
||||||
|
|
||||||
if CONFIG.get_bool("compliance.fips.enabled", False):
|
|
||||||
backend._enable_fips()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
|
|
||||||
wait_for_db()
|
wait_for_db()
|
||||||
if (
|
if (
|
||||||
len(sys.argv) > 1
|
len(sys.argv) > 1
|
||||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@goauthentik/authentik",
|
"name": "@goauthentik/authentik",
|
||||||
"version": "2025.6.1",
|
"version": "2025.6.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@goauthentik/authentik",
|
"name": "@goauthentik/authentik",
|
||||||
"version": "2025.6.1",
|
"version": "2025.6.2",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@goauthentik/authentik",
|
"name": "@goauthentik/authentik",
|
||||||
"version": "2025.6.1",
|
"version": "2025.6.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
10
packages/docusaurus-config/.prettierignore
Normal file
10
packages/docusaurus-config/.prettierignore
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Prettier Ignorefile
|
||||||
|
|
||||||
|
## Static Files
|
||||||
|
**/LICENSE
|
||||||
|
|
||||||
|
## Build asset directories
|
||||||
|
coverage
|
||||||
|
dist
|
||||||
|
out
|
||||||
|
.docusaurus
|
@ -4,3 +4,5 @@
|
|||||||
|
|
||||||
export * from "./lib/theme.js";
|
export * from "./lib/theme.js";
|
||||||
export * from "./lib/common.js";
|
export * from "./lib/common.js";
|
||||||
|
export * from "./lib/routing.js";
|
||||||
|
export * from "./lib/navbar.js";
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file Common Docusaurus configuration utilities.
|
* @file Common Docusaurus configuration utilities.
|
||||||
*
|
*
|
||||||
* @import { Config as DocusaurusConfig } from "@docusaurus/types"
|
* @import { Config, DocusaurusConfig } from "@docusaurus/types"
|
||||||
* @import { UserThemeConfig } from "./theme.js"
|
* @import { UserThemeConfig, UserThemeConfigExtra } from "./theme.js"
|
||||||
*/
|
*/
|
||||||
import { deepmerge } from "deepmerge-ts";
|
import { deepmerge } from "deepmerge-ts";
|
||||||
|
|
||||||
@ -11,14 +11,14 @@ import { createThemeConfig } from "./theme.js";
|
|||||||
//#region Types
|
//#region Types
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Omit<DocusaurusConfig, 'themeConfig'>} DocusaurusConfigBase
|
* @typedef {Omit<Config, 'themeConfig'>} DocusaurusConfigBase
|
||||||
*
|
*
|
||||||
* Represents the base configuration for Docusaurus, excluding the theme configuration.
|
* Represents the base configuration for Docusaurus, excluding the theme configuration.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef DocusaurusConfigBaseTheme
|
* @typedef DocusaurusConfigBaseTheme
|
||||||
* @property {UserThemeConfig} themeConfig The theme configuration.
|
* @property {UserThemeConfig & UserThemeConfigExtra} themeConfig The theme configuration.
|
||||||
*
|
*
|
||||||
* Represents a configuration object, only including the theme configuration.
|
* Represents a configuration object, only including the theme configuration.
|
||||||
*/
|
*/
|
||||||
@ -39,31 +39,66 @@ import { createThemeConfig } from "./theme.js";
|
|||||||
//#region Functions
|
//#region Functions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Docusaurus configuration.
|
* Create a default Docusaurus configuration.
|
||||||
*
|
|
||||||
* @param {DocusaurusConfigInit} [overrides] The options to override.
|
|
||||||
* @returns {DocusaurusConfig}
|
|
||||||
*/
|
*/
|
||||||
export function createDocusaurusConfig({ themeConfig, ...overrides } = {}) {
|
export function createDefaultDocusaurusConfig() {
|
||||||
|
const NodeEnvironment = process.env.AK_DOCUSAURUS_ENV || process.env.NODE_ENV || "development";
|
||||||
|
const production = NodeEnvironment === "production";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {DocusaurusConfig}
|
* @satisfies {Config}
|
||||||
*/
|
*/
|
||||||
const config = {
|
const DEFAULT_CONFIG = /** @type {const} */ ({
|
||||||
|
trailingSlash: true,
|
||||||
|
future: {
|
||||||
|
v4: {
|
||||||
|
removeLegacyPostBuildHeadAttribute: true,
|
||||||
|
useCssCascadeLayers: false,
|
||||||
|
},
|
||||||
|
experimental_faster: {
|
||||||
|
swcJsLoader: true,
|
||||||
|
rspackBundler: true,
|
||||||
|
lightningCssMinimizer: production,
|
||||||
|
swcJsMinimizer: production,
|
||||||
|
swcHtmlMinimizer: production,
|
||||||
|
ssgWorkerThreads: production,
|
||||||
|
mdxCrossCompilerCache: production,
|
||||||
|
rspackPersistentCache: production,
|
||||||
|
},
|
||||||
|
},
|
||||||
title: "authentik",
|
title: "authentik",
|
||||||
tagline: "Bring all of your authentication into a unified platform.",
|
tagline: "Bring all of your authentication into a unified platform.",
|
||||||
url: "https://docs.goauthentik.io",
|
url: "https://docs.goauthentik.io",
|
||||||
baseUrl: "/",
|
baseUrl: "/",
|
||||||
onBrokenLinks: "throw",
|
onBrokenLinks: "throw",
|
||||||
onBrokenAnchors: "throw",
|
onBrokenAnchors: "throw",
|
||||||
|
onBrokenMarkdownLinks: "throw",
|
||||||
|
onDuplicateRoutes: "throw",
|
||||||
favicon: "img/icon.png",
|
favicon: "img/icon.png",
|
||||||
organizationName: "Authentik Security Inc.",
|
organizationName: "Authentik Security Inc.",
|
||||||
projectName: "authentik",
|
projectName: "authentik",
|
||||||
markdown: {
|
markdown: {
|
||||||
mermaid: true,
|
mermaid: true,
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return DEFAULT_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Docusaurus configuration.
|
||||||
|
*
|
||||||
|
* @template {Partial<Config>} T
|
||||||
|
* @param {T} overrides The options to override.
|
||||||
|
* @returns {T & ReturnType<typeof createDefaultDocusaurusConfig>}
|
||||||
|
*/
|
||||||
|
export function createDocusaurusConfig({ themeConfig, ...overrides }) {
|
||||||
|
const config = {
|
||||||
|
...createDefaultDocusaurusConfig(),
|
||||||
themeConfig: createThemeConfig(themeConfig),
|
themeConfig: createThemeConfig(themeConfig),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
return deepmerge(config, overrides);
|
return deepmerge(config, overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
110
packages/docusaurus-config/lib/navbar.js
Normal file
110
packages/docusaurus-config/lib/navbar.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* @file Docusaurus navbar configuration for the authentik website.
|
||||||
|
*
|
||||||
|
* @import { NavbarItem } from "@docusaurus/theme-common";
|
||||||
|
*/
|
||||||
|
import { DocusaurusURL, SocialURL } from "./routing.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The navbar items for the authentik website.
|
||||||
|
*
|
||||||
|
* @type {NavbarItem[]}
|
||||||
|
*/
|
||||||
|
export const SocialNavbarItems = /** @type {const} */ ([
|
||||||
|
{
|
||||||
|
"href": SocialURL.GitHub,
|
||||||
|
"data-icon": "github",
|
||||||
|
"aria-label": "GitHub",
|
||||||
|
"position": "right",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": SocialURL.Discord,
|
||||||
|
"data-icon": "discord",
|
||||||
|
"aria-label": "Discord",
|
||||||
|
"position": "right",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The navbar items for the authentik website.
|
||||||
|
*
|
||||||
|
* @satisfies {NavbarItem[]}
|
||||||
|
*/
|
||||||
|
export const NavbarItemsTemplate = /** @type {const} */ ([
|
||||||
|
{
|
||||||
|
to: "{{WWW_URL}}/features",
|
||||||
|
label: "Features",
|
||||||
|
position: "left",
|
||||||
|
target: "_self",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
to: "{{INTEGRATIONS_URL}}",
|
||||||
|
label: "Integrations",
|
||||||
|
target: "_self",
|
||||||
|
position: "left",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
to: "{{DOCS_URL}}",
|
||||||
|
|
||||||
|
label: "Documentation",
|
||||||
|
position: "left",
|
||||||
|
target: "_self",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
to: "{{WWW_URL}}/pricing/",
|
||||||
|
label: "Pricing",
|
||||||
|
position: "left",
|
||||||
|
target: "_self",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
to: "{{WWW_URL}}/blog",
|
||||||
|
label: "Blog",
|
||||||
|
position: "left",
|
||||||
|
target: "_self",
|
||||||
|
},
|
||||||
|
...SocialNavbarItems,
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} NavbarItemOverrides
|
||||||
|
*
|
||||||
|
* @prop {string} WWW_URL The URL for the WWW environment.
|
||||||
|
* @prop {string} DOCS_URL The URL for the documentation.
|
||||||
|
* @prop {string} INTEGRATIONS_URL The URL for the integrations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const DEFAULT_NAVBAR_REPLACEMENTS = /** @type {const} */ ({
|
||||||
|
DOCS_URL: DocusaurusURL.Docs,
|
||||||
|
INTEGRATIONS_URL: DocusaurusURL.Integrations,
|
||||||
|
WWW_URL: DocusaurusURL.WWW,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a navbar item array, replacing placeholders with the given replacements.
|
||||||
|
*
|
||||||
|
* @param {Partial<NavbarItemOverrides>} [overrides]
|
||||||
|
* @returns {NavbarItem[]}
|
||||||
|
*/
|
||||||
|
export function createNavbarItems(overrides) {
|
||||||
|
const replacements = {
|
||||||
|
...DEFAULT_NAVBAR_REPLACEMENTS,
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
|
||||||
|
return NavbarItemsTemplate.map((item) => {
|
||||||
|
if (typeof item.to !== "string") return item;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
to: item.to.replace(
|
||||||
|
/{{([^}]+)}}/g,
|
||||||
|
/**
|
||||||
|
* @param {keyof NavbarItemOverrides} key
|
||||||
|
*/
|
||||||
|
(_, key) => {
|
||||||
|
return replacements[key];
|
||||||
|
},
|
||||||
|
),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
35
packages/docusaurus-config/lib/routing.js
Normal file
35
packages/docusaurus-config/lib/routing.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* @file Docusaurus routing configuration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {'production'|'development'} NodeEnvironment
|
||||||
|
*/
|
||||||
|
|
||||||
|
const NodeEnvironment = /** @type {NodeEnvironment} */ (process.env.NODE_ENV || "development");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @satisfies {Record<NodeEnvironment, Record<string, string>>}
|
||||||
|
*/
|
||||||
|
export const DocusaurusURLByEnvironment = /** @type {const} */ ({
|
||||||
|
development: {
|
||||||
|
Docs: "http://localhost:3000",
|
||||||
|
Integrations: "http://localhost:3001",
|
||||||
|
WWW: "http://localhost:3002",
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
Docs: "https://docs.goauthentik.io",
|
||||||
|
Integrations: "https://integrations.goauthentik.io",
|
||||||
|
WWW: "https://goauthentik.io",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const DocusaurusURL = DocusaurusURLByEnvironment[NodeEnvironment];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @satisfies {Record<string, string>}
|
||||||
|
*/
|
||||||
|
export const SocialURL = /** @type {const} */ ({
|
||||||
|
Discord: "https://goauthentik.io/discord",
|
||||||
|
GitHub: "https://github.com/goauthentik/authentik",
|
||||||
|
});
|
@ -3,16 +3,26 @@
|
|||||||
*
|
*
|
||||||
* @import { UserThemeConfig as UserThemeConfigCommon } from "@docusaurus/theme-common";
|
* @import { UserThemeConfig as UserThemeConfigCommon } from "@docusaurus/theme-common";
|
||||||
* @import { UserThemeConfig as UserThemeConfigAlgolia } from "@docusaurus/theme-search-algolia";
|
* @import { UserThemeConfig as UserThemeConfigAlgolia } from "@docusaurus/theme-search-algolia";
|
||||||
|
* @import { NavbarItemOverrides } from "./navbar.js"
|
||||||
*/
|
*/
|
||||||
import { deepmerge } from "deepmerge-ts";
|
import { deepmerge } from "deepmerge-ts";
|
||||||
import { themes as prismThemes } from "prism-react-renderer";
|
import { themes as prismThemes } from "prism-react-renderer";
|
||||||
|
|
||||||
|
import { createNavbarItems } from "./navbar.js";
|
||||||
|
|
||||||
//#region Types
|
//#region Types
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combined theme configuration for Docusaurus and Algolia.
|
* @typedef {Object} UserThemeConfigExtra
|
||||||
|
* @property {Partial<NavbarItemOverrides>} [navbarReplacements] The replacements for the navbar.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combined theme configuration for Docusaurus, Algolia, and our own configuration.
|
||||||
*
|
*
|
||||||
* @typedef {UserThemeConfigCommon & UserThemeConfigAlgolia} UserThemeConfig
|
* @typedef {UserThemeConfigCommon & UserThemeConfigAlgolia} UserThemeConfig
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
@ -57,10 +67,10 @@ export function createPrismConfig(overrides = {}) {
|
|||||||
/**
|
/**
|
||||||
* Creates a theme configuration for Docusaurus.
|
* Creates a theme configuration for Docusaurus.
|
||||||
*
|
*
|
||||||
* @param {Partial<UserThemeConfig>} overrides - Overrides for the default theme configuration.
|
* @param {Partial<UserThemeConfig & UserThemeConfigExtra>} overrides - Overrides for the default theme configuration.
|
||||||
* @returns {UserThemeConfig}
|
* @returns {UserThemeConfig}
|
||||||
*/
|
*/
|
||||||
export function createThemeConfig({ prism, ...overrides } = {}) {
|
export function createThemeConfig({ prism, navbarReplacements, ...overrides } = {}) {
|
||||||
/**
|
/**
|
||||||
* @type {UserThemeConfig}
|
* @type {UserThemeConfig}
|
||||||
*/
|
*/
|
||||||
@ -77,6 +87,17 @@ export function createThemeConfig({ prism, ...overrides } = {}) {
|
|||||||
appId: "36ROD0O0FV",
|
appId: "36ROD0O0FV",
|
||||||
apiKey: "727db511300ca9aec5425645bbbddfb5",
|
apiKey: "727db511300ca9aec5425645bbbddfb5",
|
||||||
},
|
},
|
||||||
|
footer: {
|
||||||
|
copyright: `Copyright © ${new Date().getFullYear()} Authentik Security Inc. Built with Docusaurus.`,
|
||||||
|
},
|
||||||
|
navbar: {
|
||||||
|
logo: {
|
||||||
|
alt: "authentik logo",
|
||||||
|
src: "img/icon_left_brand.svg",
|
||||||
|
},
|
||||||
|
|
||||||
|
items: createNavbarItems(navbarReplacements),
|
||||||
|
},
|
||||||
prism: createPrismConfig(prism),
|
prism: createPrismConfig(prism),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
342
packages/docusaurus-config/package-lock.json
generated
342
packages/docusaurus-config/package-lock.json
generated
@ -1,43 +1,51 @@
|
|||||||
{
|
{
|
||||||
"name": "@goauthentik/docusaurus-config",
|
"name": "@goauthentik/docusaurus-config",
|
||||||
"version": "2.0.0",
|
"version": "2.1.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@goauthentik/docusaurus-config",
|
"name": "@goauthentik/docusaurus-config",
|
||||||
"version": "2.0.0",
|
"version": "2.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"deepmerge-ts": "^7.1.5",
|
"deepmerge-ts": "^7.1.5",
|
||||||
"prism-react-renderer": "^2.4.1"
|
"prism-react-renderer": "^2.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/theme-common": "^3.8.0",
|
"@docusaurus/theme-common": "^3.8.1",
|
||||||
"@docusaurus/theme-search-algolia": "^3.8.0",
|
"@docusaurus/theme-search-algolia": "^3.8.1",
|
||||||
"@docusaurus/types": "^3.8.0",
|
"@docusaurus/types": "^3.8.1",
|
||||||
"@goauthentik/prettier-config": "^2.0.0",
|
"@goauthentik/prettier-config": "^2.0.0",
|
||||||
"@goauthentik/tsconfig": "^1.0.4",
|
"@goauthentik/tsconfig": "^1.0.4",
|
||||||
"@types/react": "^19.1.6",
|
"@types/react": "^19.1.6",
|
||||||
"@types/react-dom": "^19.1.5",
|
"@types/react-dom": "^19.1.5",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"react": "^19.1.0",
|
|
||||||
"react-dom": "^19.1.0",
|
|
||||||
"typescript": "^5.8.3"
|
"typescript": "^5.8.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
},
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@docusaurus/theme-common": "^3.8.0",
|
"@docusaurus/theme-common": "^3.8.1",
|
||||||
"@docusaurus/theme-search-algolia": "^3.8.0",
|
"@docusaurus/theme-search-algolia": "^3.8.1",
|
||||||
"@docusaurus/types": "^3.8.0",
|
"@docusaurus/types": "^3.8.0",
|
||||||
"react": "^18.0.0 || ^19.0.0",
|
"react": ">=18",
|
||||||
"react-dom": "^18.0.0 || ^19.0.0"
|
"react-dom": ">=18"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@docusaurus/theme-search-algolia": {
|
"@docusaurus/theme-search-algolia": {
|
||||||
"optional": true
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -320,9 +328,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/compat-data": {
|
"node_modules/@babel/compat-data": {
|
||||||
"version": "7.27.3",
|
"version": "7.27.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.5.tgz",
|
||||||
"integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==",
|
"integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -669,14 +677,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helpers": {
|
"node_modules/@babel/helpers": {
|
||||||
"version": "7.27.4",
|
"version": "7.27.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz",
|
||||||
"integrity": "sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==",
|
"integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.27.2",
|
"@babel/template": "^7.27.2",
|
||||||
"@babel/types": "^7.27.3"
|
"@babel/types": "^7.27.6"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@ -958,9 +966,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-block-scoping": {
|
"node_modules/@babel/plugin-transform-block-scoping": {
|
||||||
"version": "7.27.3",
|
"version": "7.27.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.5.tgz",
|
||||||
"integrity": "sha512-+F8CnfhuLhwUACIJMLWnjz6zvzYM2r0yeIHKlbgfw7ml8rOMJsXNXV/hyRcb3nb493gRs4WvYpQAndWj/qQmkQ==",
|
"integrity": "sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -1599,9 +1607,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-regenerator": {
|
"node_modules/@babel/plugin-transform-regenerator": {
|
||||||
"version": "7.27.4",
|
"version": "7.27.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.5.tgz",
|
||||||
"integrity": "sha512-Glp/0n8xuj+E1588otw5rjJkTXfzW7FjH3IIUrfqiZOPQCd2vbg8e+DQE8jK9g4V5/zrxFW+D9WM9gboRPELpQ==",
|
"integrity": "sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2007,9 +2015,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime-corejs3": {
|
"node_modules/@babel/runtime-corejs3": {
|
||||||
"version": "7.27.4",
|
"version": "7.27.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.27.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.27.6.tgz",
|
||||||
"integrity": "sha512-H7QhL0ucCGOObsUETNbB2PuzF4gAvN8p32P6r91bX7M/hk4bx+3yz2hTwHL9d/Efzwu1upeb4/cd7oSxCzup3w==",
|
"integrity": "sha512-vDVrlmRAY8z9Ul/HxT+8ceAru95LQgkSKiXkSYZvqtbkPSfhZJgpRp45Cldbh1GJ1kxzQkI70AqyrTI58KpaWQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2054,9 +2062,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.27.3",
|
"version": "7.27.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz",
|
||||||
"integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==",
|
"integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2619,9 +2627,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@csstools/postcss-is-pseudo-class": {
|
"node_modules/@csstools/postcss-is-pseudo-class": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.3.tgz",
|
||||||
"integrity": "sha512-JLp3POui4S1auhDR0n8wHd/zTOWmMsmK3nQd3hhL6FhWPaox5W7j1se6zXOG/aP07wV2ww0lxbKYGwbBszOtfQ==",
|
"integrity": "sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -3305,9 +3313,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/babel": {
|
"node_modules/@docusaurus/babel": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.8.1.tgz",
|
||||||
"integrity": "sha512-9EJwSgS6TgB8IzGk1L8XddJLhZod8fXT4ULYMx6SKqyCBqCFpVCEjR/hNXXhnmtVM2irDuzYoVLGWv7srG/VOA==",
|
"integrity": "sha512-3brkJrml8vUbn9aeoZUlJfsI/GqyFcDgQJwQkmBtclJgWDEQBKKeagZfOgx0WfUQhagL1sQLNW0iBdxnI863Uw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -3321,8 +3329,8 @@
|
|||||||
"@babel/runtime": "^7.25.9",
|
"@babel/runtime": "^7.25.9",
|
||||||
"@babel/runtime-corejs3": "^7.25.9",
|
"@babel/runtime-corejs3": "^7.25.9",
|
||||||
"@babel/traverse": "^7.25.9",
|
"@babel/traverse": "^7.25.9",
|
||||||
"@docusaurus/logger": "3.8.0",
|
"@docusaurus/logger": "3.8.1",
|
||||||
"@docusaurus/utils": "3.8.0",
|
"@docusaurus/utils": "3.8.1",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
"fs-extra": "^11.1.1",
|
"fs-extra": "^11.1.1",
|
||||||
"tslib": "^2.6.0"
|
"tslib": "^2.6.0"
|
||||||
@ -3332,31 +3340,31 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/bundler": {
|
"node_modules/@docusaurus/bundler": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.8.1.tgz",
|
||||||
"integrity": "sha512-Rq4Z/MSeAHjVzBLirLeMcjLIAQy92pF1OI+2rmt18fSlMARfTGLWRE8Vb+ljQPTOSfJxwDYSzsK6i7XloD2rNA==",
|
"integrity": "sha512-/z4V0FRoQ0GuSLToNjOSGsk6m2lQUG4FRn8goOVoZSRsTrU8YR2aJacX5K3RG18EaX9b+52pN4m1sL3MQZVsQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.25.9",
|
"@babel/core": "^7.25.9",
|
||||||
"@docusaurus/babel": "3.8.0",
|
"@docusaurus/babel": "3.8.1",
|
||||||
"@docusaurus/cssnano-preset": "3.8.0",
|
"@docusaurus/cssnano-preset": "3.8.1",
|
||||||
"@docusaurus/logger": "3.8.0",
|
"@docusaurus/logger": "3.8.1",
|
||||||
"@docusaurus/types": "3.8.0",
|
"@docusaurus/types": "3.8.1",
|
||||||
"@docusaurus/utils": "3.8.0",
|
"@docusaurus/utils": "3.8.1",
|
||||||
"babel-loader": "^9.2.1",
|
"babel-loader": "^9.2.1",
|
||||||
"clean-css": "^5.3.2",
|
"clean-css": "^5.3.3",
|
||||||
"copy-webpack-plugin": "^11.0.0",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"css-loader": "^6.8.1",
|
"css-loader": "^6.11.0",
|
||||||
"css-minimizer-webpack-plugin": "^5.0.1",
|
"css-minimizer-webpack-plugin": "^5.0.1",
|
||||||
"cssnano": "^6.1.2",
|
"cssnano": "^6.1.2",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"html-minifier-terser": "^7.2.0",
|
"html-minifier-terser": "^7.2.0",
|
||||||
"mini-css-extract-plugin": "^2.9.1",
|
"mini-css-extract-plugin": "^2.9.2",
|
||||||
"null-loader": "^4.0.1",
|
"null-loader": "^4.0.1",
|
||||||
"postcss": "^8.4.26",
|
"postcss": "^8.5.4",
|
||||||
"postcss-loader": "^7.3.3",
|
"postcss-loader": "^7.3.4",
|
||||||
"postcss-preset-env": "^10.1.0",
|
"postcss-preset-env": "^10.2.1",
|
||||||
"terser-webpack-plugin": "^5.3.9",
|
"terser-webpack-plugin": "^5.3.9",
|
||||||
"tslib": "^2.6.0",
|
"tslib": "^2.6.0",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
@ -3376,19 +3384,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/core": {
|
"node_modules/@docusaurus/core": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.8.1.tgz",
|
||||||
"integrity": "sha512-c7u6zFELmSGPEP9WSubhVDjgnpiHgDqMh1qVdCB7rTflh4Jx0msTYmMiO91Ez0KtHj4sIsDsASnjwfJ2IZp3Vw==",
|
"integrity": "sha512-ENB01IyQSqI2FLtOzqSI3qxG2B/jP4gQPahl2C3XReiLebcVh5B5cB9KYFvdoOqOWPyr5gXK4sjgTKv7peXCrA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/babel": "3.8.0",
|
"@docusaurus/babel": "3.8.1",
|
||||||
"@docusaurus/bundler": "3.8.0",
|
"@docusaurus/bundler": "3.8.1",
|
||||||
"@docusaurus/logger": "3.8.0",
|
"@docusaurus/logger": "3.8.1",
|
||||||
"@docusaurus/mdx-loader": "3.8.0",
|
"@docusaurus/mdx-loader": "3.8.1",
|
||||||
"@docusaurus/utils": "3.8.0",
|
"@docusaurus/utils": "3.8.1",
|
||||||
"@docusaurus/utils-common": "3.8.0",
|
"@docusaurus/utils-common": "3.8.1",
|
||||||
"@docusaurus/utils-validation": "3.8.0",
|
"@docusaurus/utils-validation": "3.8.1",
|
||||||
"boxen": "^6.2.1",
|
"boxen": "^6.2.1",
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
@ -3438,14 +3446,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/cssnano-preset": {
|
"node_modules/@docusaurus/cssnano-preset": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.8.1.tgz",
|
||||||
"integrity": "sha512-UJ4hAS2T0R4WNy+phwVff2Q0L5+RXW9cwlH6AEphHR5qw3m/yacfWcSK7ort2pMMbDn8uGrD38BTm4oLkuuNoQ==",
|
"integrity": "sha512-G7WyR2N6SpyUotqhGznERBK+x84uyhfMQM2MmDLs88bw4Flom6TY46HzkRkSEzaP9j80MbTN8naiL1fR17WQug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssnano-preset-advanced": "^6.1.2",
|
"cssnano-preset-advanced": "^6.1.2",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.5.4",
|
||||||
"postcss-sort-media-queries": "^5.2.0",
|
"postcss-sort-media-queries": "^5.2.0",
|
||||||
"tslib": "^2.6.0"
|
"tslib": "^2.6.0"
|
||||||
},
|
},
|
||||||
@ -3454,9 +3462,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/logger": {
|
"node_modules/@docusaurus/logger": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.8.1.tgz",
|
||||||
"integrity": "sha512-7eEMaFIam5Q+v8XwGqF/n0ZoCld4hV4eCCgQkfcN9Mq5inoZa6PHHW9Wu6lmgzoK5Kx3keEeABcO2SxwraoPDQ==",
|
"integrity": "sha512-2wjeGDhKcExEmjX8k1N/MRDiPKXGF2Pg+df/bDDPnnJWHXnVEZxXj80d6jcxp1Gpnksl0hF8t/ZQw9elqj2+ww==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -3468,15 +3476,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/mdx-loader": {
|
"node_modules/@docusaurus/mdx-loader": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.8.1.tgz",
|
||||||
"integrity": "sha512-mDPSzssRnpjSdCGuv7z2EIAnPS1MHuZGTaRLwPn4oQwszu4afjWZ/60sfKjTnjBjI8Vl4OgJl2vMmfmiNDX4Ng==",
|
"integrity": "sha512-DZRhagSFRcEq1cUtBMo4TKxSNo/W6/s44yhr8X+eoXqCLycFQUylebOMPseHi5tc4fkGJqwqpWJLz6JStU9L4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/logger": "3.8.0",
|
"@docusaurus/logger": "3.8.1",
|
||||||
"@docusaurus/utils": "3.8.0",
|
"@docusaurus/utils": "3.8.1",
|
||||||
"@docusaurus/utils-validation": "3.8.0",
|
"@docusaurus/utils-validation": "3.8.1",
|
||||||
"@mdx-js/mdx": "^3.0.0",
|
"@mdx-js/mdx": "^3.0.0",
|
||||||
"@slorber/remark-comment": "^1.0.0",
|
"@slorber/remark-comment": "^1.0.0",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
@ -3508,13 +3516,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/module-type-aliases": {
|
"node_modules/@docusaurus/module-type-aliases": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.8.1.tgz",
|
||||||
"integrity": "sha512-/uMb4Ipt5J/QnD13MpnoC/A4EYAe6DKNWqTWLlGrqsPJwJv73vSwkA25xnYunwfqWk0FlUQfGv/Swdh5eCCg7g==",
|
"integrity": "sha512-6xhvAJiXzsaq3JdosS7wbRt/PwEPWHr9eM4YNYqVlbgG1hSK3uQDXTVvQktasp3VO6BmfYWPozueLWuj4gB+vg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/types": "3.8.0",
|
"@docusaurus/types": "3.8.1",
|
||||||
"@types/history": "^4.7.11",
|
"@types/history": "^4.7.11",
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
"@types/react-router-config": "*",
|
"@types/react-router-config": "*",
|
||||||
@ -3528,21 +3536,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/plugin-content-docs": {
|
"node_modules/@docusaurus/plugin-content-docs": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.8.1.tgz",
|
||||||
"integrity": "sha512-fRDMFLbUN6eVRXcjP8s3Y7HpAt9pzPYh1F/7KKXOCxvJhjjCtbon4VJW0WndEPInVz4t8QUXn5QZkU2tGVCE2g==",
|
"integrity": "sha512-oByRkSZzeGNQByCMaX+kif5Nl2vmtj2IHQI2fWjCfCootsdKZDPFLonhIp5s3IGJO7PLUfe0POyw0Xh/RrGXJA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "3.8.0",
|
"@docusaurus/core": "3.8.1",
|
||||||
"@docusaurus/logger": "3.8.0",
|
"@docusaurus/logger": "3.8.1",
|
||||||
"@docusaurus/mdx-loader": "3.8.0",
|
"@docusaurus/mdx-loader": "3.8.1",
|
||||||
"@docusaurus/module-type-aliases": "3.8.0",
|
"@docusaurus/module-type-aliases": "3.8.1",
|
||||||
"@docusaurus/theme-common": "3.8.0",
|
"@docusaurus/theme-common": "3.8.1",
|
||||||
"@docusaurus/types": "3.8.0",
|
"@docusaurus/types": "3.8.1",
|
||||||
"@docusaurus/utils": "3.8.0",
|
"@docusaurus/utils": "3.8.1",
|
||||||
"@docusaurus/utils-common": "3.8.0",
|
"@docusaurus/utils-common": "3.8.1",
|
||||||
"@docusaurus/utils-validation": "3.8.0",
|
"@docusaurus/utils-validation": "3.8.1",
|
||||||
"@types/react-router-config": "^5.0.7",
|
"@types/react-router-config": "^5.0.7",
|
||||||
"combine-promises": "^1.1.0",
|
"combine-promises": "^1.1.0",
|
||||||
"fs-extra": "^11.1.1",
|
"fs-extra": "^11.1.1",
|
||||||
@ -3562,16 +3570,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/theme-common": {
|
"node_modules/@docusaurus/theme-common": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.8.1.tgz",
|
||||||
"integrity": "sha512-YqV2vAWpXGLA+A3PMLrOMtqgTHJLDcT+1Caa6RF7N4/IWgrevy5diY8oIHFkXR/eybjcrFFjUPrHif8gSGs3Tw==",
|
"integrity": "sha512-UswMOyTnPEVRvN5Qzbo+l8k4xrd5fTFu2VPPfD6FcW/6qUtVLmJTQCktbAL3KJ0BVXGm5aJXz/ZrzqFuZERGPw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/mdx-loader": "3.8.0",
|
"@docusaurus/mdx-loader": "3.8.1",
|
||||||
"@docusaurus/module-type-aliases": "3.8.0",
|
"@docusaurus/module-type-aliases": "3.8.1",
|
||||||
"@docusaurus/utils": "3.8.0",
|
"@docusaurus/utils": "3.8.1",
|
||||||
"@docusaurus/utils-common": "3.8.0",
|
"@docusaurus/utils-common": "3.8.1",
|
||||||
"@types/history": "^4.7.11",
|
"@types/history": "^4.7.11",
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
"@types/react-router-config": "*",
|
"@types/react-router-config": "*",
|
||||||
@ -3591,20 +3599,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/theme-search-algolia": {
|
"node_modules/@docusaurus/theme-search-algolia": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.1.tgz",
|
||||||
"integrity": "sha512-GBZ5UOcPgiu6nUw153+0+PNWvFKweSnvKIL6Rp04H9olKb475jfKjAwCCtju5D2xs5qXHvCMvzWOg5o9f6DtuQ==",
|
"integrity": "sha512-NBFH5rZVQRAQM087aYSRKQ9yGEK9eHd+xOxQjqNpxMiV85OhJDD4ZGz6YJIod26Fbooy54UWVdzNU0TFeUUUzQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docsearch/react": "^3.9.0",
|
"@docsearch/react": "^3.9.0",
|
||||||
"@docusaurus/core": "3.8.0",
|
"@docusaurus/core": "3.8.1",
|
||||||
"@docusaurus/logger": "3.8.0",
|
"@docusaurus/logger": "3.8.1",
|
||||||
"@docusaurus/plugin-content-docs": "3.8.0",
|
"@docusaurus/plugin-content-docs": "3.8.1",
|
||||||
"@docusaurus/theme-common": "3.8.0",
|
"@docusaurus/theme-common": "3.8.1",
|
||||||
"@docusaurus/theme-translations": "3.8.0",
|
"@docusaurus/theme-translations": "3.8.1",
|
||||||
"@docusaurus/utils": "3.8.0",
|
"@docusaurus/utils": "3.8.1",
|
||||||
"@docusaurus/utils-validation": "3.8.0",
|
"@docusaurus/utils-validation": "3.8.1",
|
||||||
"algoliasearch": "^5.17.1",
|
"algoliasearch": "^5.17.1",
|
||||||
"algoliasearch-helper": "^3.22.6",
|
"algoliasearch-helper": "^3.22.6",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
@ -3623,9 +3631,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/theme-translations": {
|
"node_modules/@docusaurus/theme-translations": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.8.1.tgz",
|
||||||
"integrity": "sha512-1DTy/snHicgkCkryWq54fZvsAglTdjTx4qjOXgqnXJ+DIty1B+aPQrAVUu8LiM+6BiILfmNxYsxhKTj+BS3PZg==",
|
"integrity": "sha512-OTp6eebuMcf2rJt4bqnvuwmm3NVXfzfYejL+u/Y1qwKhZPrjPoKWfk1CbOP5xH5ZOPkiAsx4dHdQBRJszK3z2g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -3637,9 +3645,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/types": {
|
"node_modules/@docusaurus/types": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.8.1.tgz",
|
||||||
"integrity": "sha512-RDEClpwNxZq02c+JlaKLWoS13qwWhjcNsi2wG1UpzmEnuti/z1Wx4SGpqbUqRPNSd8QWWePR8Cb7DvG0VN/TtA==",
|
"integrity": "sha512-ZPdW5AB+pBjiVrcLuw3dOS6BFlrG0XkS2lDGsj8TizcnREQg3J8cjsgfDviszOk4CweNfwo1AEELJkYaMUuOPg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -3674,15 +3682,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/utils": {
|
"node_modules/@docusaurus/utils": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.8.1.tgz",
|
||||||
"integrity": "sha512-2wvtG28ALCN/A1WCSLxPASFBFzXCnP0YKCAFIPcvEb6imNu1wg7ni/Svcp71b3Z2FaOFFIv4Hq+j4gD7gA0yfQ==",
|
"integrity": "sha512-P1ml0nvOmEFdmu0smSXOqTS1sxU5tqvnc0dA4MTKV39kye+bhQnjkIKEE18fNOvxjyB86k8esoCIFM3x4RykOQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/logger": "3.8.0",
|
"@docusaurus/logger": "3.8.1",
|
||||||
"@docusaurus/types": "3.8.0",
|
"@docusaurus/types": "3.8.1",
|
||||||
"@docusaurus/utils-common": "3.8.0",
|
"@docusaurus/utils-common": "3.8.1",
|
||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"execa": "5.1.1",
|
"execa": "5.1.1",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
@ -3707,13 +3715,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/utils-common": {
|
"node_modules/@docusaurus/utils-common": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.8.1.tgz",
|
||||||
"integrity": "sha512-3TGF+wVTGgQ3pAc9+5jVchES4uXUAhAt9pwv7uws4mVOxL4alvU3ue/EZ+R4XuGk94pDy7CNXjRXpPjlfZXQfw==",
|
"integrity": "sha512-zTZiDlvpvoJIrQEEd71c154DkcriBecm4z94OzEE9kz7ikS3J+iSlABhFXM45mZ0eN5pVqqr7cs60+ZlYLewtg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/types": "3.8.0",
|
"@docusaurus/types": "3.8.1",
|
||||||
"tslib": "^2.6.0"
|
"tslib": "^2.6.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -3721,15 +3729,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@docusaurus/utils-validation": {
|
"node_modules/@docusaurus/utils-validation": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.8.1.tgz",
|
||||||
"integrity": "sha512-MrnEbkigr54HkdFeg8e4FKc4EF+E9dlVwsY3XQZsNkbv3MKZnbHQ5LsNJDIKDROFe8PBf5C4qCAg5TPBpsjrjg==",
|
"integrity": "sha512-gs5bXIccxzEbyVecvxg6upTwaUbfa0KMmTj7HhHzc016AGyxH2o73k1/aOD0IFrdCsfJNt37MqNI47s2MgRZMA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/logger": "3.8.0",
|
"@docusaurus/logger": "3.8.1",
|
||||||
"@docusaurus/utils": "3.8.0",
|
"@docusaurus/utils": "3.8.1",
|
||||||
"@docusaurus/utils-common": "3.8.0",
|
"@docusaurus/utils-common": "3.8.1",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"joi": "^17.9.2",
|
"joi": "^17.9.2",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
@ -5402,9 +5410,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/browserslist": {
|
"node_modules/browserslist": {
|
||||||
"version": "4.24.5",
|
"version": "4.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz",
|
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz",
|
||||||
"integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==",
|
"integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -5422,8 +5430,8 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caniuse-lite": "^1.0.30001716",
|
"caniuse-lite": "^1.0.30001718",
|
||||||
"electron-to-chromium": "^1.5.149",
|
"electron-to-chromium": "^1.5.160",
|
||||||
"node-releases": "^2.0.19",
|
"node-releases": "^2.0.19",
|
||||||
"update-browserslist-db": "^1.1.3"
|
"update-browserslist-db": "^1.1.3"
|
||||||
},
|
},
|
||||||
@ -6177,13 +6185,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js-compat": {
|
"node_modules/core-js-compat": {
|
||||||
"version": "3.42.0",
|
"version": "3.43.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz",
|
||||||
"integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==",
|
"integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"browserslist": "^4.24.4"
|
"browserslist": "^4.25.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@ -6191,9 +6199,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js-pure": {
|
"node_modules/core-js-pure": {
|
||||||
"version": "3.42.0",
|
"version": "3.43.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.42.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.43.0.tgz",
|
||||||
"integrity": "sha512-007bM04u91fF4kMgwom2I5cQxAFIy8jVulgr9eozILl/SZE53QOqnW/+vviC+wQWLv+AunBG+8Q0TLoeSsSxRQ==",
|
"integrity": "sha512-i/AgxU2+A+BbJdMxh3v7/vxi2SbFqxiFmg6VsDwYB4jkucrd1BZNA9a9gphC0fYMG5IBSgQcbQnk865VCLe7xA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -7140,9 +7148,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.155",
|
"version": "1.5.170",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.170.tgz",
|
||||||
"integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==",
|
"integrity": "sha512-GP+M7aeluQo9uAyiTCxgIj/j+PrWhMlY7LFVj8prlsPljd0Fdg9AprlfUi+OCSFWy9Y5/2D/Jrj9HS8Z4rpKWA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
@ -13119,9 +13127,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.4",
|
"version": "8.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||||
"integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
|
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -13370,9 +13378,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-custom-properties": {
|
"node_modules/postcss-custom-properties": {
|
||||||
"version": "14.0.5",
|
"version": "14.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-14.0.6.tgz",
|
||||||
"integrity": "sha512-UWf/vhMapZatv+zOuqlfLmYXeOhhHLh8U8HAKGI2VJ00xLRYoAJh4xv8iX6FB6+TLXeDnm0DBLMi00E0hodbQw==",
|
"integrity": "sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -14010,9 +14018,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-nesting": {
|
"node_modules/postcss-nesting": {
|
||||||
"version": "13.0.1",
|
"version": "13.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.2.tgz",
|
||||||
"integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==",
|
"integrity": "sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -14026,7 +14034,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT-0",
|
"license": "MIT-0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@csstools/selector-resolve-nested": "^3.0.0",
|
"@csstools/selector-resolve-nested": "^3.1.0",
|
||||||
"@csstools/selector-specificity": "^5.0.0",
|
"@csstools/selector-specificity": "^5.0.0",
|
||||||
"postcss-selector-parser": "^7.0.0"
|
"postcss-selector-parser": "^7.0.0"
|
||||||
},
|
},
|
||||||
@ -14038,9 +14046,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": {
|
"node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": {
|
||||||
"version": "3.0.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.1.0.tgz",
|
||||||
"integrity": "sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==",
|
"integrity": "sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -14342,9 +14350,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss-preset-env": {
|
"node_modules/postcss-preset-env": {
|
||||||
"version": "10.2.0",
|
"version": "10.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-10.2.3.tgz",
|
||||||
"integrity": "sha512-cl13sPBbSqo1Q7Ryb19oT5NZO5IHFolRbIMdgDq4f9w1MHYiL6uZS7uSsjXJ1KzRIcX5BMjEeyxmAevVXENa3Q==",
|
"integrity": "sha512-zlQN1yYmA7lFeM1wzQI14z97mKoM8qGng+198w1+h6sCud/XxOjcKtApY9jWr7pXNS3yHDEafPlClSsWnkY8ow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -14370,7 +14378,7 @@
|
|||||||
"@csstools/postcss-hwb-function": "^4.0.10",
|
"@csstools/postcss-hwb-function": "^4.0.10",
|
||||||
"@csstools/postcss-ic-unit": "^4.0.2",
|
"@csstools/postcss-ic-unit": "^4.0.2",
|
||||||
"@csstools/postcss-initial": "^2.0.1",
|
"@csstools/postcss-initial": "^2.0.1",
|
||||||
"@csstools/postcss-is-pseudo-class": "^5.0.1",
|
"@csstools/postcss-is-pseudo-class": "^5.0.3",
|
||||||
"@csstools/postcss-light-dark-function": "^2.0.9",
|
"@csstools/postcss-light-dark-function": "^2.0.9",
|
||||||
"@csstools/postcss-logical-float-and-clear": "^3.0.0",
|
"@csstools/postcss-logical-float-and-clear": "^3.0.0",
|
||||||
"@csstools/postcss-logical-overflow": "^2.0.0",
|
"@csstools/postcss-logical-overflow": "^2.0.0",
|
||||||
@ -14392,7 +14400,7 @@
|
|||||||
"@csstools/postcss-trigonometric-functions": "^4.0.9",
|
"@csstools/postcss-trigonometric-functions": "^4.0.9",
|
||||||
"@csstools/postcss-unset-value": "^4.0.0",
|
"@csstools/postcss-unset-value": "^4.0.0",
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
"browserslist": "^4.24.5",
|
"browserslist": "^4.25.0",
|
||||||
"css-blank-pseudo": "^7.0.1",
|
"css-blank-pseudo": "^7.0.1",
|
||||||
"css-has-pseudo": "^7.0.2",
|
"css-has-pseudo": "^7.0.2",
|
||||||
"css-prefers-color-scheme": "^10.0.0",
|
"css-prefers-color-scheme": "^10.0.0",
|
||||||
@ -14403,7 +14411,7 @@
|
|||||||
"postcss-color-hex-alpha": "^10.0.0",
|
"postcss-color-hex-alpha": "^10.0.0",
|
||||||
"postcss-color-rebeccapurple": "^10.0.0",
|
"postcss-color-rebeccapurple": "^10.0.0",
|
||||||
"postcss-custom-media": "^11.0.6",
|
"postcss-custom-media": "^11.0.6",
|
||||||
"postcss-custom-properties": "^14.0.5",
|
"postcss-custom-properties": "^14.0.6",
|
||||||
"postcss-custom-selectors": "^8.0.5",
|
"postcss-custom-selectors": "^8.0.5",
|
||||||
"postcss-dir-pseudo-class": "^9.0.1",
|
"postcss-dir-pseudo-class": "^9.0.1",
|
||||||
"postcss-double-position-gradients": "^6.0.2",
|
"postcss-double-position-gradients": "^6.0.2",
|
||||||
@ -14414,7 +14422,7 @@
|
|||||||
"postcss-image-set-function": "^7.0.0",
|
"postcss-image-set-function": "^7.0.0",
|
||||||
"postcss-lab-function": "^7.0.10",
|
"postcss-lab-function": "^7.0.10",
|
||||||
"postcss-logical": "^8.1.0",
|
"postcss-logical": "^8.1.0",
|
||||||
"postcss-nesting": "^13.0.1",
|
"postcss-nesting": "^13.0.2",
|
||||||
"postcss-opacity-percentage": "^3.0.0",
|
"postcss-opacity-percentage": "^3.0.0",
|
||||||
"postcss-overflow-shorthand": "^6.0.0",
|
"postcss-overflow-shorthand": "^6.0.0",
|
||||||
"postcss-page-break": "^3.0.4",
|
"postcss-page-break": "^3.0.4",
|
||||||
@ -14989,7 +14997,7 @@
|
|||||||
"version": "19.1.0",
|
"version": "19.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
||||||
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.26.0"
|
"scheduler": "^0.26.0"
|
||||||
@ -15788,7 +15796,7 @@
|
|||||||
"version": "0.26.0",
|
"version": "0.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
|
||||||
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
|
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/schema-dts": {
|
"node_modules/schema-dts": {
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@goauthentik/docusaurus-config",
|
"name": "@goauthentik/docusaurus-config",
|
||||||
"version": "2.0.0",
|
"version": "2.1.1",
|
||||||
"description": "authentik's Docusaurus config",
|
"description": "authentik's Docusaurus config",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -p ."
|
"build": "tsc -p .",
|
||||||
|
"prettier": "prettier --write .",
|
||||||
|
"prettier-check": "prettier --check ."
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
@ -20,24 +22,26 @@
|
|||||||
"prism-react-renderer": "^2.4.1"
|
"prism-react-renderer": "^2.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/theme-common": "^3.8.0",
|
"@docusaurus/theme-common": "^3.8.1",
|
||||||
"@docusaurus/theme-search-algolia": "^3.8.0",
|
"@docusaurus/theme-search-algolia": "^3.8.1",
|
||||||
"@docusaurus/types": "^3.8.0",
|
"@docusaurus/types": "^3.8.1",
|
||||||
"@goauthentik/prettier-config": "^2.0.0",
|
"@goauthentik/prettier-config": "^2.0.0",
|
||||||
"@goauthentik/tsconfig": "^1.0.4",
|
"@goauthentik/tsconfig": "^1.0.4",
|
||||||
"@types/react": "^19.1.6",
|
"@types/react": "^19.1.6",
|
||||||
"@types/react-dom": "^19.1.5",
|
"@types/react-dom": "^19.1.5",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"react": "^19.1.0",
|
|
||||||
"react-dom": "^19.1.0",
|
|
||||||
"typescript": "^5.8.3"
|
"typescript": "^5.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@docusaurus/theme-common": "^3.8.0",
|
"@docusaurus/theme-common": "^3.8.1",
|
||||||
"@docusaurus/theme-search-algolia": "^3.8.0",
|
"@docusaurus/theme-search-algolia": "^3.8.1",
|
||||||
"@docusaurus/types": "^3.8.0",
|
"@docusaurus/types": "^3.8.0",
|
||||||
"react": "^18.0.0 || ^19.0.0",
|
"react": ">=18",
|
||||||
"react-dom": "^18.0.0 || ^19.0.0"
|
"react-dom": ">=18"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
@ -53,6 +57,12 @@
|
|||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@docusaurus/theme-search-algolia": {
|
"@docusaurus/theme-search-algolia": {
|
||||||
"optional": true
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
182
packages/eslint-config/package-lock.json
generated
182
packages/eslint-config/package-lock.json
generated
@ -216,9 +216,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/config-array": {
|
"node_modules/@eslint/config-array": {
|
||||||
"version": "0.20.0",
|
"version": "0.20.1",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz",
|
||||||
"integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
|
"integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/object-schema": "^2.1.6",
|
"@eslint/object-schema": "^2.1.6",
|
||||||
@ -274,9 +274,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.28.0",
|
"version": "9.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.29.0.tgz",
|
||||||
"integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==",
|
"integrity": "sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -576,17 +576,17 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.1.tgz",
|
||||||
"integrity": "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==",
|
"integrity": "sha512-STXcN6ebF6li4PxwNeFnqF8/2BNDvBupf2OPx2yWNzr6mKNGF7q49VM00Pz5FaomJyqvbXpY6PhO+T9w139YEQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.34.0",
|
"@typescript-eslint/scope-manager": "8.34.1",
|
||||||
"@typescript-eslint/type-utils": "8.34.0",
|
"@typescript-eslint/type-utils": "8.34.1",
|
||||||
"@typescript-eslint/utils": "8.34.0",
|
"@typescript-eslint/utils": "8.34.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.34.0",
|
"@typescript-eslint/visitor-keys": "8.34.1",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^7.0.0",
|
"ignore": "^7.0.0",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
@ -600,7 +600,7 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@typescript-eslint/parser": "^8.34.0",
|
"@typescript-eslint/parser": "^8.34.1",
|
||||||
"eslint": "^8.57.0 || ^9.0.0",
|
"eslint": "^8.57.0 || ^9.0.0",
|
||||||
"typescript": ">=4.8.4 <5.9.0"
|
"typescript": ">=4.8.4 <5.9.0"
|
||||||
}
|
}
|
||||||
@ -616,16 +616,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.1.tgz",
|
||||||
"integrity": "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==",
|
"integrity": "sha512-4O3idHxhyzjClSMJ0a29AcoK0+YwnEqzI6oz3vlRf3xw0zbzt15MzXwItOlnr5nIth6zlY2RENLsOPvhyrKAQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.34.0",
|
"@typescript-eslint/scope-manager": "8.34.1",
|
||||||
"@typescript-eslint/types": "8.34.0",
|
"@typescript-eslint/types": "8.34.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.34.0",
|
"@typescript-eslint/typescript-estree": "8.34.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.34.0",
|
"@typescript-eslint/visitor-keys": "8.34.1",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -641,14 +641,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/project-service": {
|
"node_modules/@typescript-eslint/project-service": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.1.tgz",
|
||||||
"integrity": "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==",
|
"integrity": "sha512-nuHlOmFZfuRwLJKDGQOVc0xnQrAmuq1Mj/ISou5044y1ajGNp2BNliIqp7F2LPQ5sForz8lempMFCovfeS1XoA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/tsconfig-utils": "^8.34.0",
|
"@typescript-eslint/tsconfig-utils": "^8.34.1",
|
||||||
"@typescript-eslint/types": "^8.34.0",
|
"@typescript-eslint/types": "^8.34.1",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -663,14 +663,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.1.tgz",
|
||||||
"integrity": "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==",
|
"integrity": "sha512-beu6o6QY4hJAgL1E8RaXNC071G4Kso2MGmJskCFQhRhg8VOH/FDbC8soP8NHN7e/Hdphwp8G8cE6OBzC8o41ZA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.34.0",
|
"@typescript-eslint/types": "8.34.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.34.0"
|
"@typescript-eslint/visitor-keys": "8.34.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -681,9 +681,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
"node_modules/@typescript-eslint/tsconfig-utils": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.1.tgz",
|
||||||
"integrity": "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==",
|
"integrity": "sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -698,14 +698,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.1.tgz",
|
||||||
"integrity": "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==",
|
"integrity": "sha512-Tv7tCCr6e5m8hP4+xFugcrwTOucB8lshffJ6zf1mF1TbU67R+ntCc6DzLNKM+s/uzDyv8gLq7tufaAhIBYeV8g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.34.0",
|
"@typescript-eslint/typescript-estree": "8.34.1",
|
||||||
"@typescript-eslint/utils": "8.34.0",
|
"@typescript-eslint/utils": "8.34.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.1.0"
|
"ts-api-utils": "^2.1.0"
|
||||||
},
|
},
|
||||||
@ -722,9 +722,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.1.tgz",
|
||||||
"integrity": "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==",
|
"integrity": "sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -736,16 +736,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.1.tgz",
|
||||||
"integrity": "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==",
|
"integrity": "sha512-rjCNqqYPuMUF5ODD+hWBNmOitjBWghkGKJg6hiCHzUvXRy6rK22Jd3rwbP2Xi+R7oYVvIKhokHVhH41BxPV5mA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/project-service": "8.34.0",
|
"@typescript-eslint/project-service": "8.34.1",
|
||||||
"@typescript-eslint/tsconfig-utils": "8.34.0",
|
"@typescript-eslint/tsconfig-utils": "8.34.1",
|
||||||
"@typescript-eslint/types": "8.34.0",
|
"@typescript-eslint/types": "8.34.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.34.0",
|
"@typescript-eslint/visitor-keys": "8.34.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
@ -765,9 +765,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
|
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -804,16 +804,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.1.tgz",
|
||||||
"integrity": "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==",
|
"integrity": "sha512-mqOwUdZ3KjtGk7xJJnLbHxTuWVn3GO2WZZuM+Slhkun4+qthLdXx32C8xIXbO1kfCECb3jIs3eoxK3eryk7aoQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.7.0",
|
"@eslint-community/eslint-utils": "^4.7.0",
|
||||||
"@typescript-eslint/scope-manager": "8.34.0",
|
"@typescript-eslint/scope-manager": "8.34.1",
|
||||||
"@typescript-eslint/types": "8.34.0",
|
"@typescript-eslint/types": "8.34.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.34.0"
|
"@typescript-eslint/typescript-estree": "8.34.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -828,14 +828,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.1.tgz",
|
||||||
"integrity": "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==",
|
"integrity": "sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.34.0",
|
"@typescript-eslint/types": "8.34.1",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -846,9 +846,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.14.1",
|
"version": "8.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
@ -1554,18 +1554,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.28.0",
|
"version": "9.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.29.0.tgz",
|
||||||
"integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==",
|
"integrity": "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
"@eslint/config-array": "^0.20.0",
|
"@eslint/config-array": "^0.20.1",
|
||||||
"@eslint/config-helpers": "^0.2.1",
|
"@eslint/config-helpers": "^0.2.1",
|
||||||
"@eslint/core": "^0.14.0",
|
"@eslint/core": "^0.14.0",
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@eslint/js": "9.28.0",
|
"@eslint/js": "9.29.0",
|
||||||
"@eslint/plugin-kit": "^0.3.1",
|
"@eslint/plugin-kit": "^0.3.1",
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
@ -1577,9 +1577,9 @@
|
|||||||
"cross-spawn": "^7.0.6",
|
"cross-spawn": "^7.0.6",
|
||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"eslint-scope": "^8.3.0",
|
"eslint-scope": "^8.4.0",
|
||||||
"eslint-visitor-keys": "^4.2.0",
|
"eslint-visitor-keys": "^4.2.1",
|
||||||
"espree": "^10.3.0",
|
"espree": "^10.4.0",
|
||||||
"esquery": "^1.5.0",
|
"esquery": "^1.5.0",
|
||||||
"esutils": "^2.0.2",
|
"esutils": "^2.0.2",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
@ -1792,9 +1792,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-scope": {
|
"node_modules/eslint-scope": {
|
||||||
"version": "8.3.0",
|
"version": "8.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
|
||||||
"integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
|
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esrecurse": "^4.3.0",
|
"esrecurse": "^4.3.0",
|
||||||
@ -1808,9 +1808,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-visitor-keys": {
|
"node_modules/eslint-visitor-keys": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
|
||||||
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
|
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -1820,14 +1820,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/espree": {
|
"node_modules/espree": {
|
||||||
"version": "10.3.0",
|
"version": "10.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
|
||||||
"integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
|
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "^8.14.0",
|
"acorn": "^8.15.0",
|
||||||
"acorn-jsx": "^5.3.2",
|
"acorn-jsx": "^5.3.2",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@ -4035,15 +4035,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript-eslint": {
|
"node_modules/typescript-eslint": {
|
||||||
"version": "8.34.0",
|
"version": "8.34.1",
|
||||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.34.0.tgz",
|
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.34.1.tgz",
|
||||||
"integrity": "sha512-MRpfN7uYjTrTGigFCt8sRyNqJFhjN0WwZecldaqhWm+wy0gaRt8Edb/3cuUy0zdq2opJWT6iXINKAtewnDOltQ==",
|
"integrity": "sha512-XjS+b6Vg9oT1BaIUfkW3M3LvqZE++rbzAMEHuccCfO/YkP43ha6w3jTEMilQxMF92nVOYCcdjv1ZUhAa1D/0ow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "8.34.0",
|
"@typescript-eslint/eslint-plugin": "8.34.1",
|
||||||
"@typescript-eslint/parser": "8.34.0",
|
"@typescript-eslint/parser": "8.34.1",
|
||||||
"@typescript-eslint/utils": "8.34.0"
|
"@typescript-eslint/utils": "8.34.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
9
packages/prettier-config/.prettierignore
Normal file
9
packages/prettier-config/.prettierignore
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Prettier Ignorefile
|
||||||
|
|
||||||
|
## Static Files
|
||||||
|
**/LICENSE
|
||||||
|
|
||||||
|
## Build asset directories
|
||||||
|
coverage
|
||||||
|
dist
|
||||||
|
out
|
@ -45,7 +45,6 @@ export const AuthentikPrettierConfig = {
|
|||||||
"^(@goauthentik/|#)user.+",
|
"^(@goauthentik/|#)user.+",
|
||||||
"^(@goauthentik/|#)admin.+",
|
"^(@goauthentik/|#)admin.+",
|
||||||
"^(@goauthentik/|#)flow.+",
|
"^(@goauthentik/|#)flow.+",
|
||||||
"^(@goauthentik/|#)flow.+",
|
|
||||||
|
|
||||||
"^#.+",
|
"^#.+",
|
||||||
"^@goauthentik.+",
|
"^@goauthentik.+",
|
||||||
|
32
packages/prettier-config/package-lock.json
generated
32
packages/prettier-config/package-lock.json
generated
@ -1,29 +1,29 @@
|
|||||||
{
|
{
|
||||||
"name": "@goauthentik/prettier-config",
|
"name": "@goauthentik/prettier-config",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@goauthentik/prettier-config",
|
"name": "@goauthentik/prettier-config",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@goauthentik/tsconfig": "^1.0.1",
|
"@goauthentik/tsconfig": "^1.0.1",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prettier-plugin-organize-imports": "^4.1.0",
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
"prettier-plugin-packagejson": "^2.5.14",
|
"prettier-plugin-packagejson": "^2.5.15",
|
||||||
"typescript": "^5.8.2"
|
"typescript": "^5.8.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.11"
|
"node": ">=22"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prettier-plugin-organize-imports": "^4.1.0",
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
"prettier-plugin-packagejson": "^2.5.14"
|
"prettier-plugin-packagejson": "^2.5.15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
@ -206,9 +206,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@pkgr/core": {
|
"node_modules/@pkgr/core": {
|
||||||
"version": "0.2.4",
|
"version": "0.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz",
|
||||||
"integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==",
|
"integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -437,14 +437,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prettier-plugin-packagejson": {
|
"node_modules/prettier-plugin-packagejson": {
|
||||||
"version": "2.5.14",
|
"version": "2.5.15",
|
||||||
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.14.tgz",
|
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.15.tgz",
|
||||||
"integrity": "sha512-h+3tSpr2nVpp+YOK1MDIYtYhHVXr8/0V59UUbJpIJFaqi3w4fvUokJo6eV8W+vELrUXIZzJ+DKm5G7lYzrMcKQ==",
|
"integrity": "sha512-2QSx6y4IT6LTwXtCvXAopENW5IP/aujC8fobEM2pDbs0IGkiVjW/ipPuYAHuXigbNe64aGWF7vIetukuzM3CBw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sort-package-json": "3.2.1",
|
"sort-package-json": "3.2.1",
|
||||||
"synckit": "0.11.6"
|
"synckit": "0.11.8"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"prettier": ">= 1.16.0"
|
"prettier": ">= 1.16.0"
|
||||||
@ -495,9 +495,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/synckit": {
|
"node_modules/synckit": {
|
||||||
"version": "0.11.6",
|
"version": "0.11.8",
|
||||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz",
|
||||||
"integrity": "sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==",
|
"integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@goauthentik/prettier-config",
|
"name": "@goauthentik/prettier-config",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"description": "authentik's Prettier config",
|
"description": "authentik's Prettier config",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -p ."
|
"build": "tsc -p .",
|
||||||
|
"prettier": "prettier --write .",
|
||||||
|
"prettier-check": "prettier --check ."
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": "./index.js",
|
"exports": "./index.js",
|
||||||
@ -13,17 +15,17 @@
|
|||||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prettier-plugin-organize-imports": "^4.1.0",
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
"prettier-plugin-packagejson": "^2.5.14",
|
"prettier-plugin-packagejson": "^2.5.15",
|
||||||
"typescript": "^5.8.2"
|
"typescript": "^5.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prettier-plugin-organize-imports": "^4.1.0",
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
"prettier-plugin-packagejson": "^2.5.14"
|
"prettier-plugin-packagejson": "^2.5.15"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.11"
|
"node": ">=22"
|
||||||
},
|
},
|
||||||
"types": "./out/index.d.ts",
|
"types": "./out/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "authentik"
|
name = "authentik"
|
||||||
version = "2025.6.1"
|
version = "2025.6.2"
|
||||||
description = ""
|
description = ""
|
||||||
authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }]
|
authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }]
|
||||||
requires-python = "==3.13.*"
|
requires-python = "==3.13.*"
|
||||||
@ -15,17 +15,18 @@ dependencies = [
|
|||||||
"defusedxml==0.7.1",
|
"defusedxml==0.7.1",
|
||||||
"django==5.1.11",
|
"django==5.1.11",
|
||||||
"django-countries==7.6.1",
|
"django-countries==7.6.1",
|
||||||
"django-cte==1.3.3",
|
"django-cte==2.0.0",
|
||||||
"django-filter==25.1",
|
"django-filter==25.1",
|
||||||
"django-guardian==3.0.0",
|
"django-guardian==3.0.0",
|
||||||
"django-model-utils==5.0.0",
|
"django-model-utils==5.0.0",
|
||||||
"django-pglock==1.7.2",
|
"django-pglock==1.7.2",
|
||||||
"django-prometheus==2.3.1",
|
"django-prometheus==2.4.0",
|
||||||
"django-redis==5.4.0",
|
"django-redis==6.0.0",
|
||||||
"django-storages[s3]==1.14.6",
|
"django-storages[s3]==1.14.6",
|
||||||
"django-tenants==3.8.0",
|
"django-tenants==3.8.0",
|
||||||
"djangorestframework==3.16.0",
|
"djangoql==0.18.1",
|
||||||
"djangorestframework-guardian==0.3.0",
|
"djangorestframework-guardian==0.3.0",
|
||||||
|
"djangorestframework==3.16.0",
|
||||||
"docker==7.1.0",
|
"docker==7.1.0",
|
||||||
"drf-orjson-renderer==1.7.3",
|
"drf-orjson-renderer==1.7.3",
|
||||||
"drf-spectacular==0.28.0",
|
"drf-spectacular==0.28.0",
|
||||||
@ -40,35 +41,35 @@ dependencies = [
|
|||||||
"gunicorn==23.0.0",
|
"gunicorn==23.0.0",
|
||||||
"jsonpatch==1.33",
|
"jsonpatch==1.33",
|
||||||
"jwcrypto==1.5.6",
|
"jwcrypto==1.5.6",
|
||||||
"kubernetes==32.0.1",
|
"kubernetes==33.1.0",
|
||||||
"ldap3==2.9.1",
|
"ldap3==2.9.1",
|
||||||
"lxml==5.4.0",
|
"lxml==5.4.0",
|
||||||
"msgraph-sdk==1.33.0",
|
"msgraph-sdk==1.34.0",
|
||||||
"opencontainers==0.0.14",
|
"opencontainers==0.0.14",
|
||||||
"packaging==25.0",
|
"packaging==25.0",
|
||||||
"paramiko==3.5.1",
|
"paramiko==3.5.1",
|
||||||
"psycopg[c,pool]==3.2.9",
|
"psycopg[c,pool]==3.2.9",
|
||||||
"pydantic==2.11.5",
|
"pydantic==2.11.7",
|
||||||
"pydantic-scim==0.0.8",
|
"pydantic-scim==0.0.8",
|
||||||
"pyjwt==2.10.1",
|
"pyjwt==2.10.1",
|
||||||
"pyrad==2.4",
|
"pyrad==2.4",
|
||||||
"python-kadmin-rs==0.6.0",
|
"python-kadmin-rs==0.6.1",
|
||||||
"pyyaml==6.0.2",
|
"pyyaml==6.0.2",
|
||||||
"requests-oauthlib==2.0.0",
|
"requests-oauthlib==2.0.0",
|
||||||
"scim2-filter-parser==0.7.0",
|
"scim2-filter-parser==0.7.0",
|
||||||
"sentry-sdk==2.29.1",
|
"sentry-sdk==2.30.0",
|
||||||
"service-identity==24.2.0",
|
"service-identity==24.2.0",
|
||||||
"setproctitle==1.3.6",
|
"setproctitle==1.3.6",
|
||||||
"structlog==25.4.0",
|
"structlog==25.4.0",
|
||||||
"swagger-spec-validator==3.0.4",
|
"swagger-spec-validator==3.0.4",
|
||||||
"tenant-schemas-celery==3.0.0",
|
"tenant-schemas-celery==3.0.0",
|
||||||
"twilio==9.6.2",
|
"twilio==9.6.3",
|
||||||
"ua-parser==1.0.1",
|
"ua-parser==1.0.1",
|
||||||
"unidecode==1.4.0",
|
"unidecode==1.4.0",
|
||||||
"urllib3<3",
|
"urllib3<3",
|
||||||
"uvicorn[standard]==0.34.3",
|
"uvicorn[standard]==0.34.3",
|
||||||
"watchdog==6.0.0",
|
"watchdog==6.0.0",
|
||||||
"webauthn==2.5.2",
|
"webauthn==2.6.0",
|
||||||
"wsproto==1.2.0",
|
"wsproto==1.2.0",
|
||||||
"xmlsec==1.3.15",
|
"xmlsec==1.3.15",
|
||||||
"zxcvbn==4.5.0",
|
"zxcvbn==4.5.0",
|
||||||
|
441
schema.yml
441
schema.yml
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ services:
|
|||||||
network_mode: host
|
network_mode: host
|
||||||
restart: always
|
restart: always
|
||||||
mailpit:
|
mailpit:
|
||||||
image: docker.io/axllent/mailpit:v1.26.0
|
image: docker.io/axllent/mailpit:v1.26.1
|
||||||
ports:
|
ports:
|
||||||
- 1025:1025
|
- 1025:1025
|
||||||
- 8025:8025
|
- 8025:8025
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from guardian.shortcuts import assign_perm
|
from guardian.shortcuts import assign_perm
|
||||||
from ldap3 import ALL, ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE, Connection, Server
|
from ldap3 import ALL, ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE, Connection, Server
|
||||||
@ -16,12 +15,10 @@ from authentik.flows.models import Flow
|
|||||||
from authentik.lib.generators import generate_id
|
from authentik.lib.generators import generate_id
|
||||||
from authentik.outposts.apps import MANAGED_OUTPOST
|
from authentik.outposts.apps import MANAGED_OUTPOST
|
||||||
from authentik.outposts.models import Outpost, OutpostConfig, OutpostType
|
from authentik.outposts.models import Outpost, OutpostConfig, OutpostType
|
||||||
from authentik.outposts.tests.test_ws import patched__get_ct_cached
|
|
||||||
from authentik.providers.ldap.models import APIAccessMode, LDAPProvider
|
from authentik.providers.ldap.models import APIAccessMode, LDAPProvider
|
||||||
from tests.e2e.utils import SeleniumTestCase, retry
|
from tests.e2e.utils import SeleniumTestCase, retry
|
||||||
|
|
||||||
|
|
||||||
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
|
|
||||||
class TestProviderLDAP(SeleniumTestCase):
|
class TestProviderLDAP(SeleniumTestCase):
|
||||||
"""LDAP and Outpost e2e tests"""
|
"""LDAP and Outpost e2e tests"""
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ from json import loads
|
|||||||
from sys import platform
|
from sys import platform
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from unittest.case import skip, skipUnless
|
from unittest.case import skip, skipUnless
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from channels.testing import ChannelsLiveServerTestCase
|
from channels.testing import ChannelsLiveServerTestCase
|
||||||
from jwt import decode
|
from jwt import decode
|
||||||
@ -18,12 +17,10 @@ from authentik.flows.models import Flow
|
|||||||
from authentik.lib.generators import generate_id
|
from authentik.lib.generators import generate_id
|
||||||
from authentik.outposts.models import DockerServiceConnection, Outpost, OutpostConfig, OutpostType
|
from authentik.outposts.models import DockerServiceConnection, Outpost, OutpostConfig, OutpostType
|
||||||
from authentik.outposts.tasks import outpost_connection_discovery
|
from authentik.outposts.tasks import outpost_connection_discovery
|
||||||
from authentik.outposts.tests.test_ws import patched__get_ct_cached
|
|
||||||
from authentik.providers.proxy.models import ProxyProvider
|
from authentik.providers.proxy.models import ProxyProvider
|
||||||
from tests.e2e.utils import SeleniumTestCase, retry
|
from tests.e2e.utils import SeleniumTestCase, retry
|
||||||
|
|
||||||
|
|
||||||
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
|
|
||||||
class TestProviderProxy(SeleniumTestCase):
|
class TestProviderProxy(SeleniumTestCase):
|
||||||
"""Proxy and Outpost e2e tests"""
|
"""Proxy and Outpost e2e tests"""
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ from json import loads
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from unittest import skip
|
from unittest import skip
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
|
|
||||||
@ -13,12 +12,10 @@ from authentik.core.models import Application
|
|||||||
from authentik.flows.models import Flow
|
from authentik.flows.models import Flow
|
||||||
from authentik.lib.generators import generate_id
|
from authentik.lib.generators import generate_id
|
||||||
from authentik.outposts.models import Outpost, OutpostType
|
from authentik.outposts.models import Outpost, OutpostType
|
||||||
from authentik.outposts.tests.test_ws import patched__get_ct_cached
|
|
||||||
from authentik.providers.proxy.models import ProxyMode, ProxyProvider
|
from authentik.providers.proxy.models import ProxyMode, ProxyProvider
|
||||||
from tests.e2e.utils import SeleniumTestCase, retry
|
from tests.e2e.utils import SeleniumTestCase, retry
|
||||||
|
|
||||||
|
|
||||||
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
|
|
||||||
class TestProviderProxyForward(SeleniumTestCase):
|
class TestProviderProxyForward(SeleniumTestCase):
|
||||||
"""Proxy and Outpost e2e tests"""
|
"""Proxy and Outpost e2e tests"""
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from pyrad.client import Client
|
from pyrad.client import Client
|
||||||
from pyrad.dictionary import Dictionary
|
from pyrad.dictionary import Dictionary
|
||||||
@ -13,12 +12,10 @@ from authentik.core.models import Application, User
|
|||||||
from authentik.flows.models import Flow
|
from authentik.flows.models import Flow
|
||||||
from authentik.lib.generators import generate_id, generate_key
|
from authentik.lib.generators import generate_id, generate_key
|
||||||
from authentik.outposts.models import Outpost, OutpostConfig, OutpostType
|
from authentik.outposts.models import Outpost, OutpostConfig, OutpostType
|
||||||
from authentik.outposts.tests.test_ws import patched__get_ct_cached
|
|
||||||
from authentik.providers.radius.models import RadiusProvider
|
from authentik.providers.radius.models import RadiusProvider
|
||||||
from tests.e2e.utils import SeleniumTestCase, retry
|
from tests.e2e.utils import SeleniumTestCase, retry
|
||||||
|
|
||||||
|
|
||||||
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
|
|
||||||
class TestProviderRadius(SeleniumTestCase):
|
class TestProviderRadius(SeleniumTestCase):
|
||||||
"""Radius Outpost e2e tests"""
|
"""Radius Outpost e2e tests"""
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""authentik e2e testing utilities"""
|
"""authentik e2e testing utilities"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
|
||||||
import socket
|
import socket
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from functools import lru_cache, wraps
|
from functools import lru_cache, wraps
|
||||||
@ -37,22 +36,12 @@ from authentik.core.api.users import UserSerializer
|
|||||||
from authentik.core.models import User
|
from authentik.core.models import User
|
||||||
from authentik.core.tests.utils import create_test_admin_user
|
from authentik.core.tests.utils import create_test_admin_user
|
||||||
from authentik.lib.generators import generate_id
|
from authentik.lib.generators import generate_id
|
||||||
|
from authentik.root.test_runner import get_docker_tag
|
||||||
|
|
||||||
IS_CI = "CI" in environ
|
IS_CI = "CI" in environ
|
||||||
RETRIES = int(environ.get("RETRIES", "3")) if IS_CI else 1
|
RETRIES = int(environ.get("RETRIES", "3")) if IS_CI else 1
|
||||||
|
|
||||||
|
|
||||||
def get_docker_tag() -> str:
|
|
||||||
"""Get docker-tag based off of CI variables"""
|
|
||||||
env_pr_branch = "GITHUB_HEAD_REF"
|
|
||||||
default_branch = "GITHUB_REF"
|
|
||||||
branch_name = os.environ.get(default_branch, "main")
|
|
||||||
if os.environ.get(env_pr_branch, "") != "":
|
|
||||||
branch_name = os.environ[env_pr_branch]
|
|
||||||
branch_name = branch_name.replace("refs/heads/", "").replace("/", "-")
|
|
||||||
return f"gh-{branch_name}"
|
|
||||||
|
|
||||||
|
|
||||||
def get_local_ip() -> str:
|
def get_local_ip() -> str:
|
||||||
"""Get the local machine's IP"""
|
"""Get the local machine's IP"""
|
||||||
hostname = socket.gethostname()
|
hostname = socket.gethostname()
|
||||||
|
2014
web/package-lock.json
generated
2014
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -93,19 +93,21 @@
|
|||||||
"@floating-ui/dom": "^1.6.11",
|
"@floating-ui/dom": "^1.6.11",
|
||||||
"@formatjs/intl-listformat": "^7.7.11",
|
"@formatjs/intl-listformat": "^7.7.11",
|
||||||
"@fortawesome/fontawesome-free": "^6.7.2",
|
"@fortawesome/fontawesome-free": "^6.7.2",
|
||||||
"@goauthentik/api": "^2025.6.1-1749515784",
|
"@goauthentik/api": "^2025.6.2-1750246811",
|
||||||
"@lit/context": "^1.1.2",
|
"@lit/context": "^1.1.2",
|
||||||
"@lit/localize": "^0.12.2",
|
"@lit/localize": "^0.12.2",
|
||||||
"@lit/reactive-element": "^2.0.4",
|
"@lit/reactive-element": "^2.0.4",
|
||||||
"@lit/task": "^1.0.2",
|
"@lit/task": "^1.0.2",
|
||||||
"@mdx-js/mdx": "^3.1.0",
|
"@mdx-js/mdx": "^3.1.0",
|
||||||
|
"@mrmarble/djangoql-completion": "^0.8.3",
|
||||||
"@open-wc/lit-helpers": "^0.7.0",
|
"@open-wc/lit-helpers": "^0.7.0",
|
||||||
|
"@openlayers-elements/core": "^0.4.0",
|
||||||
|
"@openlayers-elements/maps": "^0.4.0",
|
||||||
"@patternfly/elements": "^4.1.0",
|
"@patternfly/elements": "^4.1.0",
|
||||||
"@patternfly/patternfly": "^4.224.2",
|
"@patternfly/patternfly": "^4.224.2",
|
||||||
"@sentry/browser": "^9.28.0",
|
"@sentry/browser": "^9.30.0",
|
||||||
"@spotlightjs/spotlight": "^2.13.3",
|
"@spotlightjs/spotlight": "^3.0.1",
|
||||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||||
"base64-js": "^1.5.1",
|
|
||||||
"change-case": "^5.4.4",
|
"change-case": "^5.4.4",
|
||||||
"chart.js": "^4.4.9",
|
"chart.js": "^4.4.9",
|
||||||
"chartjs-adapter-date-fns": "^3.0.0",
|
"chartjs-adapter-date-fns": "^3.0.0",
|
||||||
@ -137,6 +139,7 @@
|
|||||||
"trusted-types": "^2.0.0",
|
"trusted-types": "^2.0.0",
|
||||||
"ts-pattern": "^5.7.1",
|
"ts-pattern": "^5.7.1",
|
||||||
"unist-util-visit": "^5.0.0",
|
"unist-util-visit": "^5.0.0",
|
||||||
|
"webauthn-polyfills": "^0.1.7",
|
||||||
"webcomponent-qr-code": "^1.2.0",
|
"webcomponent-qr-code": "^1.2.0",
|
||||||
"yaml": "^2.8.0"
|
"yaml": "^2.8.0"
|
||||||
},
|
},
|
||||||
@ -170,16 +173,16 @@
|
|||||||
"@types/react-dom": "^19.1.5",
|
"@types/react-dom": "^19.1.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.8.0",
|
"@typescript-eslint/eslint-plugin": "^8.8.0",
|
||||||
"@typescript-eslint/parser": "^8.8.0",
|
"@typescript-eslint/parser": "^8.8.0",
|
||||||
"@wdio/browser-runner": "9.4",
|
"@wdio/browser-runner": "9.15",
|
||||||
"@wdio/cli": "9.4",
|
"@wdio/cli": "9.15",
|
||||||
"@wdio/spec-reporter": "^9.1.2",
|
"@wdio/spec-reporter": "^9.15.0",
|
||||||
"@web/test-runner": "^0.20.2",
|
"@web/test-runner": "^0.20.2",
|
||||||
"chromedriver": "^136.0.3",
|
"chromedriver": "^136.0.3",
|
||||||
"esbuild": "^0.25.5",
|
"esbuild": "^0.25.5",
|
||||||
"esbuild-plugin-copy": "^2.1.1",
|
"esbuild-plugin-copy": "^2.1.1",
|
||||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||||
"esbuild-plugins-node-modules-polyfill": "^1.7.0",
|
"esbuild-plugins-node-modules-polyfill": "^1.7.0",
|
||||||
"eslint": "^9.28.0",
|
"eslint": "^9.29.0",
|
||||||
"eslint-plugin-lit": "^2.1.1",
|
"eslint-plugin-lit": "^2.1.1",
|
||||||
"eslint-plugin-wc": "^3.0.1",
|
"eslint-plugin-wc": "^3.0.1",
|
||||||
"github-slugger": "^2.0.0",
|
"github-slugger": "^2.0.0",
|
||||||
@ -194,7 +197,7 @@
|
|||||||
"storybook-addon-mock": "^5.0.0",
|
"storybook-addon-mock": "^5.0.0",
|
||||||
"turnstile-types": "^1.2.3",
|
"turnstile-types": "^1.2.3",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"typescript-eslint": "^8.34.0",
|
"typescript-eslint": "^8.34.1",
|
||||||
"vite-plugin-lit-css": "^2.0.0",
|
"vite-plugin-lit-css": "^2.0.0",
|
||||||
"vite-tsconfig-paths": "^5.0.1",
|
"vite-tsconfig-paths": "^5.0.1",
|
||||||
"wireit": "^0.14.12"
|
"wireit": "^0.14.12"
|
||||||
|
2
web/packages/core/types/node.d.ts
vendored
2
web/packages/core/types/node.d.ts
vendored
@ -14,7 +14,7 @@ declare module "module" {
|
|||||||
* const relativeDirname = dirname(fileURLToPath(import.meta.url));
|
* const relativeDirname = dirname(fileURLToPath(import.meta.url));
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line no-var
|
|
||||||
var __dirname: string;
|
var __dirname: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@goauthentik/api": "^2024.6.0-1719577139",
|
"@goauthentik/api": "^2024.6.0-1719577139",
|
||||||
"base64-js": "^1.5.1",
|
|
||||||
"bootstrap": "^4.6.1",
|
"bootstrap": "^4.6.1",
|
||||||
"formdata-polyfill": "^4.0.10",
|
"formdata-polyfill": "^4.0.10",
|
||||||
"jquery": "^3.7.1",
|
"jquery": "^3.7.1",
|
||||||
"weakmap-polyfill": "^2.0.4"
|
"weakmap-polyfill": "^2.0.4",
|
||||||
|
"webauthn-polyfills": "^0.1.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@goauthentik/core": "^1.0.0",
|
"@goauthentik/core": "^1.0.0",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { fromByteArray } from "base64-js";
|
|
||||||
import "formdata-polyfill";
|
import "formdata-polyfill";
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
import "weakmap-polyfill";
|
import "weakmap-polyfill";
|
||||||
|
import "webauthn-polyfills";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type AuthenticatorValidationChallenge,
|
type AuthenticatorValidationChallenge,
|
||||||
@ -257,47 +257,9 @@ class AutosubmitStage extends Stage<AutosubmitChallenge> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Assertion {
|
|
||||||
id: string;
|
|
||||||
rawId: string;
|
|
||||||
type: string;
|
|
||||||
registrationClientExtensions: string;
|
|
||||||
response: {
|
|
||||||
clientDataJSON: string;
|
|
||||||
attestationObject: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AuthAssertion {
|
|
||||||
id: string;
|
|
||||||
rawId: string;
|
|
||||||
type: string;
|
|
||||||
assertionClientExtensions: string;
|
|
||||||
response: {
|
|
||||||
clientDataJSON: string;
|
|
||||||
authenticatorData: string;
|
|
||||||
signature: string;
|
|
||||||
userHandle: string | null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge> {
|
class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge> {
|
||||||
deviceChallenge?: DeviceChallenge;
|
deviceChallenge?: DeviceChallenge;
|
||||||
|
|
||||||
b64enc(buf: Uint8Array): string {
|
|
||||||
return fromByteArray(buf).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
b64RawEnc(buf: Uint8Array): string {
|
|
||||||
return fromByteArray(buf).replace(/\+/g, "-").replace(/\//g, "_");
|
|
||||||
}
|
|
||||||
|
|
||||||
u8arr(input: string): Uint8Array {
|
|
||||||
return Uint8Array.from(atob(input.replace(/_/g, "/").replace(/-/g, "+")), (c) =>
|
|
||||||
c.charCodeAt(0),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkWebAuthnSupport(): boolean {
|
checkWebAuthnSupport(): boolean {
|
||||||
if ("credentials" in navigator) {
|
if ("credentials" in navigator) {
|
||||||
return true;
|
return true;
|
||||||
@ -310,98 +272,6 @@ class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms items in the credentialCreateOptions generated on the server
|
|
||||||
* into byte arrays expected by the navigator.credentials.create() call
|
|
||||||
*/
|
|
||||||
transformCredentialCreateOptions(
|
|
||||||
credentialCreateOptions: PublicKeyCredentialCreationOptions,
|
|
||||||
userId: string,
|
|
||||||
): PublicKeyCredentialCreationOptions {
|
|
||||||
const user = credentialCreateOptions.user;
|
|
||||||
// Because json can't contain raw bytes, the server base64-encodes the User ID
|
|
||||||
// So to get the base64 encoded byte array, we first need to convert it to a regular
|
|
||||||
// string, then a byte array, re-encode it and wrap that in an array.
|
|
||||||
const stringId = decodeURIComponent(window.atob(userId));
|
|
||||||
user.id = this.u8arr(this.b64enc(this.u8arr(stringId)));
|
|
||||||
const challenge = this.u8arr(credentialCreateOptions.challenge.toString());
|
|
||||||
|
|
||||||
return Object.assign({}, credentialCreateOptions, {
|
|
||||||
challenge,
|
|
||||||
user,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms the binary data in the credential into base64 strings
|
|
||||||
* for posting to the server.
|
|
||||||
* @param {PublicKeyCredential} newAssertion
|
|
||||||
*/
|
|
||||||
transformNewAssertionForServer(newAssertion: PublicKeyCredential): Assertion {
|
|
||||||
const attObj = new Uint8Array(
|
|
||||||
(newAssertion.response as AuthenticatorAttestationResponse).attestationObject,
|
|
||||||
);
|
|
||||||
const clientDataJSON = new Uint8Array(newAssertion.response.clientDataJSON);
|
|
||||||
const rawId = new Uint8Array(newAssertion.rawId);
|
|
||||||
|
|
||||||
const registrationClientExtensions = newAssertion.getClientExtensionResults();
|
|
||||||
return {
|
|
||||||
id: newAssertion.id,
|
|
||||||
rawId: this.b64enc(rawId),
|
|
||||||
type: newAssertion.type,
|
|
||||||
registrationClientExtensions: JSON.stringify(registrationClientExtensions),
|
|
||||||
response: {
|
|
||||||
clientDataJSON: this.b64enc(clientDataJSON),
|
|
||||||
attestationObject: this.b64enc(attObj),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
transformCredentialRequestOptions(
|
|
||||||
credentialRequestOptions: PublicKeyCredentialRequestOptions,
|
|
||||||
): PublicKeyCredentialRequestOptions {
|
|
||||||
const challenge = this.u8arr(credentialRequestOptions.challenge.toString());
|
|
||||||
|
|
||||||
const allowCredentials = (credentialRequestOptions.allowCredentials || []).map(
|
|
||||||
(credentialDescriptor) => {
|
|
||||||
const id = this.u8arr(credentialDescriptor.id.toString());
|
|
||||||
return Object.assign({}, credentialDescriptor, { id });
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return Object.assign({}, credentialRequestOptions, {
|
|
||||||
challenge,
|
|
||||||
allowCredentials,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encodes the binary data in the assertion into strings for posting to the server.
|
|
||||||
* @param {PublicKeyCredential} newAssertion
|
|
||||||
*/
|
|
||||||
transformAssertionForServer(newAssertion: PublicKeyCredential): AuthAssertion {
|
|
||||||
const response = newAssertion.response as AuthenticatorAssertionResponse;
|
|
||||||
const authData = new Uint8Array(response.authenticatorData);
|
|
||||||
const clientDataJSON = new Uint8Array(response.clientDataJSON);
|
|
||||||
const rawId = new Uint8Array(newAssertion.rawId);
|
|
||||||
const sig = new Uint8Array(response.signature);
|
|
||||||
const assertionClientExtensions = newAssertion.getClientExtensionResults();
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: newAssertion.id,
|
|
||||||
rawId: this.b64enc(rawId),
|
|
||||||
type: newAssertion.type,
|
|
||||||
assertionClientExtensions: JSON.stringify(assertionClientExtensions),
|
|
||||||
|
|
||||||
response: {
|
|
||||||
clientDataJSON: this.b64RawEnc(clientDataJSON),
|
|
||||||
signature: this.b64RawEnc(sig),
|
|
||||||
authenticatorData: this.b64RawEnc(authData),
|
|
||||||
userHandle: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.challenge.deviceChallenges.length === 1) {
|
if (this.challenge.deviceChallenges.length === 1) {
|
||||||
this.deviceChallenge = this.challenge.deviceChallenges[0];
|
this.deviceChallenge = this.challenge.deviceChallenges[0];
|
||||||
@ -505,8 +375,8 @@ class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge>
|
|||||||
`);
|
`);
|
||||||
navigator.credentials
|
navigator.credentials
|
||||||
.get({
|
.get({
|
||||||
publicKey: this.transformCredentialRequestOptions(
|
publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(
|
||||||
this.deviceChallenge?.challenge as PublicKeyCredentialRequestOptions,
|
this.deviceChallenge?.challenge as PublicKeyCredentialRequestOptionsJSON,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
.then((assertion) => {
|
.then((assertion) => {
|
||||||
@ -514,15 +384,9 @@ class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge>
|
|||||||
throw new Error("No assertion");
|
throw new Error("No assertion");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// we now have an authentication assertion! encode the byte arrays contained
|
|
||||||
// in the assertion data as strings for posting to the server
|
|
||||||
const transformedAssertionForServer = this.transformAssertionForServer(
|
|
||||||
assertion as PublicKeyCredential,
|
|
||||||
);
|
|
||||||
|
|
||||||
// post the assertion to the server for verification.
|
// post the assertion to the server for verification.
|
||||||
this.executor.submit({
|
this.executor.submit({
|
||||||
webauthn: transformedAssertionForServer,
|
webauthn: (assertion as PublicKeyCredential).toJSON(),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new Error(`Error when validating assertion on server: ${err}`);
|
throw new Error(`Error when validating assertion on server: ${err}`);
|
||||||
|
@ -88,7 +88,8 @@ export class RecentEventsCard extends Table<Event> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return super.renderEmpty(
|
return super.renderEmpty(
|
||||||
html`<ak-empty-state header=${msg("No Events found.")}>
|
html`<ak-empty-state
|
||||||
|
><span slot="header">${msg("No Events found.")}</span>
|
||||||
<div slot="body">${msg("No matching events could be found.")}</div>
|
<div slot="body">${msg("No matching events could be found.")}</div>
|
||||||
</ak-empty-state>`,
|
</ak-empty-state>`,
|
||||||
);
|
);
|
||||||
|
@ -5,6 +5,7 @@ import { policyEngineModes } from "@goauthentik/admin/policies/PolicyEngineModes
|
|||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import "@goauthentik/components/ak-file-input";
|
import "@goauthentik/components/ak-file-input";
|
||||||
import "@goauthentik/components/ak-radio-input";
|
import "@goauthentik/components/ak-radio-input";
|
||||||
|
import "@goauthentik/components/ak-slug-input";
|
||||||
import "@goauthentik/components/ak-switch-input";
|
import "@goauthentik/components/ak-switch-input";
|
||||||
import "@goauthentik/components/ak-text-input";
|
import "@goauthentik/components/ak-text-input";
|
||||||
import "@goauthentik/components/ak-textarea-input";
|
import "@goauthentik/components/ak-textarea-input";
|
||||||
@ -130,14 +131,14 @@ export class ApplicationForm extends WithCapabilitiesConfig(ModelForm<Applicatio
|
|||||||
required
|
required
|
||||||
help=${msg("Application's display Name.")}
|
help=${msg("Application's display Name.")}
|
||||||
></ak-text-input>
|
></ak-text-input>
|
||||||
<ak-text-input
|
<ak-slug-input
|
||||||
name="slug"
|
name="slug"
|
||||||
value=${ifDefined(this.instance?.slug)}
|
value=${ifDefined(this.instance?.slug)}
|
||||||
label=${msg("Slug")}
|
label=${msg("Slug")}
|
||||||
required
|
required
|
||||||
help=${msg("Internal application name used in URLs.")}
|
help=${msg("Internal application name used in URLs.")}
|
||||||
input-hint="code"
|
input-hint="code"
|
||||||
></ak-text-input>
|
></ak-slug-input>
|
||||||
<ak-text-input
|
<ak-text-input
|
||||||
name="group"
|
name="group"
|
||||||
value=${ifDefined(this.instance?.group)}
|
value=${ifDefined(this.instance?.group)}
|
||||||
|
@ -117,13 +117,11 @@ export class ApplicationWizardApplicationStep extends ApplicationWizardStep {
|
|||||||
?invalid=${this.errors.has("name")}
|
?invalid=${this.errors.has("name")}
|
||||||
.errorMessages=${errors.name ?? this.errorMessages("name")}
|
.errorMessages=${errors.name ?? this.errorMessages("name")}
|
||||||
help=${msg("Application's display Name.")}
|
help=${msg("Application's display Name.")}
|
||||||
id="ak-application-wizard-details-name"
|
|
||||||
></ak-text-input>
|
></ak-text-input>
|
||||||
<ak-slug-input
|
<ak-slug-input
|
||||||
name="slug"
|
name="slug"
|
||||||
value=${ifDefined(app.slug)}
|
value=${ifDefined(app.slug)}
|
||||||
label=${msg("Slug")}
|
label=${msg("Slug")}
|
||||||
source="#ak-application-wizard-details-name"
|
|
||||||
required
|
required
|
||||||
?invalid=${errors.slug ?? this.errors.has("slug")}
|
?invalid=${errors.slug ?? this.errors.has("slug")}
|
||||||
.errorMessages=${this.errorMessages("slug")}
|
.errorMessages=${this.errorMessages("slug")}
|
||||||
|
@ -115,7 +115,8 @@ export class ApplicationWizardBindingsStep extends ApplicationWizardStep {
|
|||||||
.columns=${COLUMNS}
|
.columns=${COLUMNS}
|
||||||
.content=${[]}
|
.content=${[]}
|
||||||
></ak-select-table>
|
></ak-select-table>
|
||||||
<ak-empty-state header=${msg("No bound policies.")} icon="pf-icon-module">
|
<ak-empty-state icon="pf-icon-module"
|
||||||
|
><span slot="header">${msg("No bound policies.")} </span>
|
||||||
<div slot="body">${msg("No policies are currently bound to this object.")}</div>
|
<div slot="body">${msg("No policies are currently bound to this object.")}</div>
|
||||||
<div slot="primary">
|
<div slot="primary">
|
||||||
<button
|
<button
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import "@goauthentik/components/ak-private-textarea-input.js";
|
import "@goauthentik/components/ak-secret-textarea-input.js";
|
||||||
import "@goauthentik/elements/CodeMirror";
|
import "@goauthentik/elements/CodeMirror";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
||||||
@ -46,7 +46,7 @@ export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-private-textarea-input
|
<ak-secret-textarea-input
|
||||||
label=${msg("Certificate")}
|
label=${msg("Certificate")}
|
||||||
name="certificateData"
|
name="certificateData"
|
||||||
input-hint="code"
|
input-hint="code"
|
||||||
@ -54,8 +54,8 @@ export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string
|
|||||||
required
|
required
|
||||||
?revealed=${this.instance === undefined}
|
?revealed=${this.instance === undefined}
|
||||||
help=${msg("PEM-encoded Certificate data.")}
|
help=${msg("PEM-encoded Certificate data.")}
|
||||||
></ak-private-textarea-input>
|
></ak-secret-textarea-input>
|
||||||
<ak-private-textarea-input
|
<ak-secret-textarea-input
|
||||||
label=${msg("Private Key")}
|
label=${msg("Private Key")}
|
||||||
name="keyData"
|
name="keyData"
|
||||||
input-hint="code"
|
input-hint="code"
|
||||||
@ -63,7 +63,7 @@ export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string
|
|||||||
help=${msg(
|
help=${msg(
|
||||||
"Optional Private Key. If this is set, you can use this keypair for encryption.",
|
"Optional Private Key. If this is set, you can use this keypair for encryption.",
|
||||||
)}
|
)}
|
||||||
></ak-private-textarea-input>`;
|
></ak-secret-textarea-input>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { EVENT_REFRESH_ENTERPRISE } from "@goauthentik/common/constants";
|
import { EVENT_REFRESH_ENTERPRISE } from "@goauthentik/common/constants";
|
||||||
import "@goauthentik/components/ak-private-textarea-input.js";
|
import "@goauthentik/components/ak-secret-textarea-input.js";
|
||||||
import "@goauthentik/elements/CodeMirror";
|
import "@goauthentik/elements/CodeMirror";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
||||||
@ -62,13 +62,13 @@ export class EnterpriseLicenseForm extends ModelForm<License, string> {
|
|||||||
value="${ifDefined(this.installID)}"
|
value="${ifDefined(this.installID)}"
|
||||||
/>
|
/>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-private-textarea-input
|
<ak-secret-textarea-input
|
||||||
name="key"
|
name="key"
|
||||||
?revealed=${this.instance === undefined}
|
?revealed=${this.instance === undefined}
|
||||||
label=${msg("License key")}
|
label=${msg("License key")}
|
||||||
input-hint="code"
|
input-hint="code"
|
||||||
>
|
>
|
||||||
</ak-private-textarea-input>`;
|
</ak-secret-textarea-input>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
import "#elements/Tabs";
|
||||||
|
import { WithLicenseSummary } from "#elements/mixins/license";
|
||||||
|
import { updateURLParams } from "#elements/router/RouteMatch";
|
||||||
|
import "@goauthentik/admin/events/EventMap";
|
||||||
import "@goauthentik/admin/events/EventVolumeChart";
|
import "@goauthentik/admin/events/EventVolumeChart";
|
||||||
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
|
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
@ -15,11 +19,14 @@ import { msg } from "@lit/localize";
|
|||||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||||
import { customElement, property } from "lit/decorators.js";
|
import { customElement, property } from "lit/decorators.js";
|
||||||
|
|
||||||
import { Event, EventsApi } from "@goauthentik/api";
|
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
|
||||||
|
|
||||||
|
import { Event, EventsApi, LicenseSummaryStatusEnum } from "@goauthentik/api";
|
||||||
|
|
||||||
@customElement("ak-event-list")
|
@customElement("ak-event-list")
|
||||||
export class EventListPage extends TablePage<Event> {
|
export class EventListPage extends WithLicenseSummary(TablePage<Event>) {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
|
supportsQL = true;
|
||||||
|
|
||||||
pageTitle(): string {
|
pageTitle(): string {
|
||||||
return msg("Event Log");
|
return msg("Event Log");
|
||||||
@ -38,11 +45,15 @@ export class EventListPage extends TablePage<Event> {
|
|||||||
order = "-created";
|
order = "-created";
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return super.styles.concat(css`
|
// @ts-expect-error
|
||||||
|
return super.styles.concat(
|
||||||
|
PFGrid,
|
||||||
|
css`
|
||||||
.pf-m-no-padding-bottom {
|
.pf-m-no-padding-bottom {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
`);
|
`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async apiEndpoint(): Promise<PaginatedResponse<Event>> {
|
async apiEndpoint(): Promise<PaginatedResponse<Event>> {
|
||||||
@ -61,16 +72,41 @@ export class EventListPage extends TablePage<Event> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderSectionBefore(): TemplateResult {
|
renderSectionBefore(): TemplateResult {
|
||||||
return html`
|
if (this.licenseSummary?.status !== LicenseSummaryStatusEnum.Unlicensed) {
|
||||||
<div class="pf-c-page__main-section pf-m-no-padding-bottom">
|
return html`<div
|
||||||
|
class="pf-l-grid pf-m-gutter pf-c-page__main-section pf-m-no-padding-bottom"
|
||||||
|
>
|
||||||
|
<ak-events-volume-chart
|
||||||
|
class="pf-l-grid__item pf-m-12-col pf-m-4-col-on-xl pf-m-4-col-on-2xl "
|
||||||
|
.query=${{
|
||||||
|
page: this.page,
|
||||||
|
search: this.search,
|
||||||
|
}}
|
||||||
|
with-map
|
||||||
|
></ak-events-volume-chart>
|
||||||
|
<ak-events-map
|
||||||
|
class="pf-l-grid__item pf-m-12-col pf-m-8-col-on-xl pf-m-8-col-on-2xl "
|
||||||
|
.events=${this.data}
|
||||||
|
@select-event=${(ev: CustomEvent<{ eventId: string }>) => {
|
||||||
|
this.search = `event_uuid = "${ev.detail.eventId}"`;
|
||||||
|
this.page = 1;
|
||||||
|
updateURLParams({
|
||||||
|
search: this.search,
|
||||||
|
tablePage: this.page,
|
||||||
|
});
|
||||||
|
this.fetch();
|
||||||
|
}}
|
||||||
|
></ak-events-map>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
return html`<div class="pf-c-page__main-section pf-m-no-padding-bottom">
|
||||||
<ak-events-volume-chart
|
<ak-events-volume-chart
|
||||||
.query=${{
|
.query=${{
|
||||||
page: this.page,
|
page: this.page,
|
||||||
search: this.search,
|
search: this.search,
|
||||||
}}
|
}}
|
||||||
></ak-events-volume-chart>
|
></ak-events-volume-chart>
|
||||||
</div>
|
</div>`;
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
row(item: EventWithContext): SlottedTemplateResult[] {
|
row(item: EventWithContext): SlottedTemplateResult[] {
|
||||||
|
161
web/src/admin/events/EventMap.ts
Normal file
161
web/src/admin/events/EventMap.ts
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
import { EventWithContext } from "#common/events";
|
||||||
|
import { globalAK } from "#common/global";
|
||||||
|
import { PaginatedResponse } from "#elements/table/Table";
|
||||||
|
import { AKElement } from "@goauthentik/elements/Base";
|
||||||
|
import "@openlayers-elements/core/ol-layer-vector";
|
||||||
|
import type OlLayerVector from "@openlayers-elements/core/ol-layer-vector";
|
||||||
|
import OlMap from "@openlayers-elements/core/ol-map";
|
||||||
|
import "@openlayers-elements/maps/ol-layer-openstreetmap";
|
||||||
|
import "@openlayers-elements/maps/ol-select";
|
||||||
|
import Feature from "ol/Feature";
|
||||||
|
import { Point } from "ol/geom";
|
||||||
|
import { fromLonLat } from "ol/proj";
|
||||||
|
import Icon from "ol/style/Icon";
|
||||||
|
import Style from "ol/style/Style";
|
||||||
|
|
||||||
|
import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit";
|
||||||
|
import { customElement, property, query } from "lit/decorators.js";
|
||||||
|
|
||||||
|
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
||||||
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
|
import OL from "ol/ol.css";
|
||||||
|
|
||||||
|
import { Event } from "@goauthentik/api";
|
||||||
|
|
||||||
|
@customElement("ak-map")
|
||||||
|
export class Map extends OlMap {
|
||||||
|
public render() {
|
||||||
|
return html`
|
||||||
|
<style>
|
||||||
|
${OL}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="map"></div>
|
||||||
|
<slot></slot>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @event {select-event} - Fired when an event is selected on the map. ID of the event is contained
|
||||||
|
* in the `Event.detail` field.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@customElement("ak-events-map")
|
||||||
|
export class EventMap extends AKElement {
|
||||||
|
@property({ attribute: false })
|
||||||
|
events?: PaginatedResponse<Event>;
|
||||||
|
|
||||||
|
@query("ol-layer-vector")
|
||||||
|
vectorLayer?: OlLayerVector;
|
||||||
|
|
||||||
|
@query("ak-map")
|
||||||
|
map?: Map;
|
||||||
|
|
||||||
|
@property({ type: Number })
|
||||||
|
zoomPaddingPx = 100;
|
||||||
|
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return [
|
||||||
|
PFBase,
|
||||||
|
PFCard,
|
||||||
|
css`
|
||||||
|
.pf-c-card,
|
||||||
|
ol-map {
|
||||||
|
height: 24rem;
|
||||||
|
}
|
||||||
|
:host([theme="dark"]) ol-map {
|
||||||
|
filter: invert(100%) hue-rotate(180deg);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
updated(_changedProperties: PropertyValues<this>): void {
|
||||||
|
if (!_changedProperties.has("events")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.vectorLayer?.source || !this.map?.map) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Remove all existing points
|
||||||
|
this.vectorLayer.source.clear();
|
||||||
|
// Re-add them
|
||||||
|
this.events?.results
|
||||||
|
.filter((event) => {
|
||||||
|
if (!Object.hasOwn(event.context, "geo")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const geo = (event as EventWithContext).context.geo;
|
||||||
|
if (!geo?.lat || !geo.long) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.forEach((event) => {
|
||||||
|
const geo = (event as EventWithContext).context.geo!;
|
||||||
|
const point = new Point(fromLonLat([geo.long!, geo.lat!]));
|
||||||
|
const feature = new Feature({
|
||||||
|
geometry: point,
|
||||||
|
});
|
||||||
|
feature.setStyle(
|
||||||
|
new Style({
|
||||||
|
image: new Icon({
|
||||||
|
anchor: [0.5, 1],
|
||||||
|
offset: [0, 0],
|
||||||
|
opacity: 1,
|
||||||
|
scale: 1,
|
||||||
|
rotateWithView: false,
|
||||||
|
rotation: 0,
|
||||||
|
src: `${globalAK().api.base}static/dist/assets/images/map_pin.svg`,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
feature.setId(event.pk);
|
||||||
|
this.vectorLayer?.source?.addFeature(feature);
|
||||||
|
});
|
||||||
|
// Zoom to show points better
|
||||||
|
this.map.map.getView().fit(this.vectorLayer.source.getExtent(), {
|
||||||
|
padding: [
|
||||||
|
this.zoomPaddingPx,
|
||||||
|
this.zoomPaddingPx,
|
||||||
|
this.zoomPaddingPx,
|
||||||
|
this.zoomPaddingPx,
|
||||||
|
],
|
||||||
|
duration: 500,
|
||||||
|
maxZoom: 4.5,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): TemplateResult {
|
||||||
|
return html`<div class="pf-c-card">
|
||||||
|
<ak-map>
|
||||||
|
<ol-select
|
||||||
|
@feature-selected=${(ev: CustomEvent<{ feature: Feature }>) => {
|
||||||
|
const eventId = ev.detail.feature.getId();
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent("select-event", {
|
||||||
|
composed: true,
|
||||||
|
bubbles: true,
|
||||||
|
detail: {
|
||||||
|
eventId: eventId,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
></ol-select>
|
||||||
|
<ol-layer-openstreetmap></ol-layer-openstreetmap>
|
||||||
|
<ol-layer-vector></ol-layer-vector>
|
||||||
|
</ak-map>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
}
|
@ -11,11 +11,14 @@ import { EventVolume, EventsApi, EventsEventsListRequest } from "@goauthentik/ap
|
|||||||
|
|
||||||
@customElement("ak-events-volume-chart")
|
@customElement("ak-events-volume-chart")
|
||||||
export class EventVolumeChart extends EventChart {
|
export class EventVolumeChart extends EventChart {
|
||||||
|
@property({ attribute: "with-map", type: Boolean })
|
||||||
|
withMap = false;
|
||||||
|
|
||||||
_query?: EventsEventsListRequest;
|
_query?: EventsEventsListRequest;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
set query(value: EventsEventsListRequest | undefined) {
|
set query(value: EventsEventsListRequest | undefined) {
|
||||||
if (JSON.stringify(this._query) === JSON.stringify(value)) return;
|
if (JSON.stringify(value) !== JSON.stringify(this._query)) return;
|
||||||
this._query = value;
|
this._query = value;
|
||||||
this.refreshHandler();
|
this.refreshHandler();
|
||||||
}
|
}
|
||||||
@ -24,6 +27,9 @@ export class EventVolumeChart extends EventChart {
|
|||||||
return super.styles.concat(
|
return super.styles.concat(
|
||||||
PFCard,
|
PFCard,
|
||||||
css`
|
css`
|
||||||
|
:host([with-map]) .pf-c-card {
|
||||||
|
height: 24rem;
|
||||||
|
}
|
||||||
.pf-c-card {
|
.pf-c-card {
|
||||||
height: 20rem;
|
height: 20rem;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
|
|||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal label=${msg("Group")} name="group">
|
<ak-form-element-horizontal label=${msg("Group")} name="destinationGroup">
|
||||||
<ak-search-select
|
<ak-search-select
|
||||||
.fetchObjects=${async (query?: string): Promise<Group[]> => {
|
.fetchObjects=${async (query?: string): Promise<Group[]> => {
|
||||||
const args: CoreGroupsListRequest = {
|
const args: CoreGroupsListRequest = {
|
||||||
@ -86,14 +86,44 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
|
|||||||
return group?.pk;
|
return group?.pk;
|
||||||
}}
|
}}
|
||||||
.selected=${(group: Group): boolean => {
|
.selected=${(group: Group): boolean => {
|
||||||
return group.pk === this.instance?.group;
|
return group.pk === this.instance?.destinationGroup;
|
||||||
}}
|
}}
|
||||||
blankable
|
blankable
|
||||||
>
|
>
|
||||||
</ak-search-select>
|
</ak-search-select>
|
||||||
|
<p class="pf-c-form__helper-text">
|
||||||
|
${msg("Select the group of users which the alerts are sent to. ")}
|
||||||
|
</p>
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${msg(
|
${msg(
|
||||||
"Select the group of users which the alerts are sent to. If no group is selected the rule is disabled.",
|
"If no group is selected and 'Send notification to event user' is disabled the rule is disabled. ",
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
|
<ak-form-element-horizontal name="destinationEventUser">
|
||||||
|
<label class="pf-c-switch">
|
||||||
|
<input
|
||||||
|
class="pf-c-switch__input"
|
||||||
|
type="checkbox"
|
||||||
|
?checked=${this.instance?.destinationEventUser ?? false}
|
||||||
|
/>
|
||||||
|
<span class="pf-c-switch__toggle">
|
||||||
|
<span class="pf-c-switch__toggle-icon">
|
||||||
|
<i class="fas fa-check" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span class="pf-c-switch__label"
|
||||||
|
>${msg("Send notification to event user")}</span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<p class="pf-c-form__helper-text">
|
||||||
|
${msg(
|
||||||
|
"When enabled, notification will be sent to the user that triggered the event in addition to any users in the group above. The event user will always be the first user, to send a notification only to the event user enabled 'Send once' in the notification transport.",
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p class="pf-c-form__helper-text">
|
||||||
|
${msg(
|
||||||
|
"If no group is selected and 'Send notification to event user' is disabled the rule is disabled. ",
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
|
@ -3,6 +3,7 @@ import "@goauthentik/admin/policies/BoundPoliciesList";
|
|||||||
import "@goauthentik/admin/rbac/ObjectPermissionModal";
|
import "@goauthentik/admin/rbac/ObjectPermissionModal";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { severityToLabel } from "@goauthentik/common/labels";
|
import { severityToLabel } from "@goauthentik/common/labels";
|
||||||
|
import "@goauthentik/components/ak-status-label";
|
||||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||||
import "@goauthentik/elements/forms/ModalForm";
|
import "@goauthentik/elements/forms/ModalForm";
|
||||||
@ -51,6 +52,7 @@ export class RuleListPage extends TablePage<NotificationRule> {
|
|||||||
|
|
||||||
columns(): TableColumn[] {
|
columns(): TableColumn[] {
|
||||||
return [
|
return [
|
||||||
|
new TableColumn(msg("Enabled")),
|
||||||
new TableColumn(msg("Name"), "name"),
|
new TableColumn(msg("Name"), "name"),
|
||||||
new TableColumn(msg("Severity"), "severity"),
|
new TableColumn(msg("Severity"), "severity"),
|
||||||
new TableColumn(msg("Sent to group"), "group"),
|
new TableColumn(msg("Sent to group"), "group"),
|
||||||
@ -81,12 +83,16 @@ export class RuleListPage extends TablePage<NotificationRule> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
row(item: NotificationRule): TemplateResult[] {
|
row(item: NotificationRule): TemplateResult[] {
|
||||||
|
const enabled = !!item.destinationGroupObj || item.destinationEventUser;
|
||||||
return [
|
return [
|
||||||
|
html`<ak-status-label type="warning" ?good=${enabled}></ak-status-label>`,
|
||||||
html`${item.name}`,
|
html`${item.name}`,
|
||||||
html`${severityToLabel(item.severity)}`,
|
html`${severityToLabel(item.severity)}`,
|
||||||
html`${item.groupObj
|
html`${item.destinationGroupObj
|
||||||
? html`<a href="#/identity/groups/${item.groupObj.pk}">${item.groupObj.name}</a>`
|
? html`<a href="#/identity/groups/${item.destinationGroupObj.pk}"
|
||||||
: msg("None (rule disabled)")}`,
|
>${item.destinationGroupObj.name}</a
|
||||||
|
>`
|
||||||
|
: msg("-")}`,
|
||||||
html`<ak-forms-modal>
|
html`<ak-forms-modal>
|
||||||
<span slot="submit"> ${msg("Update")} </span>
|
<span slot="submit"> ${msg("Update")} </span>
|
||||||
<span slot="header"> ${msg("Update Notification Rule")} </span>
|
<span slot="header"> ${msg("Update Notification Rule")} </span>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
|
import "@goauthentik/components/ak-hidden-text-input";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
||||||
import "@goauthentik/elements/forms/Radio";
|
import "@goauthentik/elements/forms/Radio";
|
||||||
@ -100,18 +101,15 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
|
|||||||
>
|
>
|
||||||
</ak-radio>
|
</ak-radio>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal
|
<ak-hidden-text-input
|
||||||
?hidden=${!this.showWebhook}
|
|
||||||
label=${msg("Webhook URL")}
|
|
||||||
name="webhookUrl"
|
name="webhookUrl"
|
||||||
|
label=${msg("Webhook URL")}
|
||||||
|
value="${this.instance?.webhookUrl || ""}"
|
||||||
|
input-hint="code"
|
||||||
|
?hidden=${!this.showWebhook}
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
<input
|
</ak-hidden-text-input>
|
||||||
type="text"
|
|
||||||
value="${ifDefined(this.instance?.webhookUrl)}"
|
|
||||||
class="pf-c-form-control"
|
|
||||||
/>
|
|
||||||
</ak-form-element-horizontal>
|
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
?hidden=${!this.showWebhook}
|
?hidden=${!this.showWebhook}
|
||||||
label=${msg("Webhook Body Mapping")}
|
label=${msg("Webhook Body Mapping")}
|
||||||
|
@ -135,7 +135,8 @@ export class BoundStagesList extends Table<FlowStageBinding> {
|
|||||||
|
|
||||||
renderEmpty(): TemplateResult {
|
renderEmpty(): TemplateResult {
|
||||||
return super.renderEmpty(
|
return super.renderEmpty(
|
||||||
html`<ak-empty-state header=${msg("No Stages bound")} icon="pf-icon-module">
|
html`<ak-empty-state icon="pf-icon-module">
|
||||||
|
<span slot="header">${msg("No Stages bound")}</span>
|
||||||
<div slot="body">${msg("No stages are currently bound to this flow.")}</div>
|
<div slot="body">${msg("No stages are currently bound to this flow.")}</div>
|
||||||
<div slot="primary">
|
<div slot="primary">
|
||||||
<ak-stage-wizard
|
<ak-stage-wizard
|
||||||
|
@ -3,6 +3,7 @@ import { DesignationToLabel, LayoutToLabel } from "@goauthentik/admin/flows/util
|
|||||||
import { policyEngineModes } from "@goauthentik/admin/policies/PolicyEngineModes";
|
import { policyEngineModes } from "@goauthentik/admin/policies/PolicyEngineModes";
|
||||||
import { AuthenticationEnum } from "@goauthentik/api/dist/models/AuthenticationEnum";
|
import { AuthenticationEnum } from "@goauthentik/api/dist/models/AuthenticationEnum";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
|
import "@goauthentik/components/ak-slug-input.js";
|
||||||
import "@goauthentik/elements/forms/FormGroup";
|
import "@goauthentik/elements/forms/FormGroup";
|
||||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||||
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
||||||
@ -91,17 +92,16 @@ export class FlowForm extends WithCapabilitiesConfig(ModelForm<Flow, string>) {
|
|||||||
/>
|
/>
|
||||||
<p class="pf-c-form__helper-text">${msg("Shown as the Title in Flow pages.")}</p>
|
<p class="pf-c-form__helper-text">${msg("Shown as the Title in Flow pages.")}</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal label=${msg("Slug")} required name="slug">
|
|
||||||
<input
|
<ak-slug-input
|
||||||
type="text"
|
name="slug"
|
||||||
value="${ifDefined(this.instance?.slug)}"
|
value=${ifDefined(this.instance?.slug)}
|
||||||
class="pf-c-form-control pf-m-monospace"
|
label=${msg("Slug")}
|
||||||
autocomplete="off"
|
|
||||||
spellcheck="false"
|
|
||||||
required
|
required
|
||||||
/>
|
help=${msg("Visible in the URL.")}
|
||||||
<p class="pf-c-form__helper-text">${msg("Visible in the URL.")}</p>
|
input-hint="code"
|
||||||
</ak-form-element-horizontal>
|
></ak-slug-input>
|
||||||
|
|
||||||
<ak-form-element-horizontal label=${msg("Designation")} required name="designation">
|
<ak-form-element-horizontal label=${msg("Designation")} required name="designation">
|
||||||
<select class="pf-c-form-control">
|
<select class="pf-c-form-control">
|
||||||
<option value="" ?selected=${this.instance?.designation === undefined}>
|
<option value="" ?selected=${this.instance?.designation === undefined}>
|
||||||
|
@ -198,7 +198,8 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
|
|||||||
|
|
||||||
renderEmpty(): TemplateResult {
|
renderEmpty(): TemplateResult {
|
||||||
return super.renderEmpty(
|
return super.renderEmpty(
|
||||||
html`<ak-empty-state header=${msg("No Policies bound.")} icon="pf-icon-module">
|
html`<ak-empty-state icon="pf-icon-module"
|
||||||
|
><span slot="header">${msg("No Policies bound.")}</span>
|
||||||
<div slot="body">${msg("No policies are currently bound to this object.")}</div>
|
<div slot="body">${msg("No policies are currently bound to this object.")}</div>
|
||||||
<div slot="primary">
|
<div slot="primary">
|
||||||
<ak-policy-wizard
|
<ak-policy-wizard
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user