Compare commits

..

22 Commits

Author SHA1 Message Date
c4271b1ff7 argh 2025-04-30 17:53:59 -05:00
d37f025881 tweak 2025-04-30 17:43:06 -05:00
149815885d final tweaks 2025-04-30 17:23:48 -05:00
be46545613 tweak to remove gerunds 2025-04-30 17:17:34 -05:00
9d3822373a rework intro 2025-04-30 17:16:48 -05:00
ab84adc13f Update website/docs/add-secure-apps/providers/oauth2/device_code.md
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
2025-04-30 17:16:48 -05:00
689c59fe1c Update website/docs/add-secure-apps/providers/oauth2/device_code.md
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
b8578623fc Update device_code.md
removed newline as per "prettier --write"

Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
ae4947e85b Update website/docs/add-secure-apps/providers/oauth2/device_code.md
Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
5e840baf84 Update website/docs/add-secure-apps/providers/oauth2/device_code.md
Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
df5ec2c020 Update website/docs/add-secure-apps/providers/oauth2/device_code.md
Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
f4c64b49c2 Update website/docs/add-secure-apps/providers/oauth2/device_code.md
Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
1c022cb366 Update website/docs/add-secure-apps/providers/oauth2/device_code.md
Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
ebd620562c Update website/docs/add-secure-apps/providers/oauth2/device_code.md
Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
7ecdc1e681 Fixed relative path
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
56bb76c4ef Fixed formatting according to style guide
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
8c2ba9176b "Relative vs. absolute paths" rule
Removed full link in favor of relative path

Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
11cbde771b Added step-by-step tutorial for setup
Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
14b6fc5d85 SEO Optimization
Added alternative name to "also known" section to improve searchability

Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
5d8630595d Improved UX
Marked keywords with Capital letters and proper formatting to clarify those are references to actual values/labels

Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
54f4b83cf7 Improved documentation
Added link for brand keyword, removed repetition

Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
3b6de494c9 Improved RFC reference
Replaced "abilities" with "capabilities" to better reflect RFC wording, added extended summary from RFC to ensure complete and clear understanding.

Signed-off-by: Dametto Luca <45915503+LucaTheHacker@users.noreply.github.com>
2025-04-30 17:16:48 -05:00
293 changed files with 5784 additions and 12432 deletions

View File

@ -118,15 +118,3 @@ updates:
prefix: "core:" prefix: "core:"
labels: labels:
- dependencies - dependencies
- package-ecosystem: docker-compose
directories:
# - /scripts # Maybe
- /tests/e2e
schedule:
interval: daily
time: "04:00"
open-pull-requests-limit: 10
commit-message:
prefix: "core:"
labels:
- dependencies

View File

@ -29,7 +29,7 @@ jobs:
- name: Generate API - name: Generate API
run: make gen-client-go run: make gen-client-go
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v8 uses: golangci/golangci-lint-action@v7
with: with:
version: latest version: latest
args: --timeout 5000s --verbose args: --timeout 5000s --verbose

View File

@ -16,7 +16,7 @@
], ],
"typescript.preferences.importModuleSpecifier": "non-relative", "typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifierEnding": "index", "typescript.preferences.importModuleSpecifierEnding": "index",
"typescript.tsdk": "./node_modules/typescript/lib", "typescript.tsdk": "./web/node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true, "typescript.enablePromptUseWorkspaceTsdk": true,
"yaml.schemas": { "yaml.schemas": {
"./blueprints/schema.json": "blueprints/**/*.yaml" "./blueprints/schema.json": "blueprints/**/*.yaml"
@ -30,5 +30,7 @@
} }
], ],
"go.testFlags": ["-count=1"], "go.testFlags": ["-count=1"],
"github-actions.workflows.pinned.workflows": [".github/workflows/ci-main.yml"] "github-actions.workflows.pinned.workflows": [
".github/workflows/ci-main.yml"
]
} }

View File

@ -85,17 +85,18 @@ FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.0 AS geoip
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN" ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN"
ENV GEOIPUPDATE_VERBOSE="1" ENV GEOIPUPDATE_VERBOSE="1"
ENV GEOIPUPDATE_ACCOUNT_ID_FILE="/run/secrets/GEOIPUPDATE_ACCOUNT_ID" ENV GEOIPUPDATE_ACCOUNT_ID_FILE="/run/secrets/GEOIPUPDATE_ACCOUNT_ID"
ENV GEOIPUPDATE_LICENSE_KEY_FILE="/run/secrets/GEOIPUPDATE_LICENSE_KEY"
USER root USER root
RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
--mount=type=secret,id=GEOIPUPDATE_LICENSE_KEY \ --mount=type=secret,id=GEOIPUPDATE_LICENSE_KEY \
mkdir -p /usr/share/GeoIP && \ mkdir -p /usr/share/GeoIP && \
/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 "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
# Stage 5: Download uv # Stage 5: Download uv
FROM ghcr.io/astral-sh/uv:0.7.3 AS uv FROM ghcr.io/astral-sh/uv:0.7.0 AS uv
# Stage 6: Base python image # 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.12.10-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" \

View File

@ -42,4 +42,4 @@ See [SECURITY.md](SECURITY.md)
## Adoption and Contributions ## Adoption and Contributions
Your organization uses authentik? We'd love to add your logo to the readme and our website! Email us @ hello@goauthentik.io or open a GitHub Issue/PR! For more information on how to contribute to authentik, please refer to our [contribution guide](https://docs.goauthentik.io/docs/developer-docs?utm_source=github). Your organization uses authentik? We'd love to add your logo to the readme and our website! Email us @ hello@goauthentik.io or open a GitHub Issue/PR! For more information on how to contribute to authentik, please refer to our [CONTRIBUTING.md file](./CONTRIBUTING.md).

View File

@ -54,7 +54,7 @@ def create_component(generator: SchemaGenerator, name, schema, type_=ResolvedCom
return component return component
def postprocess_schema_responses(result, generator: SchemaGenerator, **kwargs): def postprocess_schema_responses(result, generator: SchemaGenerator, **kwargs): # noqa: W0613
"""Workaround to set a default response for endpoints. """Workaround to set a default response for endpoints.
Workaround suggested at Workaround suggested at
<https://github.com/tfranzel/drf-spectacular/issues/119#issuecomment-656970357> <https://github.com/tfranzel/drf-spectacular/issues/119#issuecomment-656970357>

View File

@ -164,7 +164,9 @@ class BlueprintEntry:
"""Get the blueprint model, with yaml tags resolved if present""" """Get the blueprint model, with yaml tags resolved if present"""
return str(self.tag_resolver(self.model, blueprint)) return str(self.tag_resolver(self.model, blueprint))
def get_permissions(self, blueprint: "Blueprint") -> Generator[BlueprintEntryPermission]: def get_permissions(
self, blueprint: "Blueprint"
) -> Generator[BlueprintEntryPermission, None, None]:
"""Get permissions of this entry, with all yaml tags resolved""" """Get permissions of this entry, with all yaml tags resolved"""
for perm in self.permissions: for perm in self.permissions:
yield BlueprintEntryPermission( yield BlueprintEntryPermission(

View File

@ -57,7 +57,7 @@ class LogEventSerializer(PassiveSerializer):
@contextmanager @contextmanager
def capture_logs(log_default_output=True) -> Generator[list[LogEvent]]: def capture_logs(log_default_output=True) -> Generator[list[LogEvent], None, None]:
"""Capture log entries created""" """Capture log entries created"""
logs = [] logs = []
cap = LogCapture() cap = LogCapture()

View File

@ -15,7 +15,6 @@
{% endblock %} {% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/sfe/bootstrap.min.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'dist/sfe/bootstrap.min.css' %}">
<meta name="sentry-trace" content="{{ sentry_trace }}" /> <meta name="sentry-trace" content="{{ sentry_trace }}" />
<link rel="prefetch" href="{{ flow_background_url }}" />
{% include "base/header_js.html" %} {% include "base/header_js.html" %}
<style> <style>
html, html,
@ -23,7 +22,7 @@
height: 100%; height: 100%;
} }
body { body {
background-image: url("{{ flow_background_url }}"); background-image: url("{{ flow.background_url }}");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
} }

View File

@ -5,7 +5,7 @@
{% block head_before %} {% block head_before %}
{{ block.super }} {{ block.super }}
<link rel="prefetch" href="{{ flow_background_url }}" /> <link rel="prefetch" href="{{ flow.background_url }}" />
{% if flow.compatibility_mode and not inspector %} {% if flow.compatibility_mode and not inspector %}
<script>ShadyDOM = { force: !navigator.webdriver };</script> <script>ShadyDOM = { force: !navigator.webdriver };</script>
{% endif %} {% endif %}
@ -21,7 +21,7 @@ window.authentik.flow = {
<script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script> <script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script>
<style> <style>
:root { :root {
--ak-flow-background: url("{{ flow_background_url }}"); --ak-flow-background: url("{{ flow.background_url }}");
} }
</style> </style>
{% endblock %} {% endblock %}

View File

@ -13,9 +13,7 @@ class FlowInterfaceView(InterfaceView):
"""Flow interface""" """Flow interface"""
def get_context_data(self, **kwargs: Any) -> dict[str, Any]: def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
flow = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug")) kwargs["flow"] = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
kwargs["flow"] = flow
kwargs["flow_background_url"] = flow.background_url(self.request)
kwargs["inspector"] = "inspector" in self.request.GET kwargs["inspector"] = "inspector" in self.request.GET
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)

View File

@ -59,7 +59,7 @@ class PropertyMappingManager:
request: HttpRequest | None, request: HttpRequest | None,
return_mapping: bool = False, return_mapping: bool = False,
**kwargs, **kwargs,
) -> Generator[tuple[dict, PropertyMapping]]: ) -> Generator[tuple[dict, PropertyMapping], None]:
"""Iterate over all mappings that were pre-compiled and """Iterate over all mappings that were pre-compiled and
execute all of them with the given context""" execute all of them with the given context"""
if not self.__has_compiled: if not self.__has_compiled:

View File

@ -199,7 +199,7 @@ class SCIMGroupClient(SCIMClient[Group, SCIMProviderGroup, SCIMGroupSchema]):
chunk_size = len(ops) chunk_size = len(ops)
if len(ops) < 1: if len(ops) < 1:
return return
for chunk in batched(ops, chunk_size, strict=False): for chunk in batched(ops, chunk_size):
req = PatchRequest(Operations=list(chunk)) req = PatchRequest(Operations=list(chunk))
self._request( self._request(
"PATCH", "PATCH",

File diff suppressed because one or more lines are too long

14
go.mod
View File

@ -19,18 +19,18 @@ require (
github.com/jellydator/ttlcache/v3 v3.3.0 github.com/jellydator/ttlcache/v3 v3.3.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.0
github.com/prometheus/client_golang v1.22.0 github.com/prometheus/client_golang v1.22.0
github.com/redis/go-redis/v9 v9.8.0 github.com/redis/go-redis/v9 v9.7.3
github.com/sethvargo/go-envconfig v1.3.0 github.com/sethvargo/go-envconfig v1.2.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
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.2025040.1 goauthentik.io/api/v3 v3.2025024.9
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.29.0
golang.org/x/sync v0.14.0 golang.org/x/sync v0.13.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
layeh.com/radius v0.0.0-20210819152912-ad72663a72ab layeh.com/radius v0.0.0-20210819152912-ad72663a72ab
) )
@ -75,7 +75,7 @@ require (
go.opentelemetry.io/otel/trace v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect
golang.org/x/crypto v0.36.0 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/sys v0.31.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.24.0 // indirect golang.org/x/text v0.23.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

32
go.sum
View File

@ -230,8 +230,8 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0= github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0=
github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU= github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -245,14 +245,14 @@ github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sethvargo/go-envconfig v1.3.0 h1:gJs+Fuv8+f05omTpwWIu6KmuseFAXKrIaOZSh8RMt0U= github.com/sethvargo/go-envconfig v1.2.0 h1:q3XkOZWkC+G1sMLCrw9oPGTjYexygLOXDmGUit1ti8Q=
github.com/sethvargo/go-envconfig v1.3.0/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw= github.com/sethvargo/go-envconfig v1.2.0/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
@ -290,8 +290,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.2025040.1 h1:rQEcMNpz84/LPX8LVFteOJuserrd4PnU4k1Iu/wWqhs= goauthentik.io/api/v3 v3.2025024.9 h1:i3tbkyotE32ZpJ729BsPWTuLQUdtZ54Li4aP1amZzsM=
goauthentik.io/api/v3 v3.2025040.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= goauthentik.io/api/v3 v3.2025024.9/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=
@ -358,16 +358,16 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -376,8 +376,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -412,8 +412,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@ -56,7 +56,6 @@ EXPOSE 3389 6636 9300
USER 1000 USER 1000
ENV TMPDIR=/dev/shm/ \ ENV GOFIPS=1
GOFIPS=1
ENTRYPOINT ["/ldap"] ENTRYPOINT ["/ldap"]

View File

@ -97,7 +97,6 @@ elif [[ "$1" == "test-all" ]]; then
elif [[ "$1" == "healthcheck" ]]; then elif [[ "$1" == "healthcheck" ]]; then
run_authentik healthcheck $(cat $MODE_FILE) run_authentik healthcheck $(cat $MODE_FILE)
elif [[ "$1" == "dump_config" ]]; then elif [[ "$1" == "dump_config" ]]; then
shift
exec python -m authentik.lib.config $@ exec python -m authentik.lib.config $@
elif [[ "$1" == "debug" ]]; then elif [[ "$1" == "debug" ]]; then
exec sleep infinity exec sleep infinity

View File

@ -9,7 +9,7 @@
"version": "0.0.0", "version": "0.0.0",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"aws-cdk": "^2.1014.0", "aws-cdk": "^2.1012.0",
"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.1014.0", "version": "2.1012.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1014.0.tgz", "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1012.0.tgz",
"integrity": "sha512-es101rtRAClix9BncNL54iW90MiOyRv4iCC5tv/firGDnidS6pPinuK0IIFt0RO6w0+3heRxWBXg8HY+f9877w==", "integrity": "sha512-C6jSWkqP0hkY2Cs300VJHjspmTXDTMfB813kwZvRbd/OsKBfTBJBbYU16VoLAp1LVEOnQMf8otSlaSgzVF0X9A==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {

View File

@ -10,7 +10,7 @@
"node": ">=20" "node": ">=20"
}, },
"devDependencies": { "devDependencies": {
"aws-cdk": "^2.1014.0", "aws-cdk": "^2.1012.0",
"cross-env": "^7.0.3" "cross-env": "^7.0.3"
} }
} }

