Compare commits
24 Commits
version/20
...
version-20
Author | SHA1 | Date | |
---|---|---|---|
a8134e26c8 | |||
1c637bc0d1 | |||
8af668a9d2 | |||
96266e2e2b | |||
65373ab217 | |||
88590e1134 | |||
f6ff31e3de | |||
cbc14524b3 | |||
d807038d05 | |||
ba131a50ba | |||
0e37a66751 | |||
57c220dfc2 | |||
7339a22080 | |||
8c2d72affe | |||
9c31e08bd9 | |||
805b9afa80 | |||
bc809bae1e | |||
66773b69ab | |||
c149701501 | |||
b13b51b73a | |||
ee30cc1ede | |||
de095f4a10 | |||
abf3aa3a7f | |||
3ebae72a76 |
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 2025.6.2
|
||||
current_version = 2025.6.3
|
||||
tag = 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*))?
|
||||
|
2
.github/workflows/ci-main.yml
vendored
2
.github/workflows/ci-main.yml
vendored
@ -202,7 +202,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
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
|
||||
if: steps.cache-web.outputs.cache-hit != 'true'
|
||||
working-directory: web
|
||||
|
1
.github/workflows/ci-website.yml
vendored
1
.github/workflows/ci-website.yml
vendored
@ -49,6 +49,7 @@ jobs:
|
||||
matrix:
|
||||
job:
|
||||
- build
|
||||
- build:integrations
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@ -2,7 +2,7 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, "*", next, version*]
|
||||
branches: [main, next, version*]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
schedule:
|
||||
|
@ -96,7 +96,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
|
||||
# Stage 5: Download uv
|
||||
FROM ghcr.io/astral-sh/uv:0.7.8 AS uv
|
||||
# Stage 6: Base python image
|
||||
FROM ghcr.io/goauthentik/fips-python:3.13.3-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" \
|
||||
PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \
|
||||
|
4
Makefile
4
Makefile
@ -86,6 +86,10 @@ dev-create-db:
|
||||
|
||||
dev-reset: dev-drop-db dev-create-db migrate ## Drop and restore the Authentik PostgreSQL instance to a "fresh install" state.
|
||||
|
||||
update-test-mmdb: ## Update test GeoIP and ASN Databases
|
||||
curl -L https://raw.githubusercontent.com/maxmind/MaxMind-DB/refs/heads/main/test-data/GeoLite2-ASN-Test.mmdb -o ${PWD}/tests/GeoLite2-ASN-Test.mmdb
|
||||
curl -L https://raw.githubusercontent.com/maxmind/MaxMind-DB/refs/heads/main/test-data/GeoLite2-City-Test.mmdb -o ${PWD}/tests/GeoLite2-City-Test.mmdb
|
||||
|
||||
#########################
|
||||
## API Schema
|
||||
#########################
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
from os import environ
|
||||
|
||||
__version__ = "2025.6.2"
|
||||
__version__ = "2025.6.3"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
||||
|
||||
|
@ -15,13 +15,13 @@ class MMDBContextProcessor(EventContextProcessor):
|
||||
self.reader: Reader | None = None
|
||||
self._last_mtime: float = 0.0
|
||||
self.logger = get_logger()
|
||||
self.open()
|
||||
self.load()
|
||||
|
||||
def path(self) -> str | None:
|
||||
"""Get the path to the MMDB file to load"""
|
||||
raise NotImplementedError
|
||||
|
||||
def open(self):
|
||||
def load(self):
|
||||
"""Get GeoIP Reader, if configured, otherwise none"""
|
||||
path = self.path()
|
||||
if path == "" or not path:
|
||||
@ -44,7 +44,7 @@ class MMDBContextProcessor(EventContextProcessor):
|
||||
diff = self._last_mtime < mtime
|
||||
if diff > 0:
|
||||
self.logger.info("Found new MMDB Database, reopening", diff=diff, path=path)
|
||||
self.open()
|
||||
self.load()
|
||||
except OSError as exc:
|
||||
self.logger.warning("Failed to check MMDB age", exc=exc)
|
||||
|
||||
|
@ -66,7 +66,10 @@ class RACClientConsumer(AsyncWebsocketConsumer):
|
||||
def init_outpost_connection(self):
|
||||
"""Initialize guac connection settings"""
|
||||
self.token = (
|
||||
ConnectionToken.filter_not_expired(token=self.scope["url_route"]["kwargs"]["token"])
|
||||
ConnectionToken.filter_not_expired(
|
||||
token=self.scope["url_route"]["kwargs"]["token"],
|
||||
session__session__session_key=self.scope["session"].session_key,
|
||||
)
|
||||
.select_related("endpoint", "provider", "session", "session__user")
|
||||
.first()
|
||||
)
|
||||
|
@ -87,3 +87,22 @@ class TestRACViews(APITestCase):
|
||||
)
|
||||
body = loads(flow_response.content)
|
||||
self.assertEqual(body["component"], "ak-stage-access-denied")
|
||||
|
||||
def test_different_session(self):
|
||||
"""Test request"""
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"authentik_providers_rac:start",
|
||||
kwargs={"app": self.app.slug, "endpoint": str(self.endpoint.pk)},
|
||||
)
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
flow_response = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
|
||||
)
|
||||
body = loads(flow_response.content)
|
||||
next_url = body["to"]
|
||||
self.client.logout()
|
||||
final_response = self.client.get(next_url)
|
||||
self.assertEqual(final_response.url, reverse("authentik_core:if-user"))
|
||||
|
@ -68,7 +68,10 @@ class RACInterface(InterfaceView):
|
||||
|
||||
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
|
||||
# Early sanity check to ensure token still exists
|
||||
token = ConnectionToken.filter_not_expired(token=self.kwargs["token"]).first()
|
||||
token = ConnectionToken.filter_not_expired(
|
||||
token=self.kwargs["token"],
|
||||
session__session__session_key=request.session.session_key,
|
||||
).first()
|
||||
if not token:
|
||||
return redirect("authentik_core:if-user")
|
||||
self.token = token
|
||||
|
@ -11,6 +11,8 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from django.test.runner import DiscoverRunner
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.events.context_processors.asn import ASN_CONTEXT_PROCESSOR
|
||||
from authentik.events.context_processors.geoip import GEOIP_CONTEXT_PROCESSOR
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.sentry import sentry_init
|
||||
from authentik.root.signals import post_startup, pre_startup, startup
|
||||
@ -67,6 +69,10 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
|
||||
CONFIG.set("error_reporting.sample_rate", 0)
|
||||
CONFIG.set("error_reporting.environment", "testing")
|
||||
CONFIG.set("error_reporting.send_pii", True)
|
||||
|
||||
ASN_CONTEXT_PROCESSOR.load()
|
||||
GEOIP_CONTEXT_PROCESSOR.load()
|
||||
|
||||
sentry_init()
|
||||
|
||||
pre_startup.send(sender=self, mode="test")
|
||||
|
@ -71,37 +71,31 @@ def ldap_sync_single(source_pk: str):
|
||||
return
|
||||
# Delete all sync tasks from the cache
|
||||
DBSystemTask.objects.filter(name="ldap_sync", uid__startswith=source.slug).delete()
|
||||
task = chain(
|
||||
# User and group sync can happen at once, they have no dependencies on each other
|
||||
group(
|
||||
ldap_sync_paginator(source, UserLDAPSynchronizer)
|
||||
+ ldap_sync_paginator(source, GroupLDAPSynchronizer),
|
||||
),
|
||||
# Membership sync needs to run afterwards
|
||||
group(
|
||||
ldap_sync_paginator(source, MembershipLDAPSynchronizer),
|
||||
),
|
||||
# Finally, deletions. What we'd really like to do here is something like
|
||||
# ```
|
||||
# user_identifiers = <ldap query>
|
||||
# User.objects.exclude(
|
||||
# usersourceconnection__identifier__in=user_uniqueness_identifiers,
|
||||
# ).delete()
|
||||
# ```
|
||||
# This runs into performance issues in large installations. So instead we spread the
|
||||
# work out into three steps:
|
||||
# 1. Get every object from the LDAP source.
|
||||
# 2. Mark every object as "safe" in the database. This is quick, but any error could
|
||||
# mean deleting users which should not be deleted, so we do it immediately, in
|
||||
# large chunks, and only queue the deletion step afterwards.
|
||||
# 3. Delete every unmarked item. This is slow, so we spread it over many tasks in
|
||||
# small chunks.
|
||||
group(
|
||||
ldap_sync_paginator(source, UserLDAPForwardDeletion)
|
||||
+ ldap_sync_paginator(source, GroupLDAPForwardDeletion),
|
||||
),
|
||||
|
||||
# The order of these operations needs to be preserved as each depends on the previous one(s)
|
||||
# 1. User and group sync can happen simultaneously
|
||||
# 2. Membership sync needs to run afterwards
|
||||
# 3. Finally, user and group deletions can happen simultaneously
|
||||
user_group_sync = ldap_sync_paginator(source, UserLDAPSynchronizer) + ldap_sync_paginator(
|
||||
source, GroupLDAPSynchronizer
|
||||
)
|
||||
task()
|
||||
membership_sync = ldap_sync_paginator(source, MembershipLDAPSynchronizer)
|
||||
user_group_deletion = ldap_sync_paginator(
|
||||
source, UserLDAPForwardDeletion
|
||||
) + ldap_sync_paginator(source, GroupLDAPForwardDeletion)
|
||||
|
||||
# Celery is buggy with empty groups, so we are careful only to add non-empty groups.
|
||||
# See https://github.com/celery/celery/issues/9772
|
||||
task_groups = []
|
||||
if user_group_sync:
|
||||
task_groups.append(group(user_group_sync))
|
||||
if membership_sync:
|
||||
task_groups.append(group(membership_sync))
|
||||
if user_group_deletion:
|
||||
task_groups.append(group(user_group_deletion))
|
||||
|
||||
all_tasks = chain(task_groups)
|
||||
all_tasks()
|
||||
|
||||
|
||||
def ldap_sync_paginator(source: LDAPSource, sync: type[BaseLDAPSynchronizer]) -> list:
|
||||
|
@ -101,9 +101,9 @@ class BoundSessionMiddleware(SessionMiddleware):
|
||||
SESSION_KEY_BINDING_GEO, GeoIPBinding.NO_BINDING
|
||||
)
|
||||
if configured_binding_net != NetworkBinding.NO_BINDING:
|
||||
self.recheck_session_net(configured_binding_net, last_ip, new_ip)
|
||||
BoundSessionMiddleware.recheck_session_net(configured_binding_net, last_ip, new_ip)
|
||||
if configured_binding_geo != GeoIPBinding.NO_BINDING:
|
||||
self.recheck_session_geo(configured_binding_geo, last_ip, new_ip)
|
||||
BoundSessionMiddleware.recheck_session_geo(configured_binding_geo, last_ip, new_ip)
|
||||
# If we got to this point without any error being raised, we need to
|
||||
# update the last saved IP to the current one
|
||||
if SESSION_KEY_BINDING_NET in request.session or SESSION_KEY_BINDING_GEO in request.session:
|
||||
@ -111,7 +111,8 @@ class BoundSessionMiddleware(SessionMiddleware):
|
||||
# (== basically requires the user to be logged in)
|
||||
request.session[request.session.model.Keys.LAST_IP] = new_ip
|
||||
|
||||
def recheck_session_net(self, binding: NetworkBinding, last_ip: str, new_ip: str):
|
||||
@staticmethod
|
||||
def recheck_session_net(binding: NetworkBinding, last_ip: str, new_ip: str):
|
||||
"""Check network/ASN binding"""
|
||||
last_asn = ASN_CONTEXT_PROCESSOR.asn(last_ip)
|
||||
new_asn = ASN_CONTEXT_PROCESSOR.asn(new_ip)
|
||||
@ -158,7 +159,8 @@ class BoundSessionMiddleware(SessionMiddleware):
|
||||
new_ip,
|
||||
)
|
||||
|
||||
def recheck_session_geo(self, binding: GeoIPBinding, last_ip: str, new_ip: str):
|
||||
@staticmethod
|
||||
def recheck_session_geo(binding: GeoIPBinding, last_ip: str, new_ip: str):
|
||||
"""Check GeoIP binding"""
|
||||
last_geo = GEOIP_CONTEXT_PROCESSOR.city(last_ip)
|
||||
new_geo = GEOIP_CONTEXT_PROCESSOR.city(new_ip)
|
||||
@ -179,8 +181,8 @@ class BoundSessionMiddleware(SessionMiddleware):
|
||||
if last_geo.continent != new_geo.continent:
|
||||
raise SessionBindingBroken(
|
||||
"geoip.continent",
|
||||
last_geo.continent,
|
||||
new_geo.continent,
|
||||
last_geo.continent.to_dict(),
|
||||
new_geo.continent.to_dict(),
|
||||
last_ip,
|
||||
new_ip,
|
||||
)
|
||||
@ -192,8 +194,8 @@ class BoundSessionMiddleware(SessionMiddleware):
|
||||
if last_geo.country != new_geo.country:
|
||||
raise SessionBindingBroken(
|
||||
"geoip.country",
|
||||
last_geo.country,
|
||||
new_geo.country,
|
||||
last_geo.country.to_dict(),
|
||||
new_geo.country.to_dict(),
|
||||
last_ip,
|
||||
new_ip,
|
||||
)
|
||||
@ -202,8 +204,8 @@ class BoundSessionMiddleware(SessionMiddleware):
|
||||
if last_geo.city != new_geo.city:
|
||||
raise SessionBindingBroken(
|
||||
"geoip.city",
|
||||
last_geo.city,
|
||||
new_geo.city,
|
||||
last_geo.city.to_dict(),
|
||||
new_geo.city.to_dict(),
|
||||
last_ip,
|
||||
new_ip,
|
||||
)
|
||||
|
@ -3,6 +3,7 @@
|
||||
from time import sleep
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.http import HttpRequest
|
||||
from django.urls import reverse
|
||||
from django.utils.timezone import now
|
||||
|
||||
@ -17,7 +18,12 @@ from authentik.flows.views.executor import SESSION_KEY_PLAN
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.root.middleware import ClientIPMiddleware
|
||||
from authentik.stages.user_login.models import UserLoginStage
|
||||
from authentik.stages.user_login.middleware import (
|
||||
BoundSessionMiddleware,
|
||||
SessionBindingBroken,
|
||||
logout_extra,
|
||||
)
|
||||
from authentik.stages.user_login.models import GeoIPBinding, NetworkBinding, UserLoginStage
|
||||
|
||||
|
||||
class TestUserLoginStage(FlowTestCase):
|
||||
@ -192,3 +198,52 @@ class TestUserLoginStage(FlowTestCase):
|
||||
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
|
||||
response = self.client.get(reverse("authentik_api:application-list"))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_binding_net_break_log(self):
|
||||
"""Test logout_extra with exception"""
|
||||
# IPs from https://github.com/maxmind/MaxMind-DB/blob/main/source-data/GeoLite2-ASN-Test.json
|
||||
for args, expect in [
|
||||
[[NetworkBinding.BIND_ASN, "8.8.8.8", "8.8.8.8"], ["network.missing"]],
|
||||
[[NetworkBinding.BIND_ASN, "1.0.0.1", "1.128.0.1"], ["network.asn"]],
|
||||
[
|
||||
[NetworkBinding.BIND_ASN_NETWORK, "12.81.96.1", "12.81.128.1"],
|
||||
["network.asn_network"],
|
||||
],
|
||||
[[NetworkBinding.BIND_ASN_NETWORK_IP, "1.0.0.1", "1.0.0.2"], ["network.ip"]],
|
||||
]:
|
||||
with self.subTest(args[0]):
|
||||
with self.assertRaises(SessionBindingBroken) as cm:
|
||||
BoundSessionMiddleware.recheck_session_net(*args)
|
||||
self.assertEqual(cm.exception.reason, expect[0])
|
||||
# Ensure the request can be logged without throwing errors
|
||||
self.client.force_login(self.user)
|
||||
request = HttpRequest()
|
||||
request.session = self.client.session
|
||||
request.user = self.user
|
||||
logout_extra(request, cm.exception)
|
||||
|
||||
def test_binding_geo_break_log(self):
|
||||
"""Test logout_extra with exception"""
|
||||
# IPs from https://github.com/maxmind/MaxMind-DB/blob/main/source-data/GeoLite2-City-Test.json
|
||||
for args, expect in [
|
||||
[[GeoIPBinding.BIND_CONTINENT, "8.8.8.8", "8.8.8.8"], ["geoip.missing"]],
|
||||
[[GeoIPBinding.BIND_CONTINENT, "2.125.160.216", "67.43.156.1"], ["geoip.continent"]],
|
||||
[
|
||||
[GeoIPBinding.BIND_CONTINENT_COUNTRY, "81.2.69.142", "89.160.20.112"],
|
||||
["geoip.country"],
|
||||
],
|
||||
[
|
||||
[GeoIPBinding.BIND_CONTINENT_COUNTRY_CITY, "2.125.160.216", "81.2.69.142"],
|
||||
["geoip.city"],
|
||||
],
|
||||
]:
|
||||
with self.subTest(args[0]):
|
||||
with self.assertRaises(SessionBindingBroken) as cm:
|
||||
BoundSessionMiddleware.recheck_session_geo(*args)
|
||||
self.assertEqual(cm.exception.reason, expect[0])
|
||||
# Ensure the request can be logged without throwing errors
|
||||
self.client.force_login(self.user)
|
||||
request = HttpRequest()
|
||||
request.session = self.client.session
|
||||
request.user = self.user
|
||||
logout_extra(request, cm.exception)
|
||||
|
@ -2,7 +2,7 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"$id": "https://goauthentik.io/blueprints/schema.json",
|
||||
"type": "object",
|
||||
"title": "authentik 2025.6.2 Blueprint schema",
|
||||
"title": "authentik 2025.6.3 Blueprint schema",
|
||||
"required": [
|
||||
"version",
|
||||
"entries"
|
||||
|
@ -31,7 +31,7 @@ services:
|
||||
volumes:
|
||||
- redis:/data
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.2}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.3}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
@ -55,7 +55,7 @@ services:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.2}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.3}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
|
@ -33,4 +33,4 @@ func UserAgent() string {
|
||||
return fmt.Sprintf("authentik@%s", FullVersion())
|
||||
}
|
||||
|
||||
const VERSION = "2025.6.2"
|
||||
const VERSION = "2025.6.3"
|
||||
|
@ -26,7 +26,7 @@ Parameters:
|
||||
Description: authentik Docker image
|
||||
AuthentikVersion:
|
||||
Type: String
|
||||
Default: 2025.6.2
|
||||
Default: 2025.6.3
|
||||
Description: authentik Docker image tag
|
||||
AuthentikServerCPU:
|
||||
Type: Number
|
||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2025.6.2",
|
||||
"version": "2025.6.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2025.6.2",
|
||||
"version": "2025.6.3",
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"prettier": "^3.3.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2025.6.2",
|
||||
"version": "2025.6.3",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "authentik"
|
||||
version = "2025.6.2"
|
||||
version = "2025.6.3"
|
||||
description = ""
|
||||
authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }]
|
||||
requires-python = "==3.13.*"
|
||||
|
@ -1,7 +1,7 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: authentik
|
||||
version: 2025.6.2
|
||||
version: 2025.6.3
|
||||
description: Making authentication simple.
|
||||
contact:
|
||||
email: hello@goauthentik.io
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 21 KiB |
55
uv.lock
generated
55
uv.lock
generated
@ -164,7 +164,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "authentik"
|
||||
version = "2025.6.2"
|
||||
version = "2025.6.3"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "argon2-cffi" },
|
||||
@ -2383,16 +2383,16 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "protobuf"
|
||||
version = "6.30.2"
|
||||
version = "6.31.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c8/8c/cf2ac658216eebe49eaedf1e06bc06cbf6a143469236294a1171a51357c3/protobuf-6.30.2.tar.gz", hash = "sha256:35c859ae076d8c56054c25b59e5e59638d86545ed6e2b6efac6be0b6ea3ba048", size = 429315, upload-time = "2025-03-26T19:12:57.394Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/52/f3/b9655a711b32c19720253f6f06326faf90580834e2e83f840472d752bc8b/protobuf-6.31.1.tar.gz", hash = "sha256:d8cac4c982f0b957a4dc73a80e2ea24fab08e679c0de9deb835f4a12d69aca9a", size = 441797, upload-time = "2025-05-28T19:25:54.947Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/be/85/cd53abe6a6cbf2e0029243d6ae5fb4335da2996f6c177bb2ce685068e43d/protobuf-6.30.2-cp310-abi3-win32.whl", hash = "sha256:b12ef7df7b9329886e66404bef5e9ce6a26b54069d7f7436a0853ccdeb91c103", size = 419148, upload-time = "2025-03-26T19:12:41.359Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/e9/7b9f1b259d509aef2b833c29a1f3c39185e2bf21c9c1be1cd11c22cb2149/protobuf-6.30.2-cp310-abi3-win_amd64.whl", hash = "sha256:7653c99774f73fe6b9301b87da52af0e69783a2e371e8b599b3e9cb4da4b12b9", size = 431003, upload-time = "2025-03-26T19:12:44.156Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/66/7f3b121f59097c93267e7f497f10e52ced7161b38295137a12a266b6c149/protobuf-6.30.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:0eb523c550a66a09a0c20f86dd554afbf4d32b02af34ae53d93268c1f73bc65b", size = 417579, upload-time = "2025-03-26T19:12:45.447Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/89/bbb1bff09600e662ad5b384420ad92de61cab2ed0f12ace1fd081fd4c295/protobuf-6.30.2-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:50f32cc9fd9cb09c783ebc275611b4f19dfdfb68d1ee55d2f0c7fa040df96815", size = 317319, upload-time = "2025-03-26T19:12:46.999Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/50/1925de813499546bc8ab3ae857e3ec84efe7d2f19b34529d0c7c3d02d11d/protobuf-6.30.2-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:4f6c687ae8efae6cf6093389a596548214467778146b7245e886f35e1485315d", size = 316212, upload-time = "2025-03-26T19:12:48.458Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/a1/93c2acf4ade3c5b557d02d500b06798f4ed2c176fa03e3c34973ca92df7f/protobuf-6.30.2-py3-none-any.whl", hash = "sha256:ae86b030e69a98e08c77beab574cbcb9fff6d031d57209f574a5aea1445f4b51", size = 167062, upload-time = "2025-03-26T19:12:55.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/6f/6ab8e4bf962fd5570d3deaa2d5c38f0a363f57b4501047b5ebeb83ab1125/protobuf-6.31.1-cp310-abi3-win32.whl", hash = "sha256:7fa17d5a29c2e04b7d90e5e32388b8bfd0e7107cd8e616feef7ed3fa6bdab5c9", size = 423603, upload-time = "2025-05-28T19:25:41.198Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/3a/b15c4347dd4bf3a1b0ee882f384623e2063bb5cf9fa9d57990a4f7df2fb6/protobuf-6.31.1-cp310-abi3-win_amd64.whl", hash = "sha256:426f59d2964864a1a366254fa703b8632dcec0790d8862d30034d8245e1cd447", size = 435283, upload-time = "2025-05-28T19:25:44.275Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/c9/b9689a2a250264a84e66c46d8862ba788ee7a641cdca39bccf64f59284b7/protobuf-6.31.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:6f1227473dc43d44ed644425268eb7c2e488ae245d51c6866d19fe158e207402", size = 425604, upload-time = "2025-05-28T19:25:45.702Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/a1/7a5a94032c83375e4fe7e7f56e3976ea6ac90c5e85fac8576409e25c39c3/protobuf-6.31.1-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:a40fc12b84c154884d7d4c4ebd675d5b3b5283e155f324049ae396b95ddebc39", size = 322115, upload-time = "2025-05-28T19:25:47.128Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/b1/b59d405d64d31999244643d88c45c8241c58f17cc887e73bcb90602327f8/protobuf-6.31.1-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:4ee898bf66f7a8b0bd21bce523814e6fbd8c6add948045ce958b73af7e8878c6", size = 321070, upload-time = "2025-05-28T19:25:50.036Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/af/ab3c51ab7507a7325e98ffe691d9495ee3d3aa5f589afad65ec920d39821/protobuf-6.31.1-py3-none-any.whl", hash = "sha256:720a6c7e6b77288b85063569baae8536671b39f15cc22037ec7045658d80489e", size = 168724, upload-time = "2025-05-28T19:25:53.926Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2776,7 +2776,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
version = "2.32.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
@ -2784,9 +2784,9 @@ dependencies = [
|
||||
{ name = "idna" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3112,20 +3112,21 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "tornado"
|
||||
version = "6.4.2"
|
||||
version = "6.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/59/45/a0daf161f7d6f36c3ea5fc0c2de619746cc3dd4c76402e9db545bd920f63/tornado-6.4.2.tar.gz", hash = "sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b", size = 501135, upload-time = "2024-11-22T03:06:38.036Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/51/89/c72771c81d25d53fe33e3dca61c233b665b2780f21820ba6fd2c6793c12b/tornado-6.5.1.tar.gz", hash = "sha256:84ceece391e8eb9b2b95578db65e920d2a61070260594819589609ba9bc6308c", size = 509934, upload-time = "2025-05-22T18:15:38.788Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/26/7e/71f604d8cea1b58f82ba3590290b66da1e72d840aeb37e0d5f7291bd30db/tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1", size = 436299, upload-time = "2024-11-22T03:06:20.162Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/44/87543a3b99016d0bf54fdaab30d24bf0af2e848f1d13d34a3a5380aabe16/tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803", size = 434253, upload-time = "2024-11-22T03:06:22.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/fb/fdf679b4ce51bcb7210801ef4f11fdac96e9885daa402861751353beea6e/tornado-6.4.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec", size = 437602, upload-time = "2024-11-22T03:06:24.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/3b/e31aeffffc22b475a64dbeb273026a21b5b566f74dee48742817626c47dc/tornado-6.4.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946", size = 436972, upload-time = "2024-11-22T03:06:25.559Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/55/b78a464de78051a30599ceb6983b01d8f732e6f69bf37b4ed07f642ac0fc/tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf", size = 437173, upload-time = "2024-11-22T03:06:27.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/5e/be4fb0d1684eb822c9a62fb18a3e44a06188f78aa466b2ad991d2ee31104/tornado-6.4.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634", size = 437892, upload-time = "2024-11-22T03:06:28.933Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/33/4f91fdd94ea36e1d796147003b490fe60a0215ac5737b6f9c65e160d4fe0/tornado-6.4.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73", size = 437334, upload-time = "2024-11-22T03:06:30.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/ae/c1b22d4524b0e10da2f29a176fb2890386f7bd1f63aacf186444873a88a0/tornado-6.4.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c", size = 437261, upload-time = "2024-11-22T03:06:32.458Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/25/36dbd49ab6d179bcfc4c6c093a51795a4f3bed380543a8242ac3517a1751/tornado-6.4.2-cp38-abi3-win32.whl", hash = "sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482", size = 438463, upload-time = "2024-11-22T03:06:34.71Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/cc/58b1adeb1bb46228442081e746fcdbc4540905c87e8add7c277540934edb/tornado-6.4.2-cp38-abi3-win_amd64.whl", hash = "sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38", size = 438907, upload-time = "2024-11-22T03:06:36.71Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/89/f4532dee6843c9e0ebc4e28d4be04c67f54f60813e4bf73d595fe7567452/tornado-6.5.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d50065ba7fd11d3bd41bcad0825227cc9a95154bad83239357094c36708001f7", size = 441948, upload-time = "2025-05-22T18:15:20.862Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/9a/557406b62cffa395d18772e0cdcf03bed2fff03b374677348eef9f6a3792/tornado-6.5.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9e9ca370f717997cb85606d074b0e5b247282cf5e2e1611568b8821afe0342d6", size = 440112, upload-time = "2025-05-22T18:15:22.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/82/7721b7319013a3cf881f4dffa4f60ceff07b31b394e459984e7a36dc99ec/tornado-6.5.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b77e9dfa7ed69754a54c89d82ef746398be82f749df69c4d3abe75c4d1ff4888", size = 443672, upload-time = "2025-05-22T18:15:24.027Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/42/d11c4376e7d101171b94e03cef0cbce43e823ed6567ceda571f54cf6e3ce/tornado-6.5.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253b76040ee3bab8bcf7ba9feb136436a3787208717a1fb9f2c16b744fba7331", size = 443019, upload-time = "2025-05-22T18:15:25.735Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/f7/0c48ba992d875521ac761e6e04b0a1750f8150ae42ea26df1852d6a98942/tornado-6.5.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:308473f4cc5a76227157cdf904de33ac268af770b2c5f05ca6c1161d82fdd95e", size = 443252, upload-time = "2025-05-22T18:15:27.499Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/46/d8d7413d11987e316df4ad42e16023cd62666a3c0dfa1518ffa30b8df06c/tornado-6.5.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:caec6314ce8a81cf69bd89909f4b633b9f523834dc1a352021775d45e51d9401", size = 443930, upload-time = "2025-05-22T18:15:29.299Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/b2/f8049221c96a06df89bed68260e8ca94beca5ea532ffc63b1175ad31f9cc/tornado-6.5.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:13ce6e3396c24e2808774741331638ee6c2f50b114b97a55c5b442df65fd9692", size = 443351, upload-time = "2025-05-22T18:15:31.038Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/ff/6a0079e65b326cc222a54720a748e04a4db246870c4da54ece4577bfa702/tornado-6.5.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5cae6145f4cdf5ab24744526cc0f55a17d76f02c98f4cff9daa08ae9a217448a", size = 443328, upload-time = "2025-05-22T18:15:32.426Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/18/e3f902a1d21f14035b5bc6246a8c0f51e0eef562ace3a2cea403c1fb7021/tornado-6.5.1-cp39-abi3-win32.whl", hash = "sha256:e0a36e1bc684dca10b1aa75a31df8bdfed656831489bc1e6a6ebed05dc1ec365", size = 444396, upload-time = "2025-05-22T18:15:34.205Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/09/6526e32bf1049ee7de3bebba81572673b19a2a8541f795d887e92af1a8bc/tornado-6.5.1-cp39-abi3-win_amd64.whl", hash = "sha256:908e7d64567cecd4c2b458075589a775063453aeb1d2a1853eedb806922f568b", size = 444840, upload-time = "2025-05-22T18:15:36.1Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/a7/535c44c7bea4578e48281d83c615219f3ab19e6abc67625ef637c73987be/tornado-6.5.1-cp39-abi3-win_arm64.whl", hash = "sha256:02420a0eb7bf617257b9935e2b754d1b63897525d8a289c9d65690d580b4dcf7", size = 443596, upload-time = "2025-05-22T18:15:37.433Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3287,11 +3288,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
|
@ -123,6 +123,9 @@ export class AKElement extends LitElement {
|
||||
applyUITheme(nextStyleRoot, UiThemeEnum.Dark, this.#customCSSStyleSheet);
|
||||
|
||||
this.activeTheme = UiThemeEnum.Dark;
|
||||
} else if (this.preferredColorScheme === "light") {
|
||||
applyUITheme(nextStyleRoot, UiThemeEnum.Light, this.#customCSSStyleSheet);
|
||||
this.activeTheme = UiThemeEnum.Light;
|
||||
} else if (this.preferredColorScheme === "auto") {
|
||||
createUIThemeEffect(
|
||||
(nextUITheme) => {
|
||||
|
@ -32,8 +32,8 @@ import {
|
||||
} from "./types.js";
|
||||
|
||||
function localeComparator(a: DualSelectPair, b: DualSelectPair) {
|
||||
const aSortBy = a[2] || a[0];
|
||||
const bSortBy = b[2] || b[0];
|
||||
const aSortBy = String(a[2] || a[0]);
|
||||
const bSortBy = String(b[2] || b[0]);
|
||||
|
||||
return aSortBy.localeCompare(bSortBy);
|
||||
}
|
||||
|
@ -465,8 +465,10 @@ export abstract class Table<T> extends AKElement implements TableLike {
|
||||
renderSearch(): TemplateResult {
|
||||
const runSearch = (value: string) => {
|
||||
this.search = value;
|
||||
this.page = 1;
|
||||
updateURLParams({
|
||||
search: value,
|
||||
tablePage: 1,
|
||||
});
|
||||
this.fetch();
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ import { updateURLParams } from "#elements/router/RouteMatch";
|
||||
import { Table } from "#elements/table/Table";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult } from "lit";
|
||||
import { CSSResult, nothing } from "lit";
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
@ -44,7 +44,7 @@ export abstract class TablePage<T> extends Table<T> {
|
||||
? inner
|
||||
: html`<ak-empty-state icon=${this.pageIcon()} header="${msg("No objects found.")}">
|
||||
<div slot="body">
|
||||
${this.searchEnabled() ? this.renderEmptyClearSearch() : html``}
|
||||
${this.searchEnabled() ? this.renderEmptyClearSearch() : nothing}
|
||||
</div>
|
||||
<div slot="primary">${this.renderObjectCreate()}</div>
|
||||
</ak-empty-state>`}
|
||||
@ -60,8 +60,10 @@ export abstract class TablePage<T> extends Table<T> {
|
||||
this.search = "";
|
||||
this.requestUpdate();
|
||||
this.fetch();
|
||||
this.page = 1;
|
||||
updateURLParams({
|
||||
search: "",
|
||||
tablePage: 1,
|
||||
});
|
||||
}}
|
||||
class="pf-c-button pf-m-link"
|
||||
|
@ -93,7 +93,7 @@ export class UserSettingsFlowExecutor
|
||||
}
|
||||
|
||||
updated(): void {
|
||||
if (!this.flowSlug && this.brand) {
|
||||
if (!this.flowSlug && this.brand?.flowUserSettings) {
|
||||
this.flowSlug = this.brand.flowUserSettings;
|
||||
this.nextChallenge();
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ For more information about using a Google Workspace provider, see the [Overview]
|
||||
To create a Google Workspace provider in authentik, you must have already [configured Google Workspace](./setup-gws.md) to integrate with authentik.
|
||||
|
||||
:::info
|
||||
When adding the Google Workspace provider in authentik, you must define the **Backchannel provider** using the name of the Google Workspace provider that you created in authentik. If you have also configured Google Workspace to log in using authentik following [these](../../../../integrations/services/google/), then this configuration can be done on the same app.
|
||||
When adding the Google Workspace provider in authentik, you must define the **Backchannel provider** using the name of the Google Workspace provider that you created in authentik. If you have also configured Google Workspace to log in using authentik following [these](/integrations/services/google/), then this configuration can be done on the same app.
|
||||
:::
|
||||
|
||||
### Create the Google Workspace provider in authentik
|
||||
|
@ -0,0 +1,94 @@
|
||||
---
|
||||
title: RAC Credentials Prompt
|
||||
---
|
||||
|
||||
## About the RAC credentials prompt
|
||||
|
||||
You can configure the RAC provider to prompt users for their credentials when connecting to RAC endpoints. This is particulalry useful for establishing RDP connections to modern Windows systems that often require credentials to establish a connection.
|
||||
|
||||
After implementing this configuration, when connecting to an RAC endpoint users are prompted to enter their credentials which are then passed to the RAC endpoint. This means that static credentials do not need to be set in the RAC provider, property mapping, or endpoint.
|
||||
|
||||
This configurations requires:
|
||||
|
||||
1. Creating an authorization flow.
|
||||
2. Creating two prompts.
|
||||
3. Creating and binding a prompt stage.
|
||||
4. Updating the RAC provider.
|
||||
|
||||
## Create a new authorization flow
|
||||
|
||||
1. Log in to authentik as an administrator, and open the authentik Admin interface.
|
||||
2. Navigate to **Flows and Stages** > **Flows**, click **Create**, and enter the following required settings:
|
||||
- **Name**: Enter a descriptive name for the flow.
|
||||
- **Title**: Enter a title for the flow. This will be displayed to users when they're prompted for their credentials.
|
||||
- **Slug**: Enter a slug for the flow. This will be displayed in the flow URL.
|
||||
- **Designation**: `Authorization`
|
||||
- **Authentication**: `Require authentication`
|
||||
3. Click **Create**.
|
||||
|
||||
## Create prompts
|
||||
|
||||
1. Log in to authentik as an administrator, and open the authentik Admin interface.
|
||||
2. Navigate to **Flows and Stages** > **Prompts**, click **Create**, and enter the following required settings:
|
||||
- **Name**: Enter a descriptive name for the prompt (e.g. `username`).
|
||||
- **Field Key**: `connection_settings.username`
|
||||
- **Label**: Enter a label for the field which will be displayed above it.
|
||||
- **Type**: `Text`
|
||||
- **Required**: Toggled on.
|
||||
- **Order**: `0`
|
||||
3. Click **Create** to save the prompt.
|
||||
4. On the **Prompts** page, click **Create** again, and enter the following required settings:
|
||||
- **Name**: Enter a descriptive name for the prompt (e.g. `password`).
|
||||
- **Field Key**: `connection_settings.password`
|
||||
- **Label**: Enter a label for the field which will be displayed above it.
|
||||
- **Type**: `Password`
|
||||
- **Required**: Toggled.
|
||||
- **Order**: `1`
|
||||
5. Click **Create** to save the prompt.
|
||||
|
||||
:::note
|
||||
You can optionally add other prompt fields such as `domain` (e.g. `connection_settings.domain`), which can be useful for Windows based RDP. There is also the option of adding a `Text (read-only)` type prompt field that includes explanatory text for the user (e.g. `please enter your RDP credentials`).
|
||||
:::
|
||||
|
||||
## Create and bind a prompt stage
|
||||
|
||||
1. Log in to authentik as an administrator, and open the authentik Admin interface.
|
||||
2. Navigate to **Flows and Stages** > **Flows**.
|
||||
3. Click the name of the newly created authorization flow.
|
||||
4. Click on **Stage bindings**, click **Create and bind stage**, and enter the following required settings:
|
||||
- **Select Type**: Select `Prompt stage` as the prompt type.
|
||||
- **Create Prompt Stage**:
|
||||
- **Name**: Enter a name for the prompt stage.
|
||||
- Under **Fields**:
|
||||
- Click the **x** icon to remove all selected fields.
|
||||
- Add the two newly created prompt fields (e.g.`username` and `password`) to selected fields.
|
||||
- Under **Validation Policies**:
|
||||
- Click the **x** icon to remove all selected validation policies.
|
||||
- **Create binding**:
|
||||
- Click **Finish**.
|
||||
|
||||
## Update the RAC provider
|
||||
|
||||
1. Log in to authentik as an administrator, and open the authentik Admin interface.
|
||||
2. Navigate to **Applications** > **Providers**.
|
||||
3. Click the **Edit** icon of the RAC provider that you wish to add a credentials prompt to.
|
||||
4. Change **Authorization flow** to the newly created authorization flow.
|
||||
5. Click **Update** to save the change.
|
||||
|
||||
## Update the RAC endpoint _(sometimes required)_
|
||||
|
||||
Depending on the configuration of the RDP server that's being connected to, it is sometimes necessary to set the security type that's used for the connection. For many modern windows RDP servers, this often needs to be set to `tls`.
|
||||
|
||||
1. Log in to authentik as an administrator, and open the authentik Admin interface.
|
||||
2. Navigate to **Applications** > **Providers** and click the name of the RAC provider that you're using.
|
||||
3. Under **Endpoints**, click the **Edit** icon of the endpoint that you're using.
|
||||
4. Under **Advanced Settings** in the **Settings** box, enter `security: tls`
|
||||
5. Click **Update** to save the change.
|
||||
|
||||
:::note
|
||||
Other options for the connection security type are: `any`, `nla`, `nla-ext`, `vmconnect`, and `rdp`. For more information see the [Guacamole RDP Authentication and Security Documentation](https://guacamole.apache.org/doc/gug/configuring-guacamole.html#authentication-and-security).
|
||||
:::
|
||||
|
||||
## Configuration verification
|
||||
|
||||
Log in to authentik with a user account that has the required privileges to access the RAC application. Open the User interface, and on the **My applications** page click the RAC application. You should then be redirected to the prompt stage and prompted for a username and password. Enter the credentials for the RAC endpoint and if the credentials are valid the RDP/SSH/VNC connection should be established.
|
@ -94,6 +94,8 @@ Avoid phrasing that blames the user. Be subjective and polite when providing ins
|
||||
|
||||
For Ken's sake, and many others, try to not use too many commas (avoid commaitis). Use a comma when needed to separate clauses, or for "slowing the pace" or clarity. Please **do** use the Oxford comma.
|
||||
|
||||
In [lists](#lists), add a period at the end of a bulleted item if it is a complete sentence. Try not to mix incomplete and complete sentences in the same list.
|
||||
|
||||
### Capitalization
|
||||
|
||||
#### Titles and headers
|
||||
@ -159,7 +161,7 @@ When writing out steps in a procedural topic, avoid starting with "Once...". Ins
|
||||
|
||||
- Use _italic_ for:
|
||||
|
||||
- Emphasis, but sparingly, to avoid overuse. For example, you can use italics for important terms or concepts on first mention in a section.
|
||||
- Emphasis, but sparingly, to avoid overuse. For example, you can use italics for important terms or concepts on first mention in a section. Do not use italics to indicate a variable or placeholder; instead use angle brackets as described under [Variables](#variables).
|
||||
|
||||
- Use `code formatting` for:
|
||||
|
||||
@ -167,14 +169,28 @@ When writing out steps in a procedural topic, avoid starting with "Once...". Ins
|
||||
- File paths, file names, and directory names (e.g., `/usr/local/bin/`).
|
||||
- Inline code snippets (e.g., `.env`).
|
||||
|
||||
- When handling URLs:
|
||||
### Lists
|
||||
|
||||
- For URLs entered as values or defined in fields, enclose any variables inside angle brackets (`< >`) to clearly indicate that these are placeholders that require user input.
|
||||
Add a period at the end of a bulleted item if it is a complete sentence. Try not to mix incomplete and complete sentences in the same list.
|
||||
|
||||
For example: `https://authentik.company/application/o/<slug>/.well-known/openid-configuration`
|
||||
If there is a [colon](#following-a-colon) used in a bulleted list item, follow the capitalization rules.
|
||||
|
||||
### URLs
|
||||
|
||||
- When mentioning URLs in text or within procedural instructions, omit code formatting. For instance: "In your browser, go to https://example.com."
|
||||
|
||||
- For URLs entered as values or defined in fields, enclose any variables inside angle brackets (`< >`) and use underscores between words. See more about variables below (#variables).
|
||||
|
||||
### Variables
|
||||
|
||||
To clearly indicate terms or values that are placeholders and require user input, enclose any variables inside angle brackets (`< >`) and use underscores between words to clearly indicate that these are placeholders that require user input.
|
||||
|
||||
Examples:
|
||||
|
||||
`https://authentik.company/application/o/<slug>/.well-known/openid-configuration`
|
||||
|
||||
"Add the configuration setting: `<first_name>`."
|
||||
|
||||
### Titles and headers
|
||||
|
||||
- Titles and headers (H1, H2, H3) should follow **sentence case capitalization**, meaning only the first word is capitalized, except for proper nouns or product names.
|
||||
@ -189,7 +205,7 @@ When writing out steps in a procedural topic, avoid starting with "Once...". Ins
|
||||
|
||||
### Examples
|
||||
|
||||
When you want to show an example (say, a code snippet), start on a new line, use bold text for the word "Example", and a semi-colon, like this:
|
||||
When you want to show an example (say, a code snippet), start on a new line, use bold text for the word "Example", and a colon, like this:
|
||||
|
||||
**Example**:
|
||||
|
||||
|
@ -81,20 +81,20 @@ Previously, sessions were stored by default in the cache. Now, they are stored i
|
||||
|
||||
An integration is a how authentik connects to third-party applications, directories, and other identity providers. The following integration guides were recently added.
|
||||
|
||||
- [Apple Business Manager](../../../integrations/services/apple/)
|
||||
- [FleetDM](../../../integrations/services/fleet/)
|
||||
- [Gravity](../../../integrations/services/gravity/)
|
||||
- [Homarr](../../../integrations/services/homarr/)
|
||||
- [KnocKnoc](../../../integrations/services/knocknoc)
|
||||
- [Mautic](../../../integrations/services/mautic/)
|
||||
- [Mailcow](../../../integrations/services/mailcow/)
|
||||
- [Mealie](../../../integrations/services/mealie/)
|
||||
- [OpenProject](../../../integrations/services/openproject)
|
||||
- [Sidero Omni](../../../integrations/services/omni)
|
||||
- [Tandoor](../../../integrations/services/tandoor/)
|
||||
- [Wazuh](../../../integrations/services/wazuh)
|
||||
- [XCreds](../../../integrations/services/xcreds)
|
||||
- [Zipline](../../../integrations/services/zipline/)
|
||||
- [Apple Business Manager](/integrations/services/apple/)
|
||||
- [FleetDM](/integrations/services/fleet/)
|
||||
- [Gravity](/integrations/services/gravity/)
|
||||
- [Homarr](/integrations/services/homarr/)
|
||||
- [KnocKnoc](/integrations/services/knocknoc)
|
||||
- [Mautic](/integrations/services/mautic/)
|
||||
- [Mailcow](/integrations/services/mailcow/)
|
||||
- [Mealie](/integrations/services/mealie/)
|
||||
- [OpenProject](/integrations/services/openproject)
|
||||
- [Sidero Omni](/integrations/services/omni)
|
||||
- [Tandoor](/integrations/services/tandoor/)
|
||||
- [Wazuh](/integrations/services/wazuh)
|
||||
- [XCreds](/integrations/services/xcreds)
|
||||
- [Zipline](/integrations/services/zipline/)
|
||||
|
||||
## Upgrading
|
||||
|
||||
@ -285,6 +285,16 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2025.4
|
||||
- root: temporarily deactivate database pool option (cherry-pick #14443) (#14479)
|
||||
- web/flows/sfe: fix global background image not being loaded (cherry-pick #14442) (#14450)
|
||||
|
||||
## Fixed in 2025.4.2
|
||||
|
||||
- core: Migrate permissions before deleting OldAuthenticatedSession (cherry-pick #14788) (#14791)
|
||||
- lifecycle: fix arguments not being passed to worker command (cherry-pick #14574) (#14620)
|
||||
- sources/scim: fix all users being added to group when no members are given (cherry-pick #14645) (#14666)
|
||||
|
||||
## Fixed in 2025.4.3
|
||||
|
||||
- security: fix CVE-2025-52553 (#15289)
|
||||
|
||||
## API Changes
|
||||
|
||||
#### What's New
|
||||
|
@ -37,15 +37,15 @@ slug: "/releases/2025.6"
|
||||
|
||||
An integration is how authentik connects to third-party applications, directories, and other identity providers. The following integration guides were recently added to our documentation:
|
||||
|
||||
- [Atlassian Cloud (Jira, Confluence, etc)](../../../integrations/services/atlassian/)
|
||||
- [Coder](../../../integrations/services/coder/)
|
||||
- [FileRise](../../../integrations/services/filerise/)
|
||||
- [Komodo](../../../integrations/services/komodo/)
|
||||
- [Pangolin](../../../integrations/services/pangolin/)
|
||||
- [Push Security](../../../integrations/services/push-security/)
|
||||
- [Stripe](../../../integrations/services/stripe/)
|
||||
- [Tailscale](../../../integrations/services/tailscale/)
|
||||
- [YouTrack](../../../integrations/services/youtrack/)
|
||||
- [Atlassian Cloud (Jira, Confluence, etc)](/integrations/services/atlassian/)
|
||||
- [Coder](/integrations/services/coder/)
|
||||
- [FileRise](/integrations/services/filerise/)
|
||||
- [Komodo](/integrations/services/komodo/)
|
||||
- [Pangolin](/integrations/services/pangolin/)
|
||||
- [Push Security](/integrations/services/push-security/)
|
||||
- [Stripe](/integrations/services/stripe/)
|
||||
- [Tailscale](/integrations/services/tailscale/)
|
||||
- [YouTrack](/integrations/services/youtrack/)
|
||||
|
||||
## Upgrading
|
||||
|
||||
@ -153,6 +153,22 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2025.6
|
||||
- web/elements: fix dual select without sortBy (cherry-pick #14977) (#14979)
|
||||
- web/elements: fix typo in localeComparator (cherry-pick #15054) (#15055)
|
||||
|
||||
## Fixed in 2025.6.3
|
||||
|
||||
- ci: fix CodeQL failing on cherry-pick PRs (cherry-pick #15205) (#15206)
|
||||
- ci: fix post-release e2e builds failing (cherry-pick #15082) (#15092)
|
||||
- core: bump goauthentik/fips-python from 3.13.3-slim-bookworm-fips to 3.13.5-slim-bookworm-fips in 2025.6 (#15274)
|
||||
- core: bump protobuf from 6.30.2 to v6.31.1 (cherry-pick #14894) (#15173)
|
||||
- core: bump requests from 2.32.3 to v2.32.4 (cherry-pick #15129) (#15135)
|
||||
- core: bump tornado from 6.4.2 to v6.5.1 (cherry-pick #15100) (#15116)
|
||||
- core: bump urllib3 from 2.4.0 to v2.5.0 (cherry-pick #15131) (#15174)
|
||||
- security: fix CVE-2025-52553 (cherry-pick #15289) (#15290)
|
||||
- sources/ldap: fix sync on empty groups (cherry-pick #15158) (#15171)
|
||||
- stages/user_login: fix session binding logging (#15175)
|
||||
- web/elements: Add light mode custom css handling (cherry-pick #14944) (#15096)
|
||||
- web/elements: typing error when variables are not converted to string (cherry-pick #15169) (#15222)
|
||||
- web/user: fix infinite loop when no user settings flow is set (cherry-pick #15188) (#15192)
|
||||
|
||||
## API Changes
|
||||
|
||||
#### What's New
|
||||
|
27
website/docs/security/cves/CVE-2025-52553.md
Normal file
27
website/docs/security/cves/CVE-2025-52553.md
Normal file
@ -0,0 +1,27 @@
|
||||
# CVE-2025-52553
|
||||
|
||||
_Reported by [SPIEGEL-Verlag](https://gruppe.spiegel.de)_
|
||||
|
||||
## Insufficient Session verification for Remote Access Control endpoint access
|
||||
|
||||
### Summary
|
||||
|
||||
After authorizing access to a RAC endpoint, authentik creates a token which is used for a single connection and is sent to the client in the URL. This token is intended to only be valid for the session of the user who authorized the connection, however this check is currently missing.
|
||||
|
||||
### Patches
|
||||
|
||||
authentik 2025.4.3 and 2025.6.3 fix this issue.
|
||||
|
||||
### Impact
|
||||
|
||||
When for example using RAC during a screenshare, a malicious user could access the same session by copying the URL from the shown browser.
|
||||
|
||||
### Workarounds
|
||||
|
||||
As a workaround it is recommended to decrease the duration a token is valid for (in the RAC Provider settings, set **Connection expiry** to `minutes=5` for example). We also recommend enabling the option **Delete authorization on disconnect**.
|
||||
|
||||
### For more information
|
||||
|
||||
If you have any questions or comments about this advisory:
|
||||
|
||||
- Email us at [security@goauthentik.io](mailto:security@goauthentik.io).
|
@ -2,18 +2,22 @@
|
||||
title: Events
|
||||
---
|
||||
|
||||
Events are authentik's built-in logging system. Whenever any of the following actions occur, an event is created:
|
||||
Events are authentik's built-in logging system. Every event is logged, whether it is initiated by a user or by authentik.
|
||||
|
||||
Events can be used to define [notification rules](notifications.md), with specified [transport options](transports.md) of local (in the authentik UI), email or webhook.
|
||||
|
||||
Certain information is stripped from events, to ensure no passwords or other credentials are saved in the log.
|
||||
|
||||
## Event retention
|
||||
|
||||
The event retention is configured in the system settings interface, with the default being set to 365 days.
|
||||
The event retention is configured in the **System > Settings** area of the Admin interface, with the default being set to 365 days.
|
||||
|
||||
If you want to forward these events to another application, forward the log output of all authentik containers. Every event creation is logged with the log level "info". For this configuration, it is also recommended to set the internal retention pretty low (for example, `days=1`).
|
||||
|
||||
## Event actions
|
||||
|
||||
Whenever any of the following actions occur, an event is created.
|
||||
|
||||
### `login`
|
||||
|
||||
A user logs in (including the source, if available)
|
||||
|
@ -8,9 +8,7 @@ To prevent infinite loops (events created by policies which are attached to a No
|
||||
|
||||
## Filtering Events
|
||||
|
||||
Starting with authentik 0.15, you can create notification rules, which can alert you based on the creation of certain events.
|
||||
|
||||
Filtering is done by using the Policy Engine. You can do simple filtering using the "Event Matcher Policy" type.
|
||||
An authentik administrator can create notification rules based on the creation of specified events. Filtering is done by using the Policy Engine. You can do simple filtering using the "Event Matcher Policy" type.
|
||||
|
||||

|
||||
|
||||
|
@ -27,3 +27,29 @@ uv run ak create_recovery_key 10 akadmin
|
||||
```
|
||||
|
||||
This will output a link, that can be used to instantly gain access to authentik as the user specified above. The link is valid for amount of years specified above, in this case, 10 years.
|
||||
|
||||
## Can't access initial setup flow during installation steps
|
||||
|
||||
If you're unable to access the initial setup flow (`/if/flow/initial-setup/`) immediately after installing authentik, first try restarting the containers because this often resolves temporary issues.
|
||||
|
||||
However, if the issue persists after restarting, you can directly set the admin password using the following commands:
|
||||
|
||||
Docker Compose deployments:
|
||||
|
||||
```bash
|
||||
docker compose exec server ak changepassword akadmin
|
||||
```
|
||||
|
||||
Kubernetes deployments:
|
||||
|
||||
```bash
|
||||
kubectl exec -it deployment/authentik-server -c server -- ak changepassword akadmin
|
||||
```
|
||||
|
||||
After following the prompts to set a new password, you can then login via: `https://authentik.company/if/flow/default-authentication-flow/?next=%2F`
|
||||
|
||||
After logging in, you can set the email address and other settings for the account by navigating to **Directory** > **Users** and editing the user account.
|
||||
|
||||
:::note
|
||||
This method bypasses the initial setup flow and should only be used as a last resort. The initial setup flow is the recommended method to configure the administrator user.
|
||||
:::
|
||||
|
@ -10,7 +10,7 @@ This page provides an overview of how to configure each protocol as a federated
|
||||
:::info{title="authentik as a third-party IdP"}
|
||||
authentik can also be configuration to authenticate users into Google services.
|
||||
|
||||
For more information, see the [Google Workspace Integration](../../../../../integrations/services/google/) guide.
|
||||
For more information, see the [Google Workspace Integration](/integrations/services/google/) guide.
|
||||
|
||||
## Google Cloud (OAuth)
|
||||
|
||||
|
@ -11,6 +11,7 @@ import remarkDirective from "remark-directive";
|
||||
import remarkGithub, { defaultBuildUrl } from "remark-github";
|
||||
|
||||
import remarkEnterpriseDirective from "./remark/enterprise-directive.mjs";
|
||||
import remarkLinkRewrite from "./remark/link-rewrite-directive.mjs";
|
||||
import remarkPreviewDirective from "./remark/preview-directive.mjs";
|
||||
import remarkSupportDirective from "./remark/support-directive.mjs";
|
||||
import remarkVersionDirective from "./remark/version-directive.mjs";
|
||||
@ -43,9 +44,10 @@ const config = createDocusaurusConfig({
|
||||
target: "_self",
|
||||
},
|
||||
{
|
||||
to: "integrations/",
|
||||
to: "https://integrations.goauthentik.io",
|
||||
label: "Integrations",
|
||||
position: "left",
|
||||
target: "_self",
|
||||
},
|
||||
{
|
||||
to: "docs/",
|
||||
@ -86,6 +88,7 @@ const config = createDocusaurusConfig({
|
||||
appId: "36ROD0O0FV",
|
||||
apiKey: "727db511300ca9aec5425645bbbddfb5",
|
||||
indexName: "goauthentik",
|
||||
externalUrlRegex: /(:\/\/goauthentik\.io|integrations\.goauthentik\.io)/.toString(),
|
||||
},
|
||||
},
|
||||
presets: [
|
||||
@ -94,6 +97,7 @@ const config = createDocusaurusConfig({
|
||||
/** @type {Preset.Options} */ ({
|
||||
docs: {
|
||||
id: "docs",
|
||||
routeBasePath: "docs",
|
||||
sidebarPath: "./sidebars/docs.mjs",
|
||||
showLastUpdateTime: false,
|
||||
editUrl: "https://github.com/goauthentik/authentik/edit/main/website/",
|
||||
@ -101,6 +105,9 @@ const config = createDocusaurusConfig({
|
||||
|
||||
beforeDefaultRemarkPlugins: [
|
||||
remarkDirective,
|
||||
remarkLinkRewrite(
|
||||
new Map([["/integrations", "https://integrations.goauthentik.io"]]),
|
||||
),
|
||||
remarkVersionDirective,
|
||||
remarkEnterpriseDirective,
|
||||
remarkPreviewDirective,
|
||||
@ -124,6 +131,10 @@ const config = createDocusaurusConfig({
|
||||
],
|
||||
],
|
||||
},
|
||||
gtag: {
|
||||
trackingID: ["G-9MVR9WZFZH"],
|
||||
anonymizeIP: true,
|
||||
},
|
||||
theme: {
|
||||
customCss: require.resolve("@goauthentik/docusaurus-config/css/index.css"),
|
||||
},
|
||||
@ -131,16 +142,6 @@ const config = createDocusaurusConfig({
|
||||
],
|
||||
],
|
||||
plugins: [
|
||||
[
|
||||
"@docusaurus/plugin-content-docs",
|
||||
{
|
||||
id: "docsIntegrations",
|
||||
path: "integrations",
|
||||
routeBasePath: "integrations",
|
||||
sidebarPath: "./sidebars/integrations.mjs",
|
||||
editUrl: "https://github.com/goauthentik/authentik/edit/main/website/",
|
||||
},
|
||||
],
|
||||
[
|
||||
"docusaurus-plugin-openapi-docs",
|
||||
{
|
||||
|
12
website/integrations/docusaurus.config.cjs
Normal file
12
website/integrations/docusaurus.config.cjs
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @file CommonJS Docusaurus config adapter.
|
||||
*
|
||||
* This exists to allow an ESM Docusaurus configuration to be imported in a CommonJS.
|
||||
*
|
||||
* @import Config from "./docusaurus.config.esm.mjs"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see {@linkcode Config} for the Docusaurus configuration type.
|
||||
*/
|
||||
module.exports = import("./docusaurus.config.esm.mjs").then(($) => $.default);
|
143
website/integrations/docusaurus.config.esm.mjs
Normal file
143
website/integrations/docusaurus.config.esm.mjs
Normal file
@ -0,0 +1,143 @@
|
||||
/**
|
||||
* @file Docusaurus config.
|
||||
*
|
||||
* @import * as Preset from "@docusaurus/preset-classic";
|
||||
* @import { BuildUrlValues } from "remark-github";
|
||||
*/
|
||||
import { createDocusaurusConfig } from "@goauthentik/docusaurus-config";
|
||||
import { createRequire } from "node:module";
|
||||
import remarkDirective from "remark-directive";
|
||||
import remarkGithub, { defaultBuildUrl } from "remark-github";
|
||||
|
||||
import remarkEnterpriseDirective from "../remark/enterprise-directive.mjs";
|
||||
import remarkLinkRewrite from "../remark/link-rewrite-directive.mjs";
|
||||
import remarkPreviewDirective from "../remark/preview-directive.mjs";
|
||||
import remarkSupportDirective from "../remark/support-directive.mjs";
|
||||
import remarkVersionDirective from "../remark/version-directive.mjs";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
/**
|
||||
* Documentation site configuration for Docusaurus.
|
||||
*/
|
||||
const config = createDocusaurusConfig({
|
||||
url: "https://integrations.goauthentik.io",
|
||||
future: {
|
||||
experimental_faster: true,
|
||||
},
|
||||
themes: ["@docusaurus/theme-mermaid"],
|
||||
themeConfig: {
|
||||
image: "img/social.png",
|
||||
navbar: {
|
||||
logo: {
|
||||
alt: "authentik logo",
|
||||
src: "img/icon_left_brand.svg",
|
||||
href: "https://goauthentik.io/",
|
||||
target: "_self",
|
||||
},
|
||||
items: [
|
||||
{
|
||||
to: "https://goauthentik.io/features",
|
||||
label: "Features",
|
||||
position: "left",
|
||||
target: "_self",
|
||||
},
|
||||
{
|
||||
to: "integrations/",
|
||||
label: "Integrations",
|
||||
position: "left",
|
||||
},
|
||||
{
|
||||
to: "https://docs.goauthentik.io",
|
||||
label: "Documentation",
|
||||
position: "left",
|
||||
target: "_self",
|
||||
},
|
||||
{
|
||||
to: "https://goauthentik.io/pricing/",
|
||||
label: "Pricing",
|
||||
position: "left",
|
||||
target: "_self",
|
||||
},
|
||||
{
|
||||
to: "https://goauthentik.io/blog",
|
||||
label: "Blog",
|
||||
position: "left",
|
||||
target: "_self",
|
||||
},
|
||||
{
|
||||
"href": "https://github.com/goauthentik/authentik",
|
||||
"data-icon": "github",
|
||||
"aria-label": "GitHub",
|
||||
"position": "right",
|
||||
},
|
||||
{
|
||||
"href": "https://goauthentik.io/discord",
|
||||
"data-icon": "discord",
|
||||
"aria-label": "Discord",
|
||||
"position": "right",
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
links: [],
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Authentik Security Inc. Built with Docusaurus.`,
|
||||
},
|
||||
algolia: {
|
||||
appId: "36ROD0O0FV",
|
||||
apiKey: "727db511300ca9aec5425645bbbddfb5",
|
||||
indexName: "goauthentik",
|
||||
externalUrlRegex: /(:\/\/goauthentik\.io|docs\.goauthentik\.io)/.toString(),
|
||||
},
|
||||
},
|
||||
presets: [
|
||||
[
|
||||
"@docusaurus/preset-classic",
|
||||
/** @type {Preset.Options} */ ({
|
||||
docs: {
|
||||
id: "docsIntegrations",
|
||||
path: "integrations",
|
||||
routeBasePath: "integrations",
|
||||
sidebarPath: "./sidebars/integrations.mjs",
|
||||
editUrl: "https://github.com/goauthentik/authentik/edit/main/website/",
|
||||
showLastUpdateTime: false,
|
||||
|
||||
beforeDefaultRemarkPlugins: [
|
||||
remarkDirective,
|
||||
remarkLinkRewrite(new Map([["/docs", "https://docs.goauthentik.io"]])),
|
||||
remarkVersionDirective,
|
||||
remarkEnterpriseDirective,
|
||||
remarkPreviewDirective,
|
||||
remarkSupportDirective,
|
||||
],
|
||||
remarkPlugins: [
|
||||
[
|
||||
remarkGithub,
|
||||
{
|
||||
repository: "goauthentik/authentik",
|
||||
/**
|
||||
* @param {BuildUrlValues} values
|
||||
*/
|
||||
buildUrl: (values) => {
|
||||
// Only replace issues and PR links
|
||||
return values.type === "issue" || values.type === "mention"
|
||||
? defaultBuildUrl(values)
|
||||
: false;
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
gtag: {
|
||||
trackingID: ["G-9MVR9WZFZH"],
|
||||
anonymizeIP: true,
|
||||
},
|
||||
theme: {
|
||||
customCss: require.resolve("@goauthentik/docusaurus-config/css/index.css"),
|
||||
},
|
||||
}),
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
export default config;
|
@ -12,12 +12,12 @@ Integrations are categorized into two categories: **Applications** and **Sources
|
||||
|
||||
Applications include vendor tools such as Google Workspace, GitHub, Slack, or AWS. These applications can be integrated with authentik to provide single sign-on capabilities to securely authenticate users.
|
||||
|
||||
If you want to integrate an application that isn't listed, authentik can be configured to work with most applications that support authentication protocols such as [SAML](../docs/add-secure-apps/providers/saml), [OAuth and OpenID Connect](../docs/add-secure-apps/providers/oauth2).
|
||||
If you want to integrate an application that isn't listed, authentik can be configured to work with most applications that support authentication protocols such as [SAML](/docs/add-secure-apps/providers/saml), [OAuth and OpenID Connect](/docs/add-secure-apps/providers/oauth2).
|
||||
|
||||
To learn more, refer to the [Applications](../integrations/services) page.
|
||||
|
||||
### Federated and social sources
|
||||
|
||||
Sources are a way for authentik to use external user credentials for authentication. Supported integrations with external sources via authentik include federated directories like Active Directory and social logins such as Facebook, Twitter, etc. These integrations support all major protocols, including [LDAP](../docs/users-sources/sources/protocols/ldap), [SCIM](../docs/users-sources/sources/protocols/scim), [SAML](../docs/users-sources/sources/protocols/saml), and [OAuth and OpenID Connect](../docs/users-sources/sources/protocols/oauth)
|
||||
Sources are a way for authentik to use external user credentials for authentication. Supported integrations with external sources via authentik include federated directories like Active Directory and social logins such as Facebook, Twitter, etc. These integrations support all major protocols, including [LDAP](/docs/users-sources/sources/protocols/ldap), [SCIM](/docs/users-sources/sources/protocols/scim), [SAML](/docs/users-sources/sources/protocols/saml), and [OAuth and OpenID Connect](/docs/users-sources/sources/protocols/oauth)
|
||||
|
||||
To learn more, refer to the [Sources](../docs/users-sources/sources) page.
|
||||
To learn more, refer to the [Sources](/docs/users-sources/sources) page.
|
||||
|
@ -209,7 +209,7 @@ You can always find your provider's generated values by navigating to **Provider
|
||||
|
||||
### 4. Create Shared Signals Framework provider
|
||||
|
||||
While the OIDC provider handles the authentication flow, you'll need to create a [Shared Signals Framework provider](../../../docs/add-secure-apps/providers/ssf/) to handle the backchannel communication between authentik and Apple Business Manager.
|
||||
While the OIDC provider handles the authentication flow, you'll need to create a [Shared Signals Framework provider](/docs/add-secure-apps/providers/ssf/) to handle the backchannel communication between authentik and Apple Business Manager.
|
||||
|
||||
1. From the authentik Admin interface, navigate to **Applications -> Providers** and click **Create**.
|
||||
2. Select **Shared Signals Framework Provider** and use the following values.
|
||||
|
@ -16,7 +16,7 @@ The following placeholders are used in this guide:
|
||||
|
||||
- `mautic.company` is the FQDN of the Mautic installation.
|
||||
- `authentik.company` is the FQDN of the authentik installation.
|
||||
- `mautic-provider` is the [SAML provider](../../../docs/add-secure-apps/providers/saml) whose settings will be imported into Mautic.
|
||||
- `mautic-provider` is the [SAML provider](/docs/add-secure-apps/providers/saml) whose settings will be imported into Mautic.
|
||||
|
||||
:::info
|
||||
This documentation lists only the settings that you need to change from their default values.
|
||||
@ -39,7 +39,7 @@ To support the integration of Mautic with authentik, you need to create property
|
||||
|
||||
### Create property mappings
|
||||
|
||||
Because Mautic requires a first name and last name attribute, create two [SAML provider property mappings](../../../docs/users-sources/sources/property-mappings):
|
||||
Because Mautic requires a first name and last name attribute, create two [SAML provider property mappings](/docs/users-sources/sources/property-mappings):
|
||||
|
||||
1. Log in to authentik as an administrator and open the authentik Admin interface.
|
||||
2. Navigate to **Customization** > **Property Mappings** and click **Create**:
|
||||
|
@ -103,16 +103,16 @@ To connect to an existing Nextcloud user, set the `nextcloud_user_id` attribute
|
||||
|
||||
### Provider and Application
|
||||
|
||||
1. **Create a provider:**
|
||||
1. **Create a provider:**
|
||||
In the authentik Admin Interface, navigate to **Applications > Providers**. Create an **OAuth2/OpenID Provider** with the following settings:
|
||||
|
||||
- **Name:** Nextcloud
|
||||
- **Client type:** Confidential
|
||||
- **Redirect URIs/Origins (RegEx):**
|
||||
- **Redirect URIs/Origins (RegEx):**
|
||||
`https://nextcloud.company/apps/user_oidc/code`
|
||||
- **Signing key:** Any valid certificate
|
||||
|
||||
2. **Configure advanced settings:**
|
||||
2. **Configure advanced settings:**
|
||||
Under advanced settings, set:
|
||||
|
||||
- **Scopes:**
|
||||
@ -121,7 +121,7 @@ To connect to an existing Nextcloud user, set the `nextcloud_user_id` attribute
|
||||
- **Subject mode:** Based on the User's UUID
|
||||
|
||||
:::danger
|
||||
Mapping the subject mode to authentik usernames is **not recommended** due to their mutable nature. If you choose to map to usernames, [disable username changing](../../../docs/sys-mgmt/settings#allow-users-to-change-username) in authentik and set it to `Based on the User's username`.
|
||||
Mapping the subject mode to authentik usernames is **not recommended** due to their mutable nature. If you choose to map to usernames, [disable username changing](/docs/sys-mgmt/settings#allow-users-to-change-username) in authentik and set it to `Based on the User's username`.
|
||||
:::
|
||||
|
||||
- **Include claims in ID token:** Enabled
|
||||
@ -136,15 +136,15 @@ An issue with the Nextcloud OIDC app limited the secret ID size to 64 characters
|
||||
Depending on your Nextcloud configuration, you might need to use `https://nextcloud.company/index.php/` instead of `https://nextcloud.company/`.
|
||||
:::
|
||||
|
||||
3. **Link the provider to an application:**
|
||||
3. **Link the provider to an application:**
|
||||
In **Applications > Applications**, create an application and select the provider you just created. Note the _application slug_ for later use.
|
||||
|
||||
### Nextcloud configuration
|
||||
|
||||
1. **Install the app:**
|
||||
1. **Install the app:**
|
||||
In Nextcloud, ensure the **OpenID Connect user backend** app is installed. Then navigate to **Settings > OpenID Connect**.
|
||||
|
||||
2. **Add a provider:**
|
||||
2. **Add a provider:**
|
||||
Click the **+** button and enter the following:
|
||||
|
||||
- **Identifier:** Authentik
|
||||
@ -167,7 +167,7 @@ Depending on your Nextcloud configuration, you might need to use `https://nextcl
|
||||
Enable **Use group provisioning** to allow writing to this field.
|
||||
:::
|
||||
|
||||
- **Use unique user ID:**
|
||||
- **Use unique user ID:**
|
||||
If deselected, Nextcloud uses the mapped user ID in the Federated Cloud ID.
|
||||
:::tip
|
||||
To avoid a hashed Federated Cloud ID, deselect **Use unique user ID** and use `user_id` for the User ID mapping.
|
||||
@ -177,7 +177,7 @@ Depending on your Nextcloud configuration, you might need to use `https://nextcl
|
||||
If you are using a custom profile scope and want administrators to be able to log in, ensure that **Use unique user ID** is deselected. Otherwise, this setting will remove Administrator users from the internal admin group and replace them with a hashed group ID named "admin", which lacks actual admin access rights.
|
||||
:::
|
||||
|
||||
3. **Log in:**
|
||||
3. **Log in:**
|
||||
Once configured, single sign-on (SSO) login via authentik becomes available.
|
||||
|
||||
#### Making OIDC the default login method
|
||||
@ -204,19 +204,19 @@ The following placeholders are used in this guide:
|
||||
This documentation lists only the settings you need to change from their default values. Other changes might cause issues accessing your application.
|
||||
:::
|
||||
|
||||
1. **Create an application in authentik:**
|
||||
1. **Create an application in authentik:**
|
||||
Note the chosen slug as it will be used later.
|
||||
|
||||
2. **Create a SAML provider:**
|
||||
2. **Create a SAML provider:**
|
||||
In authentik, navigate to **Applications > Providers** and create a **SAML provider** with the following settings:
|
||||
|
||||
- **ACS URL:**
|
||||
- **ACS URL:**
|
||||
`https://nextcloud.company/apps/user_saml/saml/acs`
|
||||
- **Issuer:**
|
||||
- **Issuer:**
|
||||
`https://authentik.company`
|
||||
- **Service Provider Binding:**
|
||||
- **Service Provider Binding:**
|
||||
Post
|
||||
- **Audience:**
|
||||
- **Audience:**
|
||||
`https://nextcloud.company/apps/user_saml/saml/metadata`
|
||||
- **Signing certificate:** Select any valid certificate.
|
||||
- **Property mappings:** Select all managed mappings.
|
||||
@ -227,12 +227,12 @@ Depending on your Nextcloud configuration, you might need to use `https://nextcl
|
||||
|
||||
#### Nextcloud configuration
|
||||
|
||||
1. **Install the app:**
|
||||
1. **Install the app:**
|
||||
In Nextcloud, ensure the **SSO & SAML Authentication** app is installed. Then navigate to **Settings > SSO & SAML Authentication**.
|
||||
|
||||
2. **Configure the following settings:**
|
||||
|
||||
- **Attribute to map the UID to:**
|
||||
- **Attribute to map the UID to:**
|
||||
`http://schemas.goauthentik.io/2021/02/saml/uid`
|
||||
|
||||
:::danger
|
||||
@ -240,23 +240,23 @@ Depending on your Nextcloud configuration, you might need to use `https://nextcl
|
||||
:::
|
||||
|
||||
- **Optional display name:** `authentik`
|
||||
- **Identifier of the IdP entity:**
|
||||
- **Identifier of the IdP entity:**
|
||||
`https://authentik.company`
|
||||
- **URL target for authentication requests:**
|
||||
- **URL target for authentication requests:**
|
||||
`https://authentik.company/application/saml/<application-slug>/sso/binding/redirect/`
|
||||
- **URL for SLO requests:**
|
||||
- **URL for SLO requests:**
|
||||
`https://authentik.company/application/saml/<application-slug>/slo/binding/redirect/`
|
||||
- **Public X.509 certificate of the IdP:**
|
||||
- **Public X.509 certificate of the IdP:**
|
||||
Paste the PEM from your selected certificate.
|
||||
|
||||
3. **Set attribute mapping:**
|
||||
3. **Set attribute mapping:**
|
||||
Configure the following mappings:
|
||||
|
||||
- **Display name:**
|
||||
- **Display name:**
|
||||
`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name`
|
||||
- **Email:**
|
||||
- **Email:**
|
||||
`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`
|
||||
- **User groups:**
|
||||
- **User groups:**
|
||||
`http://schemas.xmlsoap.org/claims/Group`
|
||||
|
||||
:::note
|
||||
@ -265,10 +265,10 @@ If Nextcloud is behind a reverse proxy, force HTTPS by adding `'overwriteprotoco
|
||||
|
||||
#### Group quotas
|
||||
|
||||
1. **Set up groups:**
|
||||
1. **Set up groups:**
|
||||
Create a group for each storage quota level and assign a custom attribute (e.g., `nextcloud_quota`) with values like `15 GB`.
|
||||
|
||||
2. **Create a custom SAML property mapping:**
|
||||
2. **Create a custom SAML property mapping:**
|
||||
Name the mapping **SAML Nextcloud Quota** with:
|
||||
|
||||
- **SAML Attribute Name:** `nextcloud_quota`
|
||||
@ -280,14 +280,14 @@ If Nextcloud is behind a reverse proxy, force HTTPS by adding `'overwriteprotoco
|
||||
|
||||
(Here, `"1 GB"` is the default if no quota is set.)
|
||||
|
||||
3. **Configure Nextcloud:**
|
||||
3. **Configure Nextcloud:**
|
||||
In Nextcloud under **Settings > SSO & SAML Authentication**, set the **Attribute to map the quota to** as `nextcloud_quota`.
|
||||
|
||||
#### Admin group
|
||||
|
||||
To grant admin access to authentik users:
|
||||
|
||||
1. **Create a custom SAML property mapping for admins:**
|
||||
1. **Create a custom SAML property mapping for admins:**
|
||||
Configure a mapping with:
|
||||
|
||||
- **SAML Attribute Name:** `http://schemas.xmlsoap.org/claims/Group`
|
||||
@ -300,7 +300,7 @@ To grant admin access to authentik users:
|
||||
yield "admin"
|
||||
```
|
||||
|
||||
2. **Update the Nextcloud provider:**
|
||||
2. **Update the Nextcloud provider:**
|
||||
Replace the default Groups mapping with this custom mapping.
|
||||
|
||||
</TabItem>
|
||||
|
@ -93,7 +93,7 @@ Push Security requires separate first and last names for each user, but authenti
|
||||
5. Click **Next**.
|
||||
6. Choose **Manual**, and enter the following as the **Single Sign-On Login URL**: `https://authentik.company/application/saml/<application-slug>/sso/binding/post/`
|
||||
7. Click **Upload signing certificate**, and upload the certificate downloaded from authentik.
|
||||
8. _(Optional but recommended)_ Under **Advanced Settings**, enable **Sign request**. Then download the verification certificate. You’ll need to import this into authentik. Refer to the [authentik certificate documentation](../../../docs/sys-mgmt/certificates#external-certificates) for guidance.
|
||||
8. _(Optional but recommended)_ Under **Advanced Settings**, enable **Sign request**. Then download the verification certificate. You’ll need to import this into authentik. Refer to the [authentik certificate documentation](/docs/sys-mgmt/certificates#external-certificates) for guidance.
|
||||
9. Click **Next**.
|
||||
10. On the **Attribute Mapping** page, click **Next** without making changes.
|
||||
11. Leave the **Test SSO** page open. You’ll return to it after completing the next section.
|
||||
|
@ -36,12 +36,12 @@ This documentation lists only the settings that you need to change from their de
|
||||
:::
|
||||
|
||||
:::warning
|
||||
The provider configuration assumes that connections to the outpost use LDAPS, with properly configured certificates on both authentik and the host running sssd. LDAPS is the recommended protocol for secure communication. For details on setting up SSL and StartTLS on the outpost, refer to [authentik’s LDAP provider documentation](../../../docs/add-secure-apps/providers/ldap#ssl--starttls).
|
||||
The provider configuration assumes that connections to the outpost use LDAPS, with properly configured certificates on both authentik and the host running sssd. LDAPS is the recommended protocol for secure communication. For details on setting up SSL and StartTLS on the outpost, refer to [authentik’s LDAP provider documentation](/docs/add-secure-apps/providers/ldap#ssl--starttls).
|
||||
:::
|
||||
|
||||
## authentik configuration
|
||||
|
||||
Follow [official documentation](../../../docs/add-secure-apps/outposts/#create-and-configure-an-outpost) to create an **LDAP outpost**. If you already have an LDAP outpost configured, you can use it without additional setup. No further configuration in authentik is needed.
|
||||
Follow [official documentation](/docs/add-secure-apps/outposts/#create-and-configure-an-outpost) to create an **LDAP outpost**. If you already have an LDAP outpost configured, you can use it without additional setup. No further configuration in authentik is needed.
|
||||
|
||||
## sssd configuration
|
||||
|
||||
|
@ -29,7 +29,7 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
Follow [official documentation](../../../docs/add-secure-apps/outposts/#create-and-configure-an-outpost) to create an **LDAP outpost**. If you already have an LDAP outpost configured, you can use it without additional setup. No further configuration in authentik is needed.
|
||||
Follow [official documentation](/docs/add-secure-apps/outposts/#create-and-configure-an-outpost) to create an **LDAP outpost**. If you already have an LDAP outpost configured, you can use it without additional setup. No further configuration in authentik is needed.
|
||||
|
||||
### The Lounge configuration
|
||||
|
||||
|
@ -51,6 +51,12 @@
|
||||
to = "/docs/sources/:splat"
|
||||
status = 302
|
||||
|
||||
# Split integrations to separate deploy
|
||||
[[redirects]]
|
||||
from = "/integrations/*"
|
||||
to = "https://integrations.goauthentik.io/integrations/:splat"
|
||||
status = 302
|
||||
|
||||
# Split Property Mappings docs between Providers and Sources
|
||||
[[redirects]]
|
||||
from = "/docs/property-mappings/"
|
||||
|
@ -9,6 +9,7 @@
|
||||
"build:api": "docusaurus gen-api-docs all",
|
||||
"build:docker": "cp ../docker-compose.yml ./static/docker-compose.yml",
|
||||
"build:docusaurus": "cross-env NODE_OPTIONS='--max_old_space_size=65536' docusaurus build",
|
||||
"build:integrations": "cross-env NODE_OPTIONS='--max_old_space_size=65536' docusaurus build --config integrations/docusaurus.config.cjs",
|
||||
"build:schema": "cp -f ../schema.yml ./static/schema.yml",
|
||||
"deploy": "docusaurus deploy",
|
||||
"docusaurus": "docusaurus",
|
||||
@ -21,7 +22,8 @@
|
||||
"start": "docusaurus start",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"test": "node --test",
|
||||
"watch": "run-s build:schema build:api start"
|
||||
"watch": "run-s build:schema build:api start",
|
||||
"watch:integrations": "docusaurus start --config integrations/docusaurus.config.cjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^3.7.0",
|
||||
|
31
website/remark/link-rewrite-directive.mjs
Normal file
31
website/remark/link-rewrite-directive.mjs
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @import { Root } from "mdast";
|
||||
*/
|
||||
import { visit } from "unist-util-visit";
|
||||
|
||||
/**
|
||||
* Remark plugin to transform relative links to docs to absolute URLs
|
||||
* @param {Map<string, string>} rewriteMap Map of urls to rewrite where the key is the prefix to check for and the value is the domain to add
|
||||
*/
|
||||
function remarkLinkRewrite(rewriteMap) {
|
||||
return () => {
|
||||
/**
|
||||
* @param {Root} tree The MDAST tree to transform.
|
||||
*/
|
||||
return async (tree) => {
|
||||
visit(tree, (node) => {
|
||||
if (node.type !== "link") {
|
||||
return;
|
||||
}
|
||||
rewriteMap.forEach((v, k) => {
|
||||
if (!node.url.startsWith(k)) {
|
||||
return;
|
||||
}
|
||||
node.url = `${v}${node.url}`;
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default remarkLinkRewrite;
|
@ -241,6 +241,7 @@ const items = [
|
||||
items: [
|
||||
"add-secure-apps/providers/rac/how-to-rac",
|
||||
"add-secure-apps/providers/rac/rac-public-key",
|
||||
"add-secure-apps/providers/rac/rac_credentials_prompt",
|
||||
],
|
||||
},
|
||||
"add-secure-apps/providers/radius/index",
|
||||
@ -709,7 +710,7 @@ const items = [
|
||||
{
|
||||
type: "category",
|
||||
label: "2025",
|
||||
items: ["security/cves/CVE-2025-29928"],
|
||||
items: ["security/cves/CVE-2025-52553", "security/cves/CVE-2025-29928"],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
|
@ -1,8 +1,27 @@
|
||||
import { PluginOptions } from "@docusaurus/plugin-content-docs";
|
||||
import { Options } from "@docusaurus/preset-classic";
|
||||
import { Redirect } from "@docusaurus/router";
|
||||
import { PresetConfigDefined } from "@docusaurus/types";
|
||||
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
||||
import React from "react";
|
||||
|
||||
function Home() {
|
||||
return <Redirect to="/docs" />;
|
||||
const { siteConfig } = useDocusaurusContext();
|
||||
const presets = siteConfig.presets as PresetConfigDefined[];
|
||||
const presetClassic = presets
|
||||
.filter((v) => {
|
||||
return !(v instanceof String);
|
||||
})
|
||||
.filter(([name, _]) => {
|
||||
return name === "@docusaurus/preset-classic";
|
||||
})
|
||||
.map(([_, config]) => {
|
||||
return config;
|
||||
});
|
||||
const presetConfig = presetClassic[0] as Options;
|
||||
const docsConfig = presetConfig.docs as PluginOptions;
|
||||
const presetURL = `/${docsConfig.routeBasePath}`;
|
||||
return <Redirect to={presetURL} />;
|
||||
}
|
||||
|
||||
export default Home;
|
||||
|
Reference in New Issue
Block a user