Binary file not shown.

View File

@ -12,8 +12,8 @@
# tmassimi, 2024 # tmassimi, 2024
# Marc Schmitt, 2024 # Marc Schmitt, 2024
# albanobattistella <albanobattistella@gmail.com>, 2024 # albanobattistella <albanobattistella@gmail.com>, 2024
# Matteo Piccina <altermatte@gmail.com>, 2025
# Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025 # Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025
# Matteo Piccina <altermatte@gmail.com>, 2025
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
@ -22,7 +22,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-23 09:00+0000\n" "POT-Creation-Date: 2025-04-23 09:00+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n" "PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025\n" "Last-Translator: Matteo Piccina <altermatte@gmail.com>, 2025\n"
"Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n" "Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\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"
@ -383,7 +383,7 @@ msgstr "Mappatura delle proprietà"
#: authentik/core/models.py #: authentik/core/models.py
msgid "session data" msgid "session data"
msgstr "dati sessione" msgstr ""
#: authentik/core/models.py #: authentik/core/models.py
msgid "Session" msgid "Session"
@ -509,7 +509,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 "Numero di password da verificare." msgstr ""
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
#: authentik/policies/password/models.py #: authentik/policies/password/models.py
@ -519,19 +519,18 @@ msgstr "Password non impostata nel contesto"
#: 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 ""
"Questa password è già stata utilizzata in precedenza. Scegline una diversa."
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policy" msgid "Password Uniqueness Policy"
msgstr "Politica di unicità della password" msgstr ""
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policies" msgid "Password Uniqueness Policies"
msgstr "Criteri di unicità delle password" msgstr ""
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
msgid "User Password History" msgid "User Password History"
msgstr "Cronologia password utente" msgstr ""
#: authentik/enterprise/policy.py #: authentik/enterprise/policy.py
msgid "Enterprise required to access this feature." msgid "Enterprise required to access this feature."
@ -2204,7 +2203,7 @@ msgstr "Ruoli"
#: authentik/rbac/models.py #: authentik/rbac/models.py
msgid "Initial Permissions" msgid "Initial Permissions"
msgstr "Permessi Iniziali" msgstr ""
#: authentik/rbac/models.py #: authentik/rbac/models.py
msgid "System permission" msgid "System permission"
@ -2459,9 +2458,6 @@ 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 ""
"Cerca l'appartenenza al gruppo in base a un attributo utente anziché a un "
"attributo di gruppo. Questo consente la risoluzione di gruppi nidificati su "
"sistemi come FreeIPA e Active Directory."
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "LDAP Source" msgid "LDAP Source"
@ -2481,19 +2477,19 @@ msgstr "Mappature delle proprietà della sorgente LDAP"
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection" msgid "User LDAP Source Connection"
msgstr "Connessione Sorgente LDAP Utente" msgstr ""
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "User LDAP Source Connections" msgid "User LDAP Source Connections"
msgstr "Connessioni Sorgente LDAP Utente" msgstr ""
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connection" msgid "Group LDAP Source Connection"
msgstr "Connessione Sorgente LDAP Gruppo" msgstr ""
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connections" msgid "Group LDAP Source Connections"
msgstr "Connessioni Sorgente LDAP Gruppo" msgstr ""
#: 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."
@ -2505,11 +2501,11 @@ msgstr "Nessun token ricevuto."
#: authentik/sources/oauth/models.py #: authentik/sources/oauth/models.py
msgid "HTTP Basic Authentication" msgid "HTTP Basic Authentication"
msgstr "HTTP Basic Authentication" msgstr ""
#: 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 "Includi il client ID e il segreto come parametri di richiesta" msgstr ""
#: authentik/sources/oauth/models.py #: authentik/sources/oauth/models.py
msgid "Request Token URL" msgid "Request Token URL"
@ -2556,8 +2552,6 @@ 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 ""
"Come eseguire l'autenticazione durante un flusso di richiesta del token "
"authorization_code"
#: authentik/sources/oauth/models.py #: authentik/sources/oauth/models.py
msgid "OAuth Source" msgid "OAuth Source"
@ -3490,9 +3484,6 @@ 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 ""
"Mostra all'utente il pulsante \"Ricordami su questo dispositivo\", "
"consentendo agli utenti abituali di passare direttamente all'inserimento "
"della password."
#: 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."
@ -3882,11 +3873,11 @@ 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 "La reputazione non può scendere sotto questo valore. Zero o negativo." msgstr ""
#: 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 "La reputazione non può superare questo valore. Zero o positivo." msgstr ""
#: 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."

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

538
package-lock.json generated
View File

@ -1,546 +1,12 @@
{ {
"name": "@goauthentik/authentik", "name": "@goauthentik/authentik",
"version": "2025.4.0", "version": "2025.2.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@goauthentik/authentik", "name": "@goauthentik/authentik",
"version": "2025.4.0", "version": "2025.2.1"
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.3.3",
"prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.10",
"typescript": "^5.6.2"
}
},
"node_modules/@babel/code-frame": {
"version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-validator-identifier": "^7.25.9",
"js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/generator": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz",
"integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.27.0",
"@babel/types": "^7.27.0",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
"integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.27.0"
},
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/template": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
"integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
"@babel/parser": "^7.27.0",
"@babel/types": "^7.27.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz",
"integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
"@babel/generator": "^7.27.0",
"@babel/parser": "^7.27.0",
"@babel/template": "^7.27.0",
"@babel/types": "^7.27.0",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
"integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.25.9",
"@babel/helper-validator-identifier": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@pkgr/core": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz",
"integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/unts"
}
},
"node_modules/@trivago/prettier-plugin-sort-imports": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-5.2.2.tgz",
"integrity": "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@babel/generator": "^7.26.5",
"@babel/parser": "^7.26.7",
"@babel/traverse": "^7.26.7",
"@babel/types": "^7.26.7",
"javascript-natural-sort": "^0.7.1",
"lodash": "^4.17.21"
},
"engines": {
"node": ">18.12"
},
"peerDependencies": {
"@vue/compiler-sfc": "3.x",
"prettier": "2.x - 3.x",
"prettier-plugin-svelte": "3.x",
"svelte": "4.x || 5.x"
},
"peerDependenciesMeta": {
"@vue/compiler-sfc": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
},
"svelte": {
"optional": true
}
}
},
"node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/detect-indent": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz",
"integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12.20"
}
},
"node_modules/detect-newline": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz",
"integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/fdir": {
"version": "6.4.4",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/get-stdin": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
"integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/git-hooks-list": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.2.0.tgz",
"integrity": "sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/fisker/git-hooks-list?sponsor=1"
}
},
"node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/is-plain-obj": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
"integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/javascript-natural-sort": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==",
"dev": true,
"license": "MIT"
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true,
"license": "MIT"
},
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
},
"engines": {
"node": ">=6"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true,
"license": "MIT"
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT"
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/prettier": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-plugin-organize-imports": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.1.0.tgz",
"integrity": "sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"prettier": ">=2.0",
"typescript": ">=2.9",
"vue-tsc": "^2.1.0"
},
"peerDependenciesMeta": {
"vue-tsc": {
"optional": true
}
}
},
"node_modules/prettier-plugin-packagejson": {
"version": "2.5.10",
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.10.tgz",
"integrity": "sha512-LUxATI5YsImIVSaaLJlJ3aE6wTD+nvots18U3GuQMJpUyClChaZlQrqx3dBnbhF20OnKWZyx8EgyZypQtBDtgQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"sort-package-json": "2.15.1",
"synckit": "0.9.2"
},
"peerDependencies": {
"prettier": ">= 1.16.0"
},
"peerDependenciesMeta": {
"prettier": {
"optional": true
}
}
},
"node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sort-object-keys": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz",
"integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==",
"dev": true,
"license": "MIT"
},
"node_modules/sort-package-json": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.15.1.tgz",
"integrity": "sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==",
"dev": true,
"license": "MIT",
"dependencies": {
"detect-indent": "^7.0.1",
"detect-newline": "^4.0.0",
"get-stdin": "^9.0.0",
"git-hooks-list": "^3.0.0",
"is-plain-obj": "^4.1.0",
"semver": "^7.6.0",
"sort-object-keys": "^1.1.3",
"tinyglobby": "^0.2.9"
},
"bin": {
"sort-package-json": "cli.js"
}
},
"node_modules/synckit": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
"integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@pkgr/core": "^0.1.0",
"tslib": "^2.6.2"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/unts"
}
},
"node_modules/tinyglobby": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.4.4",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD"
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
} }
} }
} }

View File

@ -1,15 +1,5 @@
{ {
"name": "@goauthentik/authentik", "name": "@goauthentik/authentik",
"version": "2025.4.0", "version": "2025.4.0",
"private": true, "private": true
"type": "module",
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.3.3",
"prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.10",
"typescript": "^5.6.2"
},
"workspaces": [],
"prettier": "./packages/prettier-config/index.js"
} }

View File

@ -1,12 +1,12 @@
{ {
"name": "@goauthentik/docusaurus-config", "name": "@goauthentik/docusaurus-config",
"version": "1.0.6", "version": "1.0.5",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@goauthentik/docusaurus-config", "name": "@goauthentik/docusaurus-config",
"version": "1.0.6", "version": "1.0.5",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"deepmerge-ts": "^7.1.5", "deepmerge-ts": "^7.1.5",

View File

@ -1,6 +1,6 @@
{ {
"name": "@goauthentik/docusaurus-config", "name": "@goauthentik/docusaurus-config",
"version": "1.0.6", "version": "1.0.5",
"description": "authentik's Docusaurus config", "description": "authentik's Docusaurus config",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {

View File

@ -2,3 +2,4 @@
This package contains utility scripts common to all TypeScript and JavaScript packages in the This package contains utility scripts common to all TypeScript and JavaScript packages in the
`@goauthentik` monorepo. `@goauthentik` monorepo.

View File

@ -1,9 +1,8 @@
/** /**
* @file Constants for JavaScript and TypeScript files. * @file Constants for JavaScript and TypeScript files.
*
*/ */
/// <reference types="../../types/global.js" />
/** /**
* The current Node.js environment, defaulting to "development" when not set. * The current Node.js environment, defaulting to "development" when not set.
* *
@ -13,4 +12,6 @@
* ensure that module tree-shaking works correctly. * ensure that module tree-shaking works correctly.
* *
*/ */
export const NodeEnvironment = process.env.NODE_ENV || "development"; export const NodeEnvironment = /** @type {'development' | 'production'} */ (
process.env.NODE_ENV || "development"
);

View File

@ -1,7 +1,4 @@
/// <reference types="./types/global.js" />
export * from "./paths.js"; export * from "./paths.js";
export * from "./constants.js"; export * from "./constants.js";
export * from "./build.js";
export * from "./version.js"; export * from "./version.js";
export * from "./scripting.js"; export * from "./scripting.js";

View File

@ -0,0 +1,19 @@
{
"name": "@goauthentik/monorepo",
"version": "1.0.0",
"description": "Utilities for the authentik monorepo.",
"private": true,
"license": "MIT",
"type": "module",
"exports": {
"./package.json": "./package.json",
".": {
"import": "./index.js",
"types": "./out/index.d.ts"
}
},
"types": "./out/index.d.ts",
"engines": {
"node": ">=20.11"
}
}

View File

@ -0,0 +1,30 @@
import { createRequire } from "node:module";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
/**
* @typedef {'~authentik'} MonoRepoRoot
*/
/**
* The root of the authentik monorepo.
*/
export const MonoRepoRoot = /** @type {MonoRepoRoot} */ (resolve(__dirname, "..", ".."));
const require = createRequire(import.meta.url);
/**
* Resolve a package name to its location in the monorepo to the single node_modules directory.
* @param {string} packageName
* @returns {string} The resolved path to the package.
* @throws {Error} If the package cannot be resolved.
*/
export function resolvePackage(packageName) {
const packageJSONPath = require.resolve(join(packageName, "package.json"), {
paths: [MonoRepoRoot],
});
return dirname(packageJSONPath);
}

View File

View File

@ -1,6 +1,6 @@
import { execSync } from "node:child_process"; import { execSync } from "node:child_process";
import PackageJSON from "../../../package.json" with { type: "json" }; import PackageJSON from "../../package.json" with { type: "json" };
import { MonoRepoRoot } from "./paths.js"; import { MonoRepoRoot } from "./paths.js";
/** /**

View File

@ -76,7 +76,6 @@ EXPOSE 9000 9300 9443
USER 1000 USER 1000
ENV TMPDIR=/dev/shm/ \ ENV GOFIPS=1
GOFIPS=1
ENTRYPOINT ["/proxy"] ENTRYPOINT ["/proxy"]

View File

@ -3,7 +3,7 @@ name = "authentik"
version = "2025.4.0" version = "2025.4.0"
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.12.*"
dependencies = [ dependencies = [
"argon2-cffi", "argon2-cffi",
"celery", "celery",
@ -52,7 +52,7 @@ dependencies = [
"pydantic-scim", "pydantic-scim",
"pyjwt", "pyjwt",
"pyrad", "pyrad",
"python-kadmin-rs", "python-kadmin-rs ==0.6.0",
"pyyaml", "pyyaml",
"requests-oauthlib", "requests-oauthlib",
"scim2-filter-parser", "scim2-filter-parser",
@ -70,7 +70,7 @@ dependencies = [
"watchdog", "watchdog",
"webauthn", "webauthn",
"wsproto", "wsproto",
"xmlsec", "xmlsec <= 1.3.14",
"zxcvbn", "zxcvbn",
] ]
@ -101,18 +101,6 @@ dev = [
"selenium", "selenium",
] ]
[tool.uv]
no-binary-package = [
# This differs from the no-binary packages in the Dockerfile. This is due to the fact
# that these packages are built from source for different reasons than cryptography and kadmin.
# These packages are built from source to link against the libxml2 on the system which is
# required for functionality and to stay up-to-date on both libraries.
# The other packages specified in the dockerfile are compiled from source to link against the
# correct FIPS OpenSSL libraries
"lxml",
"xmlsec",
]
[tool.uv.sources] [tool.uv.sources]
django-tenants = { git = "https://github.com/rissson/django-tenants.git", branch = "authentik-fixes" } django-tenants = { git = "https://github.com/rissson/django-tenants.git", branch = "authentik-fixes" }
opencontainers = { git = "https://github.com/BeryJu/oci-python", rev = "c791b19056769cd67957322806809ab70f5bead8" } opencontainers = { git = "https://github.com/BeryJu/oci-python", rev = "c791b19056769cd67957322806809ab70f5bead8" }
@ -155,12 +143,12 @@ ignore-words = ".github/codespell-words.txt"
[tool.black] [tool.black]
line-length = 100 line-length = 100
target-version = ['py313'] target-version = ['py312']
exclude = 'node_modules' exclude = 'node_modules'
[tool.ruff] [tool.ruff]
line-length = 100 line-length = 100
target-version = "py313" target-version = "py312"
exclude = ["**/migrations/**", "**/node_modules/**"] exclude = ["**/migrations/**", "**/node_modules/**"]
[tool.ruff.lint] [tool.ruff.lint]

View File

@ -56,7 +56,6 @@ HEALTHCHECK --interval=5s --retries=20 --start-period=3s CMD [ "/rac", "healthch
USER 1000 USER 1000
ENV TMPDIR=/dev/shm/ \ ENV GOFIPS=1
GOFIPS=1
ENTRYPOINT ["/rac"] ENTRYPOINT ["/rac"]

View File

@ -56,7 +56,6 @@ EXPOSE 1812/udp 9300
USER 1000 USER 1000
ENV TMPDIR=/dev/shm/ \ ENV GOFIPS=1
GOFIPS=1
ENTRYPOINT ["/radius"] ENTRYPOINT ["/radius"]

View File

@ -1,12 +1,12 @@
services: services:
chrome: chrome:
image: docker.io/selenium/standalone-chrome:136.0 image: docker.io/selenium/standalone-chrome:122.0
volumes: volumes:
- /dev/shm:/dev/shm - /dev/shm:/dev/shm
network_mode: host network_mode: host
restart: always restart: always
mailpit: mailpit:
image: docker.io/axllent/mailpit:v1.24.2 image: docker.io/axllent/mailpit:v1.6.5
ports: ports:
- 1025:1025 - 1025:1025
- 8025:8025 - 8025:8025

View File

@ -26,7 +26,6 @@ from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, TimeoutException, WebDriverException from selenium.common.exceptions import NoSuchElementException, TimeoutException, WebDriverException
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
from selenium.webdriver.remote.command import Command
from selenium.webdriver.remote.webdriver import WebDriver from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support.wait import WebDriverWait
@ -198,12 +197,7 @@ class SeleniumTestCase(DockerTestCase, StaticLiveServerTestCase):
super().tearDown() super().tearDown()
if IS_CI: if IS_CI:
print("::group::Browser logs") print("::group::Browser logs")
# Very verbose way to get browser logs for line in self.driver.get_log("browser"):
# https://github.com/SeleniumHQ/selenium/pull/15641
# for some reason this removes the `get_log` API from Remote Webdriver
# and only keeps it on the local Chrome web driver, even when using
# a remote chrome driver...? (nvm the fact this was released as a minor version)
for line in self.driver.execute(Command.GET_LOG, {"type": "browser"})["value"]:
print(line["message"]) print(line["message"])
if IS_CI: if IS_CI:
print("::endgroup::") print("::endgroup::")

View File

@ -1,28 +0,0 @@
// TypeScript Project Configuration
{
"extends": "./packages/tsconfig/tsconfig.json",
"compilerOptions": {
"baseUrl": "."
},
"watchOptions": {
"excludeDirectories": [
"**/.git", // Git
"**/.yarn", // Yarn
"**/.vscode", // VS Code
"**/.vscode-test-web", // VS Code Web Test
"**/dist", // Distributed build files
"**/out", // Output build files
"**/.drafts", // Drafts
"**/.github", // GitHub
"**/node_modules" // Node modules
]
},
// The root project has no sources of its own. By setting `files` to an empty
// list, TS won't automatically include all sources below root (the default).
"files": [],
"references": [
// Note that references are in the order we want them to be built.
// TODO: Left blank until TypeScript workspaces are complete.
]
}

2001
uv.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -2,11 +2,15 @@
node_modules node_modules
# don't lint build output (make sure it's set to your correct build folder name) # don't lint build output (make sure it's set to your correct build folder name)
dist dist
out
# don't lint nyc coverage output # don't lint nyc coverage output
coverage coverage
# Import order matters # Import order matters
poly.ts
src/locale-codes.ts src/locale-codes.ts
src/locales/ src/locales/
storybook-static/ storybook-static/
# Prettier breaks the tsconfig file
tsconfig.json
.storybook/css-import-maps* .storybook/css-import-maps*
package.json
packages/**/package.json

847
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +1,6 @@
{ {
"name": "@goauthentik/web", "name": "@goauthentik/web",
"version": "0.0.0", "version": "0.0.0",
"license": "MIT",
"private": true,
"scripts": {
"build": "wireit",
"build-locales": "wireit",
"build-locales:build": "wireit",
"build-proxy": "wireit",
"build:sfe": "wireit",
"esbuild:watch": "node scripts/build-web.mjs --watch",
"extract-locales": "wireit",
"format": "wireit",
"lint": "wireit",
"lint:imports": "wireit",
"lint:lockfile": "wireit",
"lint:nightmare": "wireit",
"lint:precommit": "wireit",
"lint:types": "wireit",
"lit-analyse": "wireit",
"postinstall": "bash scripts/patch-spotlight.sh",
"precommit": "wireit",
"prettier": "wireit",
"prettier-check": "wireit",
"pseudolocalize": "wireit",
"storybook": "storybook dev -p 6006",
"storybook:build": "wireit",
"test": "wireit",
"test:e2e": "wireit",
"test:e2e:watch": "wireit",
"test:watch": "wireit",
"tsc": "wireit",
"watch": "run-s build-locales esbuild:watch"
},
"type": "module",
"exports": {
"./package.json": "./package.json",
"./paths": "./paths.js",
"./scripts/*": "./scripts/*.mjs"
},
"dependencies": { "dependencies": {
"@codemirror/lang-css": "^6.3.1", "@codemirror/lang-css": "^6.3.1",
"@codemirror/lang-html": "^6.4.9", "@codemirror/lang-html": "^6.4.9",
@ -51,6 +13,7 @@
"@formatjs/intl-listformat": "^7.5.7", "@formatjs/intl-listformat": "^7.5.7",
"@fortawesome/fontawesome-free": "^6.6.0", "@fortawesome/fontawesome-free": "^6.6.0",
"@goauthentik/api": "^2025.4.0-1746018955", "@goauthentik/api": "^2025.4.0-1746018955",
"@lit-labs/ssr": "3.2.2",
"@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",
@ -91,7 +54,6 @@
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"remark-mdx-frontmatter": "^5.0.0", "remark-mdx-frontmatter": "^5.0.0",
"style-mod": "^4.1.2", "style-mod": "^4.1.2",
"trusted-types": "^2.0.0",
"ts-pattern": "^5.4.0", "ts-pattern": "^5.4.0",
"unist-util-visit": "^5.0.0", "unist-util-visit": "^5.0.0",
"webcomponent-qr-code": "^1.2.0", "webcomponent-qr-code": "^1.2.0",
@ -100,7 +62,6 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.11.1", "@eslint/js": "^9.11.1",
"@goauthentik/esbuild-plugin-live-reload": "^1.0.4", "@goauthentik/esbuild-plugin-live-reload": "^1.0.4",
"@goauthentik/monorepo": "^1.0.0",
"@goauthentik/prettier-config": "^1.0.4", "@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4", "@goauthentik/tsconfig": "^1.0.4",
"@hcaptcha/types": "^1.0.4", "@hcaptcha/types": "^1.0.4",
@ -132,13 +93,13 @@
"@wdio/spec-reporter": "^9.1.2", "@wdio/spec-reporter": "^9.1.2",
"chromedriver": "^131.0.1", "chromedriver": "^131.0.1",
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"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.11.1", "eslint": "^9.11.1",
"eslint-plugin-lit": "^1.15.0", "eslint-plugin-lit": "^1.15.0",
"eslint-plugin-wc": "^2.1.1", "eslint-plugin-wc": "^2.1.1",
"github-slugger": "^2.0.0", "github-slugger": "^2.0.0",
"glob": "^11.0.0",
"globals": "^15.10.0", "globals": "^15.10.0",
"knip": "^5.30.6", "knip": "^5.30.6",
"lit-analyzer": "^2.0.3", "lit-analyzer": "^2.0.3",
@ -149,6 +110,7 @@
"rollup-plugin-postcss-lit": "^2.1.0", "rollup-plugin-postcss-lit": "^2.1.0",
"storybook": "^8.3.4", "storybook": "^8.3.4",
"storybook-addon-mock": "^5.0.0", "storybook-addon-mock": "^5.0.0",
"syncpack": "^13.0.0",
"turnstile-types": "^1.2.3", "turnstile-types": "^1.2.3",
"typescript": "^5.6.2", "typescript": "^5.6.2",
"typescript-eslint": "^8.8.0", "typescript-eslint": "^8.8.0",
@ -156,6 +118,10 @@
"vite-tsconfig-paths": "^5.0.1", "vite-tsconfig-paths": "^5.0.1",
"wireit": "^0.14.9" "wireit": "^0.14.9"
}, },
"engines": {
"node": ">=20"
},
"license": "MIT",
"optionalDependencies": { "optionalDependencies": {
"@esbuild/darwin-arm64": "^0.24.0", "@esbuild/darwin-arm64": "^0.24.0",
"@esbuild/linux-amd64": "^0.18.11", "@esbuild/linux-amd64": "^0.18.11",
@ -164,6 +130,48 @@
"@rollup/rollup-linux-arm64-gnu": "4.23.0", "@rollup/rollup-linux-arm64-gnu": "4.23.0",
"@rollup/rollup-linux-x64-gnu": "4.23.0" "@rollup/rollup-linux-x64-gnu": "4.23.0"
}, },
"overrides": {
"rapidoc": {
"@apitools/openapi-parser@": "0.0.37"
},
"chromedriver": {
"axios": "^1.8.4"
}
},
"prettier": "@goauthentik/prettier-config",
"private": true,
"scripts": {
"build": "wireit",
"build-locales": "wireit",
"build-locales:build": "wireit",
"build-proxy": "wireit",
"build:sfe": "wireit",
"esbuild:watch": "node scripts/build-web.mjs --watch",
"extract-locales": "wireit",
"format": "wireit",
"lint": "wireit",
"lint:imports": "wireit",
"lint:lockfile": "wireit",
"lint:nightmare": "wireit",
"lint:package": "wireit",
"lint:precommit": "wireit",
"lint:types": "wireit",
"lit-analyse": "wireit",
"postinstall": "bash scripts/patch-spotlight.sh",
"precommit": "wireit",
"prettier": "wireit",
"prettier-check": "wireit",
"pseudolocalize": "wireit",
"storybook": "storybook dev -p 6006",
"storybook:build": "wireit",
"test": "wireit",
"test:e2e": "wireit",
"test:e2e:watch": "wireit",
"test:watch": "wireit",
"tsc": "wireit",
"watch": "run-s build-locales esbuild:watch"
},
"type": "module",
"wireit": { "wireit": {
"build": { "build": {
"#comment": [ "#comment": [
@ -240,7 +248,10 @@
"command": "lit-localize extract" "command": "lit-localize extract"
}, },
"format": { "format": {
"command": "prettier --write ." "command": "prettier --write .",
"dependencies": [
"lint:package"
]
}, },
"format:packages": { "format:packages": {
"dependencies": [ "dependencies": [
@ -279,6 +290,9 @@
"./packages/sfe:lint:lockfile" "./packages/sfe:lint:lockfile"
] ]
}, },
"lint:package": {
"command": "syncpack format -i ' '"
},
"lint:nightmare": { "lint:nightmare": {
"command": "${NODE_RUNNER} ./scripts/eslint.mjs --nightmare", "command": "${NODE_RUNNER} ./scripts/eslint.mjs --nightmare",
"env": { "env": {
@ -309,6 +323,7 @@
"lint:types", "lint:types",
"lint:components", "lint:components",
"lint:spelling", "lint:spelling",
"lint:package",
"lint:lockfile", "lint:lockfile",
"lint:lockfiles", "lint:lockfiles",
"lint:precommit", "lint:precommit",
@ -373,20 +388,8 @@
] ]
} }
}, },
"engines": {
"node": ">=20"
},
"workspaces": [ "workspaces": [
".", ".",
"./packages/*" "./packages/*"
], ]
"prettier": "@goauthentik/prettier-config",
"overrides": {
"rapidoc": {
"@apitools/openapi-parser@": "0.0.37"
},
"chromedriver": {
"axios": "^1.8.4"
}
}
} }

View File

@ -1,11 +1,22 @@
{ {
"name": "@goauthentik/esbuild-plugin-live-reload", "name": "@goauthentik/esbuild-plugin-live-reload",
"version": "1.0.4",
"description": "ESBuild plugin to watch for file changes and trigger client-side reloads.", "description": "ESBuild plugin to watch for file changes and trigger client-side reloads.",
"license": "MIT", "version": "1.0.4",
"private": true, "dependencies": {
"main": "index.js", "find-free-ports": "^3.1.1"
"type": "module", },
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/node": "^22.14.1",
"esbuild": "^0.25.0",
"prettier": "^3.3.3",
"typescript": "^5.6.2"
},
"engines": {
"node": ">=20.11"
},
"exports": { "exports": {
"./package.json": "./package.json", "./package.json": "./package.json",
".": { ".": {
@ -21,33 +32,22 @@
"import": "./plugin/index.js" "import": "./plugin/index.js"
} }
}, },
"dependencies": {
"find-free-ports": "^3.1.1"
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/node": "^22.14.1",
"esbuild": "^0.25.0",
"prettier": "^3.3.3",
"typescript": "^5.6.2"
},
"peerDependencies": {
"esbuild": "^0.25.0"
},
"engines": {
"node": ">=20.11"
},
"types": "./out/index.d.ts",
"files": [ "files": [
"./index.js", "./index.js",
"client/**/*", "client/**/*",
"plugin/**/*", "plugin/**/*",
"out/**/*" "out/**/*"
], ],
"license": "MIT",
"main": "index.js",
"peerDependencies": {
"esbuild": "^0.25.0"
},
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config",
"private": true,
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} },
"type": "module",
"types": "./out/index.d.ts"
} }

View File

@ -1,42 +0,0 @@
/**
* @file Utility functions for building and copying files.
*/
/**
* A source environment variable, which can be a string, number, boolean, null, or undefined.
* @typedef {string | number | boolean | null | undefined} EnvironmentVariable
*/
/**
* A type helper for serializing environment variables.
*
* @template {EnvironmentVariable} T
* @typedef {T extends string ? `"${T}"` : T} JSONify
*/
/**
* Given an object of environment variables, returns a new object with the same keys and values, but
* with the values serialized as strings.
*
* @template {Record<string, EnvironmentVariable>} EnvRecord
* @template {string} [Prefix='process.env.']
*
* @param {EnvRecord} input
* @param {Prefix} [prefix='process.env.']
*
* @returns {{[K in keyof EnvRecord as `${Prefix}${K}`]: JSONify<EnvRecord[K]>}}
*/
export function serializeEnvironmentVars(input, prefix = /** @type {Prefix} */ ("process.env.")) {
/**
* @type {Record<string, string>}
*/
const env = {};
for (const [key, value] of Object.entries(input)) {
const namespaceKey = prefix + key;
env[namespaceKey] = JSON.stringify(value || "");
}
return /** @type {any} */ (env);
}

View File

@ -1,28 +0,0 @@
{
"name": "@goauthentik/monorepo",
"version": "1.0.0",
"description": "Utilities for the authentik monorepo.",
"license": "MIT",
"private": true,
"main": "index.js",
"type": "module",
"exports": {
"./package.json": "./package.json",
".": {
"types": "./out/index.d.ts",
"import": "./index.js"
}
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4",
"@types/node": "^22.14.1",
"prettier": "^3.3.3",
"typescript": "^5.6.2"
},
"engines": {
"node": ">=20.11"
},
"types": "./out/index.d.ts",
"prettier": "@goauthentik/prettier-config"
}

View File

@ -1,45 +0,0 @@
import { createRequire } from "node:module";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const relativeDirname = dirname(fileURLToPath(import.meta.url));
/**
* @typedef {'~authentik'} MonoRepoRoot
*/
/**
* The root of the authentik monorepo.
*/
// TODO: Revise when this package is moved to the monorepo's `packages/monorepo` directory.
export const MonoRepoRoot = /** @type {MonoRepoRoot} */ (
resolve(relativeDirname, "..", "..", "..")
);
const require = createRequire(import.meta.url);
/**
* Resolve a package name to its location in the monorepo to the single node_modules directory.
* @param {string} packageName
*
* @returns {string} The resolved path to the package.
* @throws {Error} If the package cannot be resolved.
*/
export function resolvePackage(packageName) {
const relativePackageJSONPath = join(packageName, "package.json");
/** @type {string} */
let absolutePackageJSONPath;
try {
absolutePackageJSONPath = require.resolve(relativePackageJSONPath);
} catch (cause) {
const error = new Error(`Failed to resolve package "${packageName}"`);
error.cause = cause;
throw error;
}
return dirname(absolutePackageJSONPath);
}

View File

@ -1,15 +0,0 @@
declare module "process" {
global {
namespace NodeJS {
interface ProcessEnv {
/**
* An environment variable used to determine
* whether Node.js is running in production mode.
*
* @see {@link https://nodejs.org/en/learn/getting-started/nodejs-the-difference-between-development-and-production | The difference between development and production}
*/
NODE_ENV?: "production" | "development";
}
}
}
}

View File

@ -47,16 +47,7 @@ class SimpleFlowExecutor {
return `${ak().api.base}api/v3/flows/executor/${this.flowSlug}/?query=${encodeURIComponent(window.location.search.substring(1))}`; return `${ak().api.base}api/v3/flows/executor/${this.flowSlug}/?query=${encodeURIComponent(window.location.search.substring(1))}`;
} }
loading() {
this.container.innerHTML = `<div class="d-flex justify-content-center">
<div class="spinner-border spinner-border-md" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>`;
}
start() { start() {
this.loading();
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: this.apiURL, url: this.apiURL,

View File

@ -1,78 +0,0 @@
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const relativeDirname = dirname(fileURLToPath(import.meta.url));
//#region Base paths
/**
* @typedef {'@goauthentik/web'} WebPackageIdentifier
*/
/**
* The root of the web package.
*/
export const PackageRoot = /** @type {WebPackageIdentifier} */ (resolve(relativeDirname));
/**
* The name of the distribution directory.
*/
export const DistDirectoryName = "dist";
/**
* Path to the web package's distribution directory.
*
* This is where the built files are located after running the build process.
*/
export const DistDirectory = /** @type {`${WebPackageIdentifier}/${DistDirectoryName}`} */ (
resolve(relativeDirname, DistDirectoryName)
);
//#endregion
//#region Entry points
/**
* @typedef {{ in: string, out: string }} EntryPointTarget
*
* ESBuild entrypoint target.
* Matches the type defined in the ESBuild context.
*/
/**
* Entry points available for building.
*
* @satisfies {Record<string, EntryPointTarget>}
*/
export const EntryPoint = /** @type {const} */ ({
Admin: {
in: resolve(PackageRoot, "src", "admin", "AdminInterface", "index.entrypoint.ts"),
out: resolve(DistDirectory, "admin", "AdminInterface"),
},
User: {
in: resolve(PackageRoot, "src", "user", "index.entrypoint.ts"),
out: resolve(DistDirectory, "user", "UserInterface"),
},
Flow: {
in: resolve(PackageRoot, "src", "flow", "index.entrypoint.ts"),
out: resolve(DistDirectory, "flow", "FlowInterface"),
},
Standalone: {
in: resolve(PackageRoot, "src", "standalone", "api-browser/index.entrypoint.ts"),
out: resolve(DistDirectory, "standalone", "api-browser", "index"),
},
StandaloneLoading: {
in: resolve(PackageRoot, "src", "standalone", "loading/index.entrypoint.ts"),
out: resolve(DistDirectory, "standalone", "loading", "index"),
},
RAC: {
in: resolve(PackageRoot, "src", "rac", "index.entrypoint.ts"),
out: resolve(DistDirectory, "rac", "index"),
},
Polyfill: {
in: resolve(PackageRoot, "src", "polyfill", "index.entrypoint.ts"),
out: resolve(DistDirectory, "poly"),
},
});
//#endregion

View File

@ -4,86 +4,138 @@
* @import { BuildOptions } from "esbuild"; * @import { BuildOptions } from "esbuild";
*/ */
import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload/plugin"; import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload/plugin";
import { import { execFileSync } from "child_process";
MonoRepoRoot,
NodeEnvironment,
readBuildIdentifier,
resolvePackage,
serializeEnvironmentVars,
} from "@goauthentik/monorepo";
import { DistDirectory, DistDirectoryName, EntryPoint, PackageRoot } from "@goauthentik/web/paths";
import { deepmerge } from "deepmerge-ts"; import { deepmerge } from "deepmerge-ts";
import esbuild from "esbuild"; import esbuild from "esbuild";
import copy from "esbuild-plugin-copy";
import { polyfillNode } from "esbuild-plugin-polyfill-node"; import { polyfillNode } from "esbuild-plugin-polyfill-node";
import * as fs from "node:fs/promises"; import { copyFileSync, mkdirSync, readFileSync, statSync } from "fs";
import * as path from "node:path"; import { globSync } from "glob";
import * as path from "path";
import { cwd } from "process";
import process from "process";
import { fileURLToPath } from "url";
import { mdxPlugin } from "./esbuild/build-mdx-plugin.mjs"; import { mdxPlugin } from "./esbuild/build-mdx-plugin.mjs";
const logPrefix = "[Build]"; const __dirname = fileURLToPath(new URL(".", import.meta.url));
let authentikProjectRoot = path.join(__dirname, "..", "..");
const definitions = serializeEnvironmentVars({ try {
NODE_ENV: NodeEnvironment, // Use the package.json file in the root folder, as it has the current version information.
CWD: process.cwd(), authentikProjectRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
AK_API_BASE_PATH: process.env.AK_API_BASE_PATH, encoding: "utf8",
}); }).replace("\n", "");
} catch (_error) {
// We probably don't have a .git folder, which could happen in container builds.
}
const patternflyPath = resolvePackage("@patternfly/patternfly"); const packageJSONPath = path.join(authentikProjectRoot, "./package.json");
const rootPackage = JSON.parse(readFileSync(packageJSONPath, "utf8"));
const NODE_ENV = process.env.NODE_ENV || "development";
const AK_API_BASE_PATH = process.env.AK_API_BASE_PATH || "";
const environmentVars = new Map([
["NODE_ENV", NODE_ENV],
["CWD", cwd()],
["AK_API_BASE_PATH", AK_API_BASE_PATH],
]);
const definitions = Object.fromEntries(
Array.from(environmentVars).map(([key, value]) => {
return [`process.env.${key}`, JSON.stringify(value)];
}),
);
/** /**
* @type {Readonly<BuildOptions>} * All is magic is just to make sure the assets are copied into the right places. This is a very
* stripped down version of what the rollup-copy-plugin does, without any of the features we don't
* use, and using globSync instead of globby since we already had globSync lying around thanks to
* Typescript. If there's a third argument in an array entry, it's used to replace the internal path
* before concatenating it all together as the destination target.
* @type {Array<[string, string, string?]>}
*/
const assetsFileMappings = [
["node_modules/@patternfly/patternfly/patternfly.min.css", "."],
["node_modules/@patternfly/patternfly/assets/**", ".", "node_modules/@patternfly/patternfly/"],
["src/common/styles/**", "."],
["src/assets/images/**", "./assets/images"],
["./icons/*", "./assets/icons"],
];
/**
* @param {string} filePath
*/
const isFile = (filePath) => statSync(filePath).isFile();
/**
* @param {string} src Source file
* @param {string} dest Destination folder
* @param {string} [strip] Path to strip from the source file
*/
function nameCopyTarget(src, dest, strip) {
const target = path.join(dest, strip ? src.replace(strip, "") : path.parse(src).base);
return [src, target];
}
for (const [source, rawdest, strip] of assetsFileMappings) {
const matchedPaths = globSync(source);
const dest = path.join("dist", rawdest);
const copyTargets = matchedPaths.map((path) => nameCopyTarget(path, dest, strip));
for (const [src, dest] of copyTargets) {
if (isFile(src)) {
mkdirSync(path.dirname(dest), { recursive: true });
copyFileSync(src, dest);
}
}
}
/**
* @typedef {[source: string, destination: string]} EntryPoint
*/
/**
* This starts the definitions used for esbuild: Our targets, our arguments, the function for
* running a build, and three options for building: watching, building, and building the proxy.
* Ordered by largest to smallest interface to build even faster
*
* @type {EntryPoint[]}
*/
const entryPoints = [
["admin/AdminInterface/AdminInterface.ts", "admin"],
["user/UserInterface.ts", "user"],
["flow/FlowInterface.ts", "flow"],
["standalone/api-browser/index.ts", "standalone/api-browser"],
["rac/index.ts", "rac"],
["standalone/loading/index.ts", "standalone/loading"],
["polyfill/poly.ts", "."],
];
/**
* @type {import("esbuild").BuildOptions}
*/ */
const BASE_ESBUILD_OPTIONS = { const BASE_ESBUILD_OPTIONS = {
entryNames: `[dir]/[name]-${readBuildIdentifier()}`,
chunkNames: "[dir]/chunks/[name]-[hash]",
assetNames: "assets/[dir]/[name]-[hash]",
publicPath: path.join("/static", DistDirectoryName),
outdir: DistDirectory,
bundle: true, bundle: true,
write: true, write: true,
sourcemap: true, sourcemap: true,
minify: NodeEnvironment === "production", minify: NODE_ENV === "production",
legalComments: "external",
splitting: true, splitting: true,
treeShaking: true, treeShaking: true,
external: ["*.woff", "*.woff2"], external: ["*.woff", "*.woff2"],
tsconfig: path.resolve(PackageRoot, "tsconfig.build.json"), tsconfig: path.resolve(__dirname, "..", "tsconfig.build.json"),
loader: { loader: {
".css": "text", ".css": "text",
}, },
plugins: [ plugins: [
copy({
assets: [
{
from: path.join(patternflyPath, "patternfly.min.css"),
to: ".",
},
{
from: path.join(patternflyPath, "assets", "**"),
to: "./assets",
},
{
from: path.resolve(PackageRoot, "src", "common", "styles", "**"),
to: ".",
},
{
from: path.resolve(PackageRoot, "src", "assets", "images", "**"),
to: "./assets/images",
},
{
from: path.resolve(PackageRoot, "icons", "*"),
to: "./assets/icons",
},
],
}),
polyfillNode({ polyfillNode({
polyfills: { polyfills: {
path: true, path: true,
}, },
}), }),
mdxPlugin({ mdxPlugin({
root: MonoRepoRoot, root: authentikProjectRoot,
}), }),
], ],
define: definitions, define: definitions,
@ -99,43 +151,69 @@ const BASE_ESBUILD_OPTIONS = {
}, },
}; };
async function cleanDistDirectory() { /**
const timerLabel = `${logPrefix} ♻️ Cleaning previous builds...`; * Creates a version ID for the build.
* @returns {string}
*/
function composeVersionID() {
const { version } = rootPackage;
const buildHash = process.env.GIT_BUILD_HASH;
console.time(timerLabel); if (buildHash) {
return `${version}+${buildHash}`;
}
await fs.rm(DistDirectory, { return version;
recursive: true,
force: true,
});
await fs.mkdir(DistDirectory, {
recursive: true,
});
console.timeEnd(timerLabel);
} }
/** /**
* Creates an ESBuild options, extending the base options with the given overrides. * Build a single entry point.
* *
* @param {BuildOptions} overrides * @param {EntryPoint} buildTarget
* @returns {BuildOptions} * @param {Partial<esbuild.BuildOptions>} [overrides]
* @throws {Error} on build failure
*/ */
export function createESBuildOptions(overrides) { function createEntryPointOptions([source, dest], overrides = {}) {
/** const outdir = path.join(__dirname, "..", "dist", dest);
* @type {BuildOptions}
*/
const mergedOptions = deepmerge(BASE_ESBUILD_OPTIONS, overrides);
return mergedOptions; /**
* @type {esbuild.BuildOptions}
*/
const entryPointConfig = {
entryPoints: [`./src/${source}`],
entryNames: `[dir]/[name]-${composeVersionID()}`,
publicPath: path.join("/static", "dist", dest),
outdir,
};
/**
* @type {esbuild.BuildOptions}
*/
const mergedConfig = deepmerge(BASE_ESBUILD_OPTIONS, entryPointConfig, overrides);
return mergedConfig;
}
/**
* Build all entry points in parallel.
*
* @param {EntryPoint[]} entryPoints
* @returns {Promise<esbuild.BuildResult[]>}
*/
async function buildParallel(entryPoints) {
return Promise.all(
entryPoints.map((entryPoint) => {
return esbuild.build(createEntryPointOptions(entryPoint));
}),
);
} }
function doHelp() { function doHelp() {
console.log(`Build the authentik UI console.log(`Build the authentik UI
options: options:
-w, --watch: Build all interfaces -w, --watch: Build all ${entryPoints.length} interfaces
-p, --proxy: Build only the polyfills and the loading application -p, --proxy: Build only the polyfills and the loading application
-h, --help: This help message -h, --help: This help message
`); `);
@ -144,29 +222,27 @@ function doHelp() {
} }
async function doWatch() { async function doWatch() {
console.group(`${logPrefix} 🤖 Watching entry points`); console.log("Watching all entry points...");
const entryPoints = Object.entries(EntryPoint).map(([entrypointID, target]) => { const buildContexts = await Promise.all(
console.log(entrypointID); entryPoints.map((entryPoint) => {
return esbuild.context(
createEntryPointOptions(entryPoint, {
define: definitions,
plugins: [
liveReloadPlugin({
logPrefix: `Build Observer (${entryPoint[1]})`,
relativeRoot: path.join(__dirname, ".."),
}),
],
}),
);
}),
);
return target; await Promise.all(buildContexts.map((context) => context.rebuild()));
});
console.groupEnd(); await Promise.allSettled(buildContexts.map((context) => context.watch()));
const buildOptions = createESBuildOptions({
entryPoints,
plugins: [
liveReloadPlugin({
relativeRoot: PackageRoot,
}),
],
});
const buildContext = await esbuild.context(buildOptions);
await buildContext.rebuild();
await buildContext.watch();
return /** @type {Promise<void>} */ ( return /** @type {Promise<void>} */ (
new Promise((resolve) => { new Promise((resolve) => {
@ -178,34 +254,15 @@ async function doWatch() {
} }
async function doBuild() { async function doBuild() {
console.group(`${logPrefix} 🚀 Building entry points:`); console.log("Building all entry points");
const entryPoints = Object.entries(EntryPoint).map(([entrypointID, target]) => { return buildParallel(entryPoints);
console.log(entrypointID);
return target;
});
console.groupEnd();
const buildOptions = createESBuildOptions({
entryPoints,
});
await esbuild.build(buildOptions);
console.log("Build complete");
} }
async function doProxy() { async function doProxy() {
const entryPoints = [EntryPoint.StandaloneLoading]; return buildParallel(
entryPoints.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)),
const buildOptions = createESBuildOptions({ );
entryPoints,
});
await esbuild.build(buildOptions);
console.log("Proxy build complete");
} }
async function delegateCommand() { async function delegateCommand() {
@ -227,16 +284,12 @@ async function delegateCommand() {
} }
} }
await cleanDistDirectory() await delegateCommand()
// --- .then(() => {
.then(() => console.log("Build complete");
delegateCommand() process.exit(0);
.then(() => { })
console.log("Build complete"); .catch((error) => {
process.exit(0); console.error(error);
}) process.exit(1);
.catch((error) => { });
console.error(error);
process.exit(1);
}),
);

View File

@ -1,11 +1,11 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { VERSION } from "@goauthentik/common/constants"; import { VERSION } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global"; import { globalAK } from "@goauthentik/common/global";
import { DefaultBrand } from "@goauthentik/common/ui/config";
import "@goauthentik/elements/EmptyState"; import "@goauthentik/elements/EmptyState";
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider"; import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider"; import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider";
import { ModalButton } from "@goauthentik/elements/buttons/ModalButton"; import { ModalButton } from "@goauthentik/elements/buttons/ModalButton";
import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { TemplateResult, css, html } from "lit"; import { TemplateResult, css, html } from "lit";

View File

@ -4,17 +4,13 @@ import { ROUTES } from "@goauthentik/admin/Routes";
import { import {
EVENT_API_DRAWER_TOGGLE, EVENT_API_DRAWER_TOGGLE,
EVENT_NOTIFICATION_DRAWER_TOGGLE, EVENT_NOTIFICATION_DRAWER_TOGGLE,
EVENT_SIDEBAR_TOGGLE,
} from "@goauthentik/common/constants"; } from "@goauthentik/common/constants";
import { configureSentry } from "@goauthentik/common/sentry"; import { configureSentry } from "@goauthentik/common/sentry";
import { me } from "@goauthentik/common/users"; import { me } from "@goauthentik/common/users";
import { WebsocketClient } from "@goauthentik/common/ws"; import { WebsocketClient } from "@goauthentik/common/ws";
import { AuthenticatedInterface } from "@goauthentik/elements/Interface"; import { AuthenticatedInterface } from "@goauthentik/elements/Interface";
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider.js";
import "@goauthentik/elements/ak-locale-context"; import "@goauthentik/elements/ak-locale-context";
import "@goauthentik/elements/banner/EnterpriseStatusBanner"; import "@goauthentik/elements/banner/EnterpriseStatusBanner";
import "@goauthentik/elements/banner/EnterpriseStatusBanner";
import "@goauthentik/elements/banner/VersionBanner";
import "@goauthentik/elements/banner/VersionBanner"; import "@goauthentik/elements/banner/VersionBanner";
import "@goauthentik/elements/messages/MessageContainer"; import "@goauthentik/elements/messages/MessageContainer";
import "@goauthentik/elements/messages/MessageContainer"; import "@goauthentik/elements/messages/MessageContainer";
@ -25,32 +21,25 @@ import "@goauthentik/elements/router/RouterOutlet";
import "@goauthentik/elements/sidebar/Sidebar"; import "@goauthentik/elements/sidebar/Sidebar";
import "@goauthentik/elements/sidebar/SidebarItem"; import "@goauthentik/elements/sidebar/SidebarItem";
import { CSSResult, TemplateResult, css, html, nothing } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property, query, state } from "lit/decorators.js"; import { customElement, property, query, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js"; import { classMap } from "lit/directives/class-map.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css"; import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
import PFNav from "@patternfly/patternfly/components/Nav/nav.css";
import PFPage from "@patternfly/patternfly/components/Page/page.css"; import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { LicenseSummaryStatusEnum, SessionUser, UiThemeEnum } from "@goauthentik/api"; import { SessionUser, UiThemeEnum } from "@goauthentik/api";
import { import "./AdminSidebar";
AdminSidebarEnterpriseEntries,
AdminSidebarEntries,
renderSidebarItems,
} from "./AdminSidebar.js";
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === "development") {
await import("@goauthentik/esbuild-plugin-live-reload/client"); await import("@goauthentik/esbuild-plugin-live-reload/client");
} }
@customElement("ak-interface-admin") @customElement("ak-interface-admin")
export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) { export class AdminInterface extends AuthenticatedInterface {
//#region Properties
@property({ type: Boolean }) @property({ type: Boolean })
notificationDrawerOpen = getURLParam("notificationDrawerOpen", false); notificationDrawerOpen = getURLParam("notificationDrawerOpen", false);
@ -65,29 +54,12 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
@query("ak-about-modal") @query("ak-about-modal")
aboutModal?: AboutModal; aboutModal?: AboutModal;
@property({ type: Boolean, reflect: true })
public sidebarOpen: boolean;
#toggleSidebar = () => {
this.sidebarOpen = !this.sidebarOpen;
};
#sidebarMatcher: MediaQueryList;
#sidebarListener = (event: MediaQueryListEvent) => {
this.sidebarOpen = event.matches;
};
//#endregion
//#region Styles
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [ return [
PFBase, PFBase,
PFPage, PFPage,
PFButton, PFButton,
PFDrawer, PFDrawer,
PFNav,
css` css`
.pf-c-page__main, .pf-c-page__main,
.pf-c-drawer__content, .pf-c-drawer__content,
@ -95,30 +67,23 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
z-index: auto !important; z-index: auto !important;
background-color: transparent; background-color: transparent;
} }
.display-none { .display-none {
display: none; display: none;
} }
.pf-c-page { .pf-c-page {
background-color: var(--pf-c-page--BackgroundColor) !important; background-color: var(--pf-c-page--BackgroundColor) !important;
} }
/* Global page background colour */
:host([theme="dark"]) { :host([theme="dark"]) .pf-c-page {
/* Global page background colour */ --pf-c-page--BackgroundColor: var(--ak-dark-background);
.pf-c-page {
--pf-c-page--BackgroundColor: var(--ak-dark-background);
}
} }
ak-enterprise-status,
ak-page-navbar { ak-version-banner {
grid-area: header; grid-area: header;
} }
ak-admin-sidebar {
.ak-sidebar {
grid-area: nav; grid-area: nav;
} }
.pf-c-drawer__panel { .pf-c-drawer__panel {
z-index: var(--pf-global--ZIndex--xl); z-index: var(--pf-global--ZIndex--xl);
} }
@ -126,23 +91,10 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
]; ];
} }
//#endregion
//#region Lifecycle
constructor() { constructor() {
super(); super();
this.ws = new WebsocketClient(); this.ws = new WebsocketClient();
this.#sidebarMatcher = window.matchMedia("(min-width: 1200px)");
this.sidebarOpen = this.#sidebarMatcher.matches;
}
public connectedCallback() {
super.connectedCallback();
window.addEventListener(EVENT_SIDEBAR_TOGGLE, this.#toggleSidebar);
window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, () => { window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, () => {
this.notificationDrawerOpen = !this.notificationDrawerOpen; this.notificationDrawerOpen = !this.notificationDrawerOpen;
updateURLParams({ updateURLParams({
@ -156,14 +108,6 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
apiDrawerOpen: this.apiDrawerOpen, apiDrawerOpen: this.apiDrawerOpen,
}); });
}); });
this.#sidebarMatcher.addEventListener("change", this.#sidebarListener);
}
public disconnectedCallback(): void {
super.disconnectedCallback();
window.removeEventListener(EVENT_SIDEBAR_TOGGLE, this.#toggleSidebar);
this.#sidebarMatcher.removeEventListener("change", this.#sidebarListener);
} }
async firstUpdated(): Promise<void> { async firstUpdated(): Promise<void> {
@ -174,7 +118,6 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
this.user.user.isSuperuser || this.user.user.isSuperuser ||
// TODO: somehow add `access_admin_interface` to the API schema // TODO: somehow add `access_admin_interface` to the API schema
this.user.user.systemPermissions.includes("access_admin_interface"); this.user.user.systemPermissions.includes("access_admin_interface");
if (!canAccessAdmin && this.user.user.pk > 0) { if (!canAccessAdmin && this.user.user.pk > 0) {
window.location.assign("/if/user/"); window.location.assign("/if/user/");
} }
@ -182,14 +125,10 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
render(): TemplateResult { render(): TemplateResult {
const sidebarClasses = { const sidebarClasses = {
"pf-c-page__sidebar": true,
"pf-m-light": this.activeTheme === UiThemeEnum.Light, "pf-m-light": this.activeTheme === UiThemeEnum.Light,
"pf-m-expanded": this.sidebarOpen,
"pf-m-collapsed": !this.sidebarOpen,
}; };
const drawerOpen = this.notificationDrawerOpen || this.apiDrawerOpen; const drawerOpen = this.notificationDrawerOpen || this.apiDrawerOpen;
const drawerClasses = { const drawerClasses = {
"pf-m-expanded": drawerOpen, "pf-m-expanded": drawerOpen,
"pf-m-collapsed": !drawerOpen, "pf-m-collapsed": !drawerOpen,
@ -197,18 +136,11 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
return html` <ak-locale-context> return html` <ak-locale-context>
<div class="pf-c-page"> <div class="pf-c-page">
<ak-page-navbar> <ak-enterprise-status interface="admin"></ak-enterprise-status>
<ak-version-banner></ak-version-banner> <ak-version-banner></ak-version-banner>
<ak-enterprise-status interface="admin"></ak-enterprise-status> <ak-admin-sidebar
</ak-page-navbar> class="pf-c-page__sidebar ${classMap(sidebarClasses)}"
></ak-admin-sidebar>
<ak-sidebar class="${classMap(sidebarClasses)}">
${renderSidebarItems(AdminSidebarEntries)}
${this.licenseSummary?.status !== LicenseSummaryStatusEnum.Unlicensed
? renderSidebarItems(AdminSidebarEnterpriseEntries)
: nothing}
</ak-sidebar>
<div class="pf-c-page__drawer"> <div class="pf-c-page__drawer">
<div class="pf-c-drawer ${classMap(drawerClasses)}"> <div class="pf-c-drawer ${classMap(drawerClasses)}">
<div class="pf-c-drawer__main"> <div class="pf-c-drawer__main">

View File

@ -1,97 +1,186 @@
import { EVENT_SIDEBAR_TOGGLE } from "@goauthentik/common/constants";
import { me } from "@goauthentik/common/users";
import { AKElement } from "@goauthentik/elements/Base";
import {
CapabilitiesEnum,
WithCapabilitiesConfig,
} from "@goauthentik/elements/Interface/capabilitiesProvider";
import { WithVersion } from "@goauthentik/elements/Interface/versionProvider";
import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route"; import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
import { getRootStyle } from "@goauthentik/elements/utils/getRootStyle";
import { spread } from "@open-wc/lit-helpers"; import { spread } from "@open-wc/lit-helpers";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { TemplateResult, html, nothing } from "lit"; import { TemplateResult, html, nothing } from "lit";
import { repeat } from "lit/directives/repeat.js"; import { customElement, property, state } from "lit/decorators.js";
import { map } from "lit/directives/map.js";
// The second attribute type is of string[] to help with the 'activeWhen' control, which was import { UiThemeEnum } from "@goauthentik/api";
// commonplace and singular enough to merit its own handler. import type { SessionUser, UserSelf } from "@goauthentik/api";
type SidebarEntry = [
path: string | null,
label: string,
attributes?: Record<string, any> | string[] | null, // eslint-disable-line
children?: SidebarEntry[],
];
/** @customElement("ak-admin-sidebar")
* Recursively renders a sidebar entry. export class AkAdminSidebar extends WithCapabilitiesConfig(WithVersion(AKElement)) {
*/ @property({ type: Boolean, reflect: true })
export function renderSidebarItem([ open = true;
path,
label,
attributes,
children,
]: SidebarEntry): TemplateResult {
const properties = Array.isArray(attributes)
? { ".activeWhen": attributes }
: (attributes ?? {});
if (path) { @state()
properties.path = path; impersonation: UserSelf["username"] | null = null;
constructor() {
super();
me().then((user: SessionUser) => {
this.impersonation = user.original ? user.user.username : null;
});
this.toggleOpen = this.toggleOpen.bind(this);
this.checkWidth = this.checkWidth.bind(this);
} }
return html`<ak-sidebar-item ${spread(properties)}> // This has to be a bound method so the event listener can be removed on disconnection as
${label ? html`<span slot="label">${label}</span>` : nothing} // needed.
${children ? renderSidebarItems(children) : nothing} toggleOpen() {
</ak-sidebar-item>`; this.open = !this.open;
}
checkWidth() {
// This works just fine, but it assumes that the `--ak-sidebar--minimum-auto-width` is in
// REMs. If that changes, this code will have to be adjusted as well.
const minWidth =
parseFloat(getRootStyle("--ak-sidebar--minimum-auto-width")) *
parseFloat(getRootStyle("font-size"));
this.open = window.innerWidth >= minWidth;
}
connectedCallback() {
super.connectedCallback();
window.addEventListener(EVENT_SIDEBAR_TOGGLE, this.toggleOpen);
window.addEventListener("resize", this.checkWidth);
// After connecting to the DOM, we can now perform this check to see if the sidebar should
// be open by default.
this.checkWidth();
}
// The symmetry (☟, ☝) here is critical in that you want to start adding these handlers after
// connection, and removing them before disconnection.
disconnectedCallback() {
window.removeEventListener(EVENT_SIDEBAR_TOGGLE, this.toggleOpen);
window.removeEventListener("resize", this.checkWidth);
super.disconnectedCallback();
}
render() {
return html`
<ak-sidebar
class="pf-c-page__sidebar ${this.open ? "pf-m-expanded" : "pf-m-collapsed"} ${this
.activeTheme === UiThemeEnum.Light
? "pf-m-light"
: ""}"
>
${this.renderSidebarItems()}
</ak-sidebar>
`;
}
updated() {
// This is permissible as`:host.classList` is not one of the properties Lit uses as a
// scheduling trigger. This sort of shenanigans can trigger an loop, in that it will trigger
// a browser reflow, which may trigger some other styling the application is monitoring,
// triggering a re-render which triggers a browser reflow, ad infinitum. But we've been
// living with that since jQuery, and it's both well-known and fortunately rare.
// eslint-disable-next-line wc/no-self-class
this.classList.remove("pf-m-expanded", "pf-m-collapsed");
// eslint-disable-next-line wc/no-self-class
this.classList.add(this.open ? "pf-m-expanded" : "pf-m-collapsed");
}
renderSidebarItems(): TemplateResult {
// The second attribute type is of string[] to help with the 'activeWhen' control, which was
// commonplace and singular enough to merit its own handler.
type SidebarEntry = [
path: string | null,
label: string,
attributes?: Record<string, any> | string[] | null, // eslint-disable-line
children?: SidebarEntry[],
];
// prettier-ignore
const sidebarContent: SidebarEntry[] = [
[null, msg("Dashboards"), { "?expanded": true }, [
["/administration/overview", msg("Overview")],
["/administration/dashboard/users", msg("User Statistics")],
["/administration/system-tasks", msg("System Tasks")]]],
[null, msg("Applications"), null, [
["/core/applications", msg("Applications"), [`^/core/applications/(?<slug>${SLUG_REGEX})$`]],
["/core/providers", msg("Providers"), [`^/core/providers/(?<id>${ID_REGEX})$`]],
["/outpost/outposts", msg("Outposts")]]],
[null, msg("Events"), null, [
["/events/log", msg("Logs"), [`^/events/log/(?<id>${UUID_REGEX})$`]],
["/events/rules", msg("Notification Rules")],
["/events/transports", msg("Notification Transports")]]],
[null, msg("Customization"), null, [
["/policy/policies", msg("Policies")],
["/core/property-mappings", msg("Property Mappings")],
["/blueprints/instances", msg("Blueprints")],
["/policy/reputation", msg("Reputation scores")]]],
[null, msg("Flows and Stages"), null, [
["/flow/flows", msg("Flows"), [`^/flow/flows/(?<slug>${SLUG_REGEX})$`]],
["/flow/stages", msg("Stages")],
["/flow/stages/prompts", msg("Prompts")]]],
[null, msg("Directory"), null, [
["/identity/users", msg("Users"), [`^/identity/users/(?<id>${ID_REGEX})$`]],
["/identity/groups", msg("Groups"), [`^/identity/groups/(?<id>${UUID_REGEX})$`]],
["/identity/roles", msg("Roles"), [`^/identity/roles/(?<id>${UUID_REGEX})$`]],
["/identity/initial-permissions", msg("Initial Permissions"), [`^/identity/initial-permissions/(?<id>${ID_REGEX})$`]],
["/core/sources", msg("Federation and Social login"), [`^/core/sources/(?<slug>${SLUG_REGEX})$`]],
["/core/tokens", msg("Tokens and App passwords")],
["/flow/stages/invitations", msg("Invitations")]]],
[null, msg("System"), null, [
["/core/brands", msg("Brands")],
["/crypto/certificates", msg("Certificates")],
["/outpost/integrations", msg("Outpost Integrations")],
["/admin/settings", msg("Settings")]]],
];
// Typescript requires the type here to correctly type the recursive path
type SidebarRenderer = (_: SidebarEntry) => TemplateResult;
const renderOneSidebarItem: SidebarRenderer = ([path, label, attributes, children]) => {
const properties = Array.isArray(attributes)
? { ".activeWhen": attributes }
: (attributes ?? {});
if (path) {
properties.path = path;
}
return html`<ak-sidebar-item ${spread(properties)}>
${label ? html`<span slot="label">${label}</span>` : nothing}
${map(children, renderOneSidebarItem)}
</ak-sidebar-item>`;
};
// prettier-ignore
return html`
${map(sidebarContent, renderOneSidebarItem)}
${this.renderEnterpriseMenu()}
`;
}
renderEnterpriseMenu() {
return this.can(CapabilitiesEnum.IsEnterprise)
? html`
<ak-sidebar-item>
<span slot="label">${msg("Enterprise")}</span>
<ak-sidebar-item path="/enterprise/licenses">
<span slot="label">${msg("Licenses")}</span>
</ak-sidebar-item>
</ak-sidebar-item>
`
: nothing;
}
} }
/** declare global {
* Recursively renders a collection of sidebar entries. interface HTMLElementTagNameMap {
*/ "ak-admin-sidebar": AkAdminSidebar;
export function renderSidebarItems(entries: readonly SidebarEntry[]) { }
return repeat(entries, ([path, label]) => path || label, renderSidebarItem);
} }
// prettier-ignore
export const AdminSidebarEntries: readonly SidebarEntry[] = [
[null, msg("Dashboards"), { "?expanded": true }, [
["/administration/overview", msg("Overview")],
["/administration/dashboard/users", msg("User Statistics")],
["/administration/system-tasks", msg("System Tasks")]]
],
[null, msg("Applications"), null, [
["/core/applications", msg("Applications"), [`^/core/applications/(?<slug>${SLUG_REGEX})$`]],
["/core/providers", msg("Providers"), [`^/core/providers/(?<id>${ID_REGEX})$`]],
["/outpost/outposts", msg("Outposts")]]
],
[null, msg("Events"), null, [
["/events/log", msg("Logs"), [`^/events/log/(?<id>${UUID_REGEX})$`]],
["/events/rules", msg("Notification Rules")],
["/events/transports", msg("Notification Transports")]]
],
[null, msg("Customization"), null, [
["/policy/policies", msg("Policies")],
["/core/property-mappings", msg("Property Mappings")],
["/blueprints/instances", msg("Blueprints")],
["/policy/reputation", msg("Reputation scores")]]
],
[null, msg("Flows and Stages"), null, [
["/flow/flows", msg("Flows"), [`^/flow/flows/(?<slug>${SLUG_REGEX})$`]],
["/flow/stages", msg("Stages")],
["/flow/stages/prompts", msg("Prompts")]]
],
[null, msg("Directory"), null, [
["/identity/users", msg("Users"), [`^/identity/users/(?<id>${ID_REGEX})$`]],
["/identity/groups", msg("Groups"), [`^/identity/groups/(?<id>${UUID_REGEX})$`]],
["/identity/roles", msg("Roles"), [`^/identity/roles/(?<id>${UUID_REGEX})$`]],
["/identity/initial-permissions", msg("Initial Permissions"), [`^/identity/initial-permissions/(?<id>${ID_REGEX})$`]],
["/core/sources", msg("Federation and Social login"), [`^/core/sources/(?<slug>${SLUG_REGEX})$`]],
["/core/tokens", msg("Tokens and App passwords")],
["/flow/stages/invitations", msg("Invitations")]]
],
[null, msg("System"), null, [
["/core/brands", msg("Brands")],
["/crypto/certificates", msg("Certificates")],
["/outpost/integrations", msg("Outpost Integrations")],
["/admin/settings", msg("Settings")]]
],
];
// prettier-ignore
export const AdminSidebarEnterpriseEntries: readonly SidebarEntry[] = [
[null, msg("Enterprise"), null, [
["/enterprise/licenses", msg("Licenses"), null]
],
]]

View File

@ -0,0 +1,5 @@
import { AdminInterface } from "./AdminInterface";
import "./AdminInterface";
export { AdminInterface };
export default AdminInterface;

View File

@ -94,13 +94,10 @@ export class AdminOverviewPage extends AdminOverviewBase {
} }
render(): TemplateResult { render(): TemplateResult {
const username = this.user?.user.name || this.user?.user.username; const name = this.user?.user.name ?? this.user?.user.username;
return html` <ak-page-header return html`<ak-page-header description=${msg("General system status")} ?hasIcon=${false}>
header=${msg(str`Welcome, ${username || ""}.`)} <span slot="header"> ${msg(str`Welcome, ${name || ""}.`)} </span>
description=${msg("General system status")}
?hasIcon=${false}
>
</ak-page-header> </ak-page-header>
<section class="pf-c-page__main-section"> <section class="pf-c-page__main-section">
<div class="pf-l-grid pf-m-gutter"> <div class="pf-l-grid pf-m-gutter">

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-number-input"; import "@goauthentik/components/ak-number-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";
@ -183,14 +184,20 @@ export class AdminSettingsForm extends Form<SettingsRequest> {
label=${msg("Reputation: lower limit")} label=${msg("Reputation: lower limit")}
required required
name="reputationLowerLimit" name="reputationLowerLimit"
value="${this._settings?.reputationLowerLimit ?? DEFAULT_REPUTATION_LOWER_LIMIT}" value="${first(
this._settings?.reputationLowerLimit,
DEFAULT_REPUTATION_LOWER_LIMIT,
)}"
help=${msg("Reputation cannot decrease lower than this value. Zero or negative.")} help=${msg("Reputation cannot decrease lower than this value. Zero or negative.")}
></ak-number-input> ></ak-number-input>
<ak-number-input <ak-number-input
label=${msg("Reputation: upper limit")} label=${msg("Reputation: upper limit")}
required required
name="reputationUpperLimit" name="reputationUpperLimit"
value="${this._settings?.reputationUpperLimit ?? DEFAULT_REPUTATION_UPPER_LIMIT}" value="${first(
this._settings?.reputationUpperLimit,
DEFAULT_REPUTATION_UPPER_LIMIT,
)}"
help=${msg("Reputation cannot increase higher than this value. Zero or positive.")} help=${msg("Reputation cannot increase higher than this value. Zero or positive.")}
></ak-number-input> ></ak-number-input>
<ak-form-element-horizontal label=${msg("Footer links")} name="footerLinks"> <ak-form-element-horizontal label=${msg("Footer links")} name="footerLinks">
@ -250,7 +257,7 @@ export class AdminSettingsForm extends Form<SettingsRequest> {
label=${msg("Default token length")} label=${msg("Default token length")}
required required
name="defaultTokenLength" name="defaultTokenLength"
value="${this._settings?.defaultTokenLength ?? 60}" value="${first(this._settings?.defaultTokenLength, 60)}"
help=${msg("Default length of generated tokens")} help=${msg("Default length of generated tokens")}
></ak-number-input> ></ak-number-input>
`; `;

View File

@ -83,10 +83,13 @@ export class AdminSettingsPage extends AKElement {
} }
render() { render() {
if (!this.settings) return nothing; if (!this.settings) {
return nothing;
}
return html` return html`
<ak-page-header icon="fa fa-cog" header="${msg("System settings")}"> </ak-page-header> <ak-page-header icon="fa fa-cog" header="" description="">
<span slot="header"> ${msg("System settings")} </span>
</ak-page-header>
<section class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter"> <section class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter">
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__body"> <div class="pf-c-card__body">

View File

@ -1,6 +1,7 @@
import "@goauthentik/admin/applications/ProviderSelectModal"; import "@goauthentik/admin/applications/ProviderSelectModal";
import { iconHelperText } from "@goauthentik/admin/helperText"; import { iconHelperText } from "@goauthentik/admin/helperText";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
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-switch-input"; import "@goauthentik/components/ak-switch-input";
@ -193,7 +194,7 @@ export class ApplicationForm extends WithCapabilitiesConfig(ModelForm<Applicatio
></ak-text-input> ></ak-text-input>
<ak-switch-input <ak-switch-input
name="openInNewTab" name="openInNewTab"
?checked=${this.instance?.openInNewTab ?? false} ?checked=${first(this.instance?.openInNewTab, false)}
label=${msg("Open in new tab")} label=${msg("Open in new tab")}
help=${msg( help=${msg(
"If checked, the launch URL will open in a new browser tab or window from the user's application library.", "If checked, the launch URL will open in a new browser tab or window from the user's application library.",
@ -220,7 +221,7 @@ export class ApplicationForm extends WithCapabilitiesConfig(ModelForm<Applicatio
: html` <ak-text-input : html` <ak-text-input
label=${msg("Icon")} label=${msg("Icon")}
name="metaIcon" name="metaIcon"
value=${this.instance?.metaIcon ?? ""} value=${first(this.instance?.metaIcon, "")}
help=${iconHelperText} help=${iconHelperText}
> >
</ak-text-input>`} </ak-text-input>`}

View File

@ -113,7 +113,8 @@ export class ApplicationViewPage extends AKElement {
renderApp(): TemplateResult { renderApp(): TemplateResult {
if (!this.application) { if (!this.application) {
return html`<ak-empty-state loading header=${msg("Loading")}> </ak-empty-state>`; return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
</ak-empty-state>`;
} }
return html`<ak-tabs> return html`<ak-tabs>
${this.missingOutpost ${this.missingOutpost

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -59,7 +60,7 @@ export class ApplicationEntitlementForm extends ModelForm<ApplicationEntitlement
return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name"> return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${this.instance?.name ?? ""}" value="${first(this.instance?.name, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -71,7 +72,7 @@ export class ApplicationEntitlementForm extends ModelForm<ApplicationEntitlement
> >
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.attributes ?? {})}" value="${YAML.stringify(first(this.instance?.attributes, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,6 +1,7 @@
import { policyOptions } from "@goauthentik/admin/applications/PolicyOptions.js"; import { policyOptions } from "@goauthentik/admin/applications/PolicyOptions.js";
import { ApplicationWizardStep } from "@goauthentik/admin/applications/wizard/ApplicationWizardStep.js"; import { ApplicationWizardStep } from "@goauthentik/admin/applications/wizard/ApplicationWizardStep.js";
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js"; import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { isSlug } from "@goauthentik/common/utils.js";
import { camelToSnake } from "@goauthentik/common/utils.js"; import { camelToSnake } from "@goauthentik/common/utils.js";
import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-slug-input"; import "@goauthentik/components/ak-slug-input";
@ -10,7 +11,6 @@ import { type NavigableButton, type WizardButton } from "@goauthentik/components
import { type KeyUnknown } from "@goauthentik/elements/forms/Form"; import { type KeyUnknown } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { isSlug } from "@goauthentik/elements/router/utils.js";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { html } from "lit"; import { html } from "lit";

View File

@ -1,5 +1,6 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { docLink } from "@goauthentik/common/global"; import { docLink } from "@goauthentik/common/global";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-toggle-group"; import "@goauthentik/components/ak-toggle-group";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
@ -79,7 +80,7 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -183,7 +184,7 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
<ak-form-element-horizontal label=${msg("Context")} name="context"> <ak-form-element-horizontal label=${msg("Context")} name="context">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.context ?? {})}" value="${YAML.stringify(first(this.instance?.context, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,13 +1,14 @@
import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-crypto-certificate-search";
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { DefaultBrand } from "@goauthentik/common/ui/config"; import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
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";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand";
import YAML from "yaml"; import YAML from "yaml";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
@ -53,7 +54,7 @@ export class BrandForm extends ModelForm<Brand, string> {
return html` <ak-form-element-horizontal label=${msg("Domain")} required name="domain"> return html` <ak-form-element-horizontal label=${msg("Domain")} required name="domain">
<input <input
type="text" type="text"
value="${this.instance?.domain ?? window.location.host}" value="${first(this.instance?.domain, window.location.host)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -71,7 +72,7 @@ export class BrandForm extends ModelForm<Brand, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?._default ?? false} ?checked=${first(this.instance?._default, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -91,7 +92,10 @@ export class BrandForm extends ModelForm<Brand, string> {
<ak-form-element-horizontal label=${msg("Title")} required name="brandingTitle"> <ak-form-element-horizontal label=${msg("Title")} required name="brandingTitle">
<input <input
type="text" type="text"
value="${this.instance?.brandingTitle ?? DefaultBrand.brandingTitle}" value="${first(
this.instance?.brandingTitle,
DefaultBrand.brandingTitle,
)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -102,7 +106,7 @@ export class BrandForm extends ModelForm<Brand, string> {
<ak-form-element-horizontal label=${msg("Logo")} required name="brandingLogo"> <ak-form-element-horizontal label=${msg("Logo")} required name="brandingLogo">
<input <input
type="text" type="text"
value="${this.instance?.brandingLogo ?? DefaultBrand.brandingLogo}" value="${first(this.instance?.brandingLogo, DefaultBrand.brandingLogo)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -119,8 +123,10 @@ export class BrandForm extends ModelForm<Brand, string> {
> >
<input <input
type="text" type="text"
value="${this.instance?.brandingFavicon ?? value="${first(
DefaultBrand.brandingFavicon}" this.instance?.brandingFavicon,
DefaultBrand.brandingFavicon,
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -137,8 +143,10 @@ export class BrandForm extends ModelForm<Brand, string> {
> >
<input <input
type="text" type="text"
value="${this.instance?.brandingDefaultFlowBackground ?? value="${first(
"/static/dist/assets/images/flow_background.jpg"}" this.instance?.brandingDefaultFlowBackground,
"/static/dist/assets/images/flow_background.jpg",
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -157,8 +165,10 @@ export class BrandForm extends ModelForm<Brand, string> {
> >
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.CSS} mode=${CodeMirrorMode.CSS}
value="${this.instance?.brandingCustomCss ?? value="${first(
DefaultBrand.brandingCustomCss}" this.instance?.brandingCustomCss,
DefaultBrand.brandingCustomCss,
)}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -307,7 +317,7 @@ export class BrandForm extends ModelForm<Brand, string> {
<ak-form-element-horizontal label=${msg("Attributes")} name="attributes"> <ak-form-element-horizontal label=${msg("Attributes")} name="attributes">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.attributes ?? {})}" value="${YAML.stringify(first(this.instance?.attributes, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
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";
@ -184,7 +185,7 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.sendOnce ?? false} ?checked=${first(this.instance?.sendOnce, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,6 +1,7 @@
import { DesignationToLabel, LayoutToLabel } from "@goauthentik/admin/flows/utils"; import { DesignationToLabel, LayoutToLabel } from "@goauthentik/admin/flows/utils";
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 { first } from "@goauthentik/common/utils";
import { import {
CapabilitiesEnum, CapabilitiesEnum,
WithCapabilitiesConfig, WithCapabilitiesConfig,
@ -226,7 +227,7 @@ export class FlowForm extends WithCapabilitiesConfig(ModelForm<Flow, string>) {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.compatibilityMode ?? false} ?checked=${first(this.instance?.compatibilityMode, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -406,7 +407,7 @@ export class FlowForm extends WithCapabilitiesConfig(ModelForm<Flow, string>) {
> >
<input <input
type="text" type="text"
value="${this.instance?.background ?? ""}" value="${first(this.instance?.background, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,5 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { groupBy } from "@goauthentik/common/utils"; import { first, groupBy } from "@goauthentik/common/utils";
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";
@ -123,7 +123,7 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
<ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order"> <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
<input <input
type="number" type="number"
value="${this.instance?.order ?? this.defaultOrder}" value="${first(this.instance?.order, this.defaultOrder)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -133,7 +133,7 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.evaluateOnPlan ?? false} ?checked=${first(this.instance?.evaluateOnPlan, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -151,7 +151,7 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.reEvaluatePolicies ?? true} ?checked=${first(this.instance?.reEvaluatePolicies, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import "@goauthentik/admin/groups/MemberSelectModal"; import "@goauthentik/admin/groups/MemberSelectModal";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider";
@ -76,7 +77,7 @@ export class GroupForm extends ModelForm<Group, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.isSuperuser ?? false} ?checked=${first(this.instance?.isSuperuser, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -149,7 +150,7 @@ export class GroupForm extends ModelForm<Group, string> {
> >
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.attributes ?? {})}" value="${YAML.stringify(first(this.instance?.attributes, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,5 +1,6 @@
import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-crypto-certificate-search";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
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/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
@ -52,7 +53,7 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.local ?? false} ?checked=${first(this.instance?.local, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -56,7 +57,7 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.local ?? false} ?checked=${first(this.instance?.local, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -74,7 +75,7 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
<ak-form-element-horizontal label=${msg("Kubeconfig")} name="kubeconfig"> <ak-form-element-horizontal label=${msg("Kubeconfig")} name="kubeconfig">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.kubeconfig ?? {})}" value="${YAML.stringify(first(this.instance?.kubeconfig, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -86,7 +87,7 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.verifySsl ?? true} ?checked=${first(this.instance?.verifySsl, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -3,7 +3,7 @@ import {
PolicyBindingCheckTargetToLabel, PolicyBindingCheckTargetToLabel,
} from "@goauthentik/admin/policies/utils"; } from "@goauthentik/admin/policies/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { groupBy } from "@goauthentik/common/utils"; import { first, groupBy } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-toggle-group"; import "@goauthentik/components/ak-toggle-group";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
@ -274,7 +274,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -289,7 +289,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.negate ?? false} ?checked=${first(this.instance?.negate, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -305,7 +305,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order"> <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
<input <input
type="number" type="number"
value="${this.instance?.order ?? this.defaultOrder}" value="${first(this.instance?.order, this.defaultOrder)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -313,7 +313,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<ak-form-element-horizontal label=${msg("Timeout")} ?required=${true} name="timeout"> <ak-form-element-horizontal label=${msg("Timeout")} ?required=${true} name="timeout">
<input <input
type="number" type="number"
value="${this.instance?.timeout ?? 30}" value="${first(this.instance?.timeout, 30)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-status-label"; import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
@ -124,7 +125,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
<ak-form-element-horizontal label=${msg("Context")} name="context"> <ak-form-element-horizontal label=${msg("Context")} name="context">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value=${YAML.stringify(this.request?.context ?? {})} value=${YAML.stringify(first(this.request?.context, {}))}
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -50,7 +51,7 @@ export class DummyPolicyForm extends BasePolicyForm<DummyPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -73,7 +74,7 @@ export class DummyPolicyForm extends BasePolicyForm<DummyPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.result ?? false} ?checked=${first(this.instance?.result, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -90,7 +91,7 @@ export class DummyPolicyForm extends BasePolicyForm<DummyPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.waitMin ?? 1}" value="${first(this.instance?.waitMin, 1)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -107,7 +108,7 @@ export class DummyPolicyForm extends BasePolicyForm<DummyPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.waitMax ?? 5}" value="${first(this.instance?.waitMax, 5)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
@ -62,7 +63,7 @@ export class EventMatcherPolicyForm extends BasePolicyForm<EventMatcherPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -50,7 +51,7 @@ export class PasswordExpiryPolicyForm extends BasePolicyForm<PasswordExpiryPolic
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -85,7 +86,7 @@ export class PasswordExpiryPolicyForm extends BasePolicyForm<PasswordExpiryPolic
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.denyOnly ?? false} ?checked=${first(this.instance?.denyOnly, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,6 +1,7 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { docLink } from "@goauthentik/common/global"; import { docLink } from "@goauthentik/common/global";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -53,7 +54,7 @@ export class ExpressionPolicyForm extends BasePolicyForm<ExpressionPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select"; import "@goauthentik/elements/ak-dual-select";
import { DataProvision, DualSelectPair } from "@goauthentik/elements/ak-dual-select/types"; import { DataProvision, DualSelectPair } from "@goauthentik/elements/ak-dual-select/types";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -111,7 +112,7 @@ export class GeoIPPolicyForm extends BasePolicyForm<GeoIPPolicy> {
<input <input
type="number" type="number"
min="1" min="1"
value="${this.instance?.historyMaxDistanceKm ?? 100}" value="${first(this.instance?.historyMaxDistanceKm, 100)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -127,7 +128,7 @@ export class GeoIPPolicyForm extends BasePolicyForm<GeoIPPolicy> {
<input <input
type="number" type="number"
min="1" min="1"
value="${this.instance?.distanceToleranceKm ?? 50}" value="${first(this.instance?.distanceToleranceKm, 50)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -141,7 +142,7 @@ export class GeoIPPolicyForm extends BasePolicyForm<GeoIPPolicy> {
<input <input
type="number" type="number"
min="1" min="1"
value="${this.instance?.historyLoginCount ?? 5}" value="${first(this.instance?.historyLoginCount, 5)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -177,7 +178,7 @@ export class GeoIPPolicyForm extends BasePolicyForm<GeoIPPolicy> {
<input <input
type="number" type="number"
min="1" min="1"
value="${this.instance?.impossibleToleranceKm ?? 50}" value="${first(this.instance?.impossibleToleranceKm, 50)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -55,7 +56,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.lengthMin ?? 10}" value="${first(this.instance?.lengthMin, 10)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -67,7 +68,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.amountUppercase ?? 2}" value="${first(this.instance?.amountUppercase, 2)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -79,7 +80,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.amountLowercase ?? 2}" value="${first(this.instance?.amountLowercase, 2)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -91,7 +92,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.amountDigits ?? 2}" value="${first(this.instance?.amountDigits, 2)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -103,7 +104,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.amountSymbols ?? 2}" value="${first(this.instance?.amountSymbols, 2)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -153,7 +154,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.hibpAllowedCount ?? 0}" value="${first(this.instance?.hibpAllowedCount, 0)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -178,7 +179,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.zxcvbnScoreThreshold ?? 0}" value="${first(this.instance?.zxcvbnScoreThreshold, 0)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -235,7 +236,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -271,7 +272,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkStaticRules ?? true} ?checked=${first(this.instance?.checkStaticRules, true)}
@change=${(ev: Event) => { @change=${(ev: Event) => {
const el = ev.target as HTMLInputElement; const el = ev.target as HTMLInputElement;
this.showStatic = el.checked; this.showStatic = el.checked;
@ -290,7 +291,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkHaveIBeenPwned ?? true} ?checked=${first(this.instance?.checkHaveIBeenPwned, true)}
@change=${(ev: Event) => { @change=${(ev: Event) => {
const el = ev.target as HTMLInputElement; const el = ev.target as HTMLInputElement;
this.showHIBP = el.checked; this.showHIBP = el.checked;
@ -315,7 +316,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkZxcvbn ?? true} ?checked=${first(this.instance?.checkZxcvbn, true)}
@change=${(ev: Event) => { @change=${(ev: Event) => {
const el = ev.target as HTMLInputElement; const el = ev.target as HTMLInputElement;
this.showZxcvbn = el.checked; this.showZxcvbn = el.checked;

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -60,7 +61,7 @@ doesn't pass when either or both of the selected options are equal or above the
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -83,7 +84,7 @@ doesn't pass when either or both of the selected options are equal or above the
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkIp ?? true} ?checked=${first(this.instance?.checkIp, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -98,7 +99,7 @@ doesn't pass when either or both of the selected options are equal or above the
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkUsername ?? false} ?checked=${first(this.instance?.checkUsername, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -50,7 +51,7 @@ export class UniquePasswordPolicyForm extends BasePolicyForm<UniquePasswordPolic
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -87,7 +88,7 @@ export class UniquePasswordPolicyForm extends BasePolicyForm<UniquePasswordPolic
> >
<input <input
type="number" type="number"
value="${this.instance?.numHistoricalPasswords ?? 1}" value="${first(this.instance?.numHistoricalPasswords, 1)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import { Form } from "@goauthentik/elements/forms/Form"; import { Form } from "@goauthentik/elements/forms/Form";
@ -180,7 +181,7 @@ export class PolicyTestForm extends Form<PropertyMappingTestRequest> {
<ak-form-element-horizontal label=${msg("Context")} name="context"> <ak-form-element-horizontal label=${msg("Context")} name="context">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value=${YAML.stringify(this.request?.context ?? {})} value=${YAML.stringify(first(this.request?.context, {}))}
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${this.renderExampleButtons()}</p> <p class="pf-c-form__helper-text">${this.renderExampleButtons()}</p>

View File

@ -42,7 +42,7 @@ export class ProviderViewPage extends AKElement {
renderProvider(): TemplateResult { renderProvider(): TemplateResult {
if (!this.provider) { if (!this.provider) {
return html`<ak-empty-state loading ?fullHeight=${true}></ak-empty-state>`; return html`<ak-empty-state ?loading=${true} ?fullHeight=${true}></ak-empty-state>`;
} }
switch (this.provider?.component) { switch (this.provider?.component) {
case "ak-provider-saml-form": case "ak-provider-saml-form":

View File

@ -4,6 +4,7 @@ import {
propertyMappingsSelector, propertyMappingsSelector,
} from "@goauthentik/admin/providers/google_workspace/GoogleWorkspaceProviderFormHelpers.js"; } from "@goauthentik/admin/providers/google_workspace/GoogleWorkspaceProviderFormHelpers.js";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
@ -67,7 +68,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
> >
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.JavaScript} mode=${CodeMirrorMode.JavaScript}
.value="${this.instance?.credentials ?? {}}" .value="${first(this.instance?.credentials, {})}"
></ak-codemirror> ></ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${msg("Google Cloud credentials file.")} ${msg("Google Cloud credentials file.")}
@ -80,7 +81,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
> >
<input <input
type="email" type="email"
value="${this.instance?.delegatedSubject ?? ""}" value="${first(this.instance?.delegatedSubject, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -97,7 +98,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
> >
<input <input
type="text" type="text"
value="${this.instance?.defaultGroupEmailDomain ?? ""}" value="${first(this.instance?.defaultGroupEmailDomain, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -165,7 +166,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.dryRun ?? false} ?checked=${first(this.instance?.dryRun, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -190,7 +191,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.excludeUsersServiceAccount ?? true} ?checked=${first(this.instance?.excludeUsersServiceAccount, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -4,6 +4,7 @@ import {
propertyMappingsSelector, propertyMappingsSelector,
} from "@goauthentik/admin/providers/microsoft_entra/MicrosoftEntraProviderFormHelpers.js"; } from "@goauthentik/admin/providers/microsoft_entra/MicrosoftEntraProviderFormHelpers.js";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -65,7 +66,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
> >
<input <input
type="text" type="text"
value="${this.instance?.clientId ?? ""}" value="${first(this.instance?.clientId, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -80,7 +81,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
> >
<input <input
type="text" type="text"
value="${this.instance?.clientSecret ?? ""}" value="${first(this.instance?.clientSecret, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -95,7 +96,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
> >
<input <input
type="text" type="text"
value="${this.instance?.tenantId ?? ""}" value="${first(this.instance?.tenantId, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -154,7 +155,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.dryRun ?? false} ?checked=${first(this.instance?.dryRun, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -179,7 +180,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.excludeUsersServiceAccount ?? true} ?checked=${first(this.instance?.excludeUsersServiceAccount, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -4,7 +4,7 @@ import {
IRedirectURIInput, IRedirectURIInput,
akOAuthRedirectURIInput, akOAuthRedirectURIInput,
} from "@goauthentik/admin/providers/oauth2/OAuth2ProviderRedirectURI"; } from "@goauthentik/admin/providers/oauth2/OAuth2ProviderRedirectURI";
import { ascii_letters, digits, randomString } from "@goauthentik/common/utils"; import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-radio-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";
@ -161,7 +161,7 @@ export function renderForm(
<ak-text-input <ak-text-input
name="clientId" name="clientId"
label=${msg("Client ID")} label=${msg("Client ID")}
value="${provider?.clientId ?? randomString(40, ascii_letters + digits)}" value="${first(provider?.clientId, randomString(40, ascii_letters + digits))}"
required required
inputHint="code" inputHint="code"
> >
@ -169,7 +169,10 @@ export function renderForm(
<ak-text-input <ak-text-input
name="clientSecret" name="clientSecret"
label=${msg("Client Secret")} label=${msg("Client Secret")}
value="${provider?.clientSecret ?? randomString(128, ascii_letters + digits)}" value="${first(
provider?.clientSecret,
randomString(128, ascii_letters + digits),
)}"
inputHint="code" inputHint="code"
?hidden=${!showClientSecret} ?hidden=${!showClientSecret}
> >
@ -254,7 +257,7 @@ export function renderForm(
label=${msg("Access code validity")} label=${msg("Access code validity")}
inputHint="code" inputHint="code"
required required
value="${provider?.accessCodeValidity ?? "minutes=1"}" value="${first(provider?.accessCodeValidity, "minutes=1")}"
.bighelp=${html`<p class="pf-c-form__helper-text"> .bighelp=${html`<p class="pf-c-form__helper-text">
${msg("Configure how long access codes are valid for.")} ${msg("Configure how long access codes are valid for.")}
</p> </p>
@ -264,7 +267,7 @@ export function renderForm(
<ak-text-input <ak-text-input
name="accessTokenValidity" name="accessTokenValidity"
label=${msg("Access Token validity")} label=${msg("Access Token validity")}
value="${provider?.accessTokenValidity ?? "minutes=5"}" value="${first(provider?.accessTokenValidity, "minutes=5")}"
inputHint="code" inputHint="code"
required required
.bighelp=${html` <p class="pf-c-form__helper-text"> .bighelp=${html` <p class="pf-c-form__helper-text">
@ -277,7 +280,7 @@ export function renderForm(
<ak-text-input <ak-text-input
name="refreshTokenValidity" name="refreshTokenValidity"
label=${msg("Refresh Token validity")} label=${msg("Refresh Token validity")}
value="${provider?.refreshTokenValidity ?? "days=30"}" value="${first(provider?.refreshTokenValidity, "days=30")}"
inputHint="code" inputHint="code"
?required=${true} ?required=${true}
.bighelp=${html` <p class="pf-c-form__helper-text"> .bighelp=${html` <p class="pf-c-form__helper-text">
@ -314,7 +317,7 @@ export function renderForm(
<ak-switch-input <ak-switch-input
name="includeClaimsInIdToken" name="includeClaimsInIdToken"
label=${msg("Include claims in id_token")} label=${msg("Include claims in id_token")}
?checked=${provider?.includeClaimsInIdToken ?? true} ?checked=${first(provider?.includeClaimsInIdToken, true)}
help=${msg( help=${msg(
"Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.", "Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.",
)} )}

View File

@ -432,7 +432,7 @@ export class OAuth2ProviderViewPage extends AKElement {
<div class="pf-c-card__body"> <div class="pf-c-card__body">
${this.preview ${this.preview
? html`<pre>${JSON.stringify(this.preview?.preview, null, 4)}</pre>` ? html`<pre>${JSON.stringify(this.preview?.preview, null, 4)}</pre>`
: html` <ak-empty-state loading></ak-empty-state> `} : html` <ak-empty-state ?loading=${true}></ak-empty-state> `}
</div> </div>
</div> </div>
</div>`; </div>`;

View File

@ -3,6 +3,7 @@ import "@goauthentik/admin/providers/proxy/ProxyProviderForm";
import "@goauthentik/admin/rbac/ObjectPermissionsPage"; import "@goauthentik/admin/rbac/ObjectPermissionsPage";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { EVENT_REFRESH } from "@goauthentik/common/constants";
import { convertToSlug } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-status-label"; import "@goauthentik/components/ak-status-label";
import "@goauthentik/components/events/ObjectChangelog"; import "@goauthentik/components/events/ObjectChangelog";
import MDCaddyStandalone from "@goauthentik/docs/add-secure-apps/providers/proxy/_caddy_standalone.md"; import MDCaddyStandalone from "@goauthentik/docs/add-secure-apps/providers/proxy/_caddy_standalone.md";
@ -21,7 +22,6 @@ import type { Replacer } from "@goauthentik/elements/ak-mdx";
import "@goauthentik/elements/buttons/ModalButton"; import "@goauthentik/elements/buttons/ModalButton";
import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/buttons/SpinnerButton";
import { getURLParam } from "@goauthentik/elements/router/RouteMatch"; import { getURLParam } from "@goauthentik/elements/router/RouteMatch";
import { formatSlug } from "@goauthentik/elements/router/utils.js";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit"; import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit";
@ -183,7 +183,7 @@ export class ProxyProviderViewPage extends AKElement {
return html`<ak-tabs pageIdentifier="proxy-setup"> return html`<ak-tabs pageIdentifier="proxy-setup">
${servers.map((server) => { ${servers.map((server) => {
return html`<section return html`<section
slot="page-${formatSlug(server.label)}" slot="page-${convertToSlug(server.label)}"
data-tab-title="${server.label}" data-tab-title="${server.label}"
class="pf-c-page__main-section pf-m-no-padding-mobile ak-markdown-section" class="pf-c-page__main-section pf-m-no-padding-mobile ak-markdown-section"
> >

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-radio-input";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
@ -98,7 +99,7 @@ export class EndpointForm extends ModelForm<Endpoint, string> {
> >
<input <input
type="number" type="number"
value="${this.instance?.maximumConnections ?? 1}" value="${first(this.instance?.maximumConnections, 1)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -122,7 +123,7 @@ export class EndpointForm extends ModelForm<Endpoint, string> {
<ak-form-element-horizontal label=${msg("Settings")} name="settings"> <ak-form-element-horizontal label=${msg("Settings")} name="settings">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value="${YAML.stringify(this.instance?.settings ?? {})}" value="${YAML.stringify(first(this.instance?.settings, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${msg("Connection settings.")}</p> <p class="pf-c-form__helper-text">${msg("Connection settings.")}</p>

View File

@ -1,6 +1,7 @@
import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-crypto-certificate-search";
import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -81,7 +82,7 @@ export class RACProviderFormPage extends ModelForm<RACProvider, number> {
> >
<input <input
type="text" type="text"
value="${this.instance?.connectionExpiry ?? "hours=8"}" value="${first(this.instance?.connectionExpiry, "hours=8")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -99,7 +100,7 @@ export class RACProviderFormPage extends ModelForm<RACProvider, number> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.deleteTokenOnDisconnect ?? false} ?checked=${first(this.instance?.deleteTokenOnDisconnect, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -134,7 +135,7 @@ export class RACProviderFormPage extends ModelForm<RACProvider, number> {
<ak-form-element-horizontal label=${msg("Settings")} name="settings"> <ak-form-element-horizontal label=${msg("Settings")} name="settings">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value="${YAML.stringify(this.instance?.settings ?? {})}" value="${YAML.stringify(first(this.instance?.settings, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${msg("Connection settings.")}</p> <p class="pf-c-form__helper-text">${msg("Connection settings.")}</p>

View File

@ -1,6 +1,6 @@
import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search";
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import { ascii_letters, digits, randomString } from "@goauthentik/common/utils"; import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
@ -78,14 +78,17 @@ export function renderForm(
name="sharedSecret" name="sharedSecret"
label=${msg("Shared secret")} label=${msg("Shared secret")}
.errorMessages=${errors?.sharedSecret ?? []} .errorMessages=${errors?.sharedSecret ?? []}
value=${provider?.sharedSecret ?? randomString(128, ascii_letters + digits)} value=${first(
provider?.sharedSecret,
randomString(128, ascii_letters + digits),
)}
required required
inputHint="code" inputHint="code"
></ak-text-input> ></ak-text-input>
<ak-text-input <ak-text-input
name="clientNetworks" name="clientNetworks"
label=${msg("Client Networks")} label=${msg("Client Networks")}
value=${provider?.clientNetworks ?? "0.0.0.0/0, ::/0"} value=${first(provider?.clientNetworks, "0.0.0.0/0, ::/0")}
.errorMessages=${errors?.clientNetworks ?? []} .errorMessages=${errors?.clientNetworks ?? []}
required required
help=${clientNetworksHelp} help=${clientNetworksHelp}

View File

@ -502,7 +502,7 @@ export class SAMLProviderViewPage extends AKElement {
renderTabPreview(): TemplateResult { renderTabPreview(): TemplateResult {
if (!this.preview) { if (!this.preview) {
return html`<ak-empty-state loading></ak-empty-state>`; return html`<ak-empty-state ?loading=${true}></ak-empty-state>`;
} }
return html` <div return html` <div
class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter" class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter"

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -36,7 +37,7 @@ export function renderForm(provider?: Partial<SCIMProvider>, errors: ValidationE
<ak-text-input <ak-text-input
name="url" name="url"
label=${msg("URL")} label=${msg("URL")}
value="${provider?.url ?? ""}" value="${first(provider?.url, "")}"
.errorMessages=${errors?.url ?? []} .errorMessages=${errors?.url ?? []}
required required
help=${msg("SCIM base url, usually ends in /v2.")} help=${msg("SCIM base url, usually ends in /v2.")}
@ -95,7 +96,7 @@ export function renderForm(provider?: Partial<SCIMProvider>, errors: ValidationE
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${provider?.dryRun ?? false} ?checked=${first(provider?.dryRun, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -118,7 +119,7 @@ export function renderForm(provider?: Partial<SCIMProvider>, errors: ValidationE
<ak-switch-input <ak-switch-input
name="excludeUsersServiceAccount" name="excludeUsersServiceAccount"
label=${msg("Exclude service accounts")} label=${msg("Exclude service accounts")}
?checked=${provider?.excludeUsersServiceAccount ?? true} ?checked=${first(provider?.excludeUsersServiceAccount, true)}
> >
</ak-switch-input> </ak-switch-input>

Some files were not shown because too many files have changed in this diff Show More