Compare commits

..

13 Commits

Author SHA1 Message Date
dff82e05b9 format
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-16 12:30:35 +02:00
820046cf22 web: bump the goauthentik group across 5 directories with 1 update
Bumps the goauthentik group with 1 update in the /packages/docusaurus-config directory: @goauthentik/prettier-config.
Bumps the goauthentik group with 1 update in the /packages/eslint-config directory: @goauthentik/prettier-config.
Bumps the goauthentik group with 1 update in the /web directory: @goauthentik/prettier-config.
Bumps the goauthentik group with 1 update in the /web/packages/core directory: @goauthentik/prettier-config.
Bumps the goauthentik group with 1 update in the /web/packages/esbuild-plugin-live-reload directory: @goauthentik/prettier-config.


Updates `@goauthentik/prettier-config` from 1.0.5 to 2.0.0

Updates `@goauthentik/prettier-config` from 1.0.5 to 2.0.0

Updates `@goauthentik/prettier-config` from 1.0.5 to 2.0.0

Updates `@goauthentik/prettier-config` from 1.0.5 to 2.0.0

Updates `@goauthentik/prettier-config` from 1.0.5 to 2.0.0

---
updated-dependencies:
- dependency-name: "@goauthentik/prettier-config"
  dependency-version: 2.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: goauthentik
- dependency-name: "@goauthentik/prettier-config"
  dependency-version: 2.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: goauthentik
- dependency-name: "@goauthentik/prettier-config"
  dependency-version: 2.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: goauthentik
- dependency-name: "@goauthentik/prettier-config"
  dependency-version: 2.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: goauthentik
- dependency-name: "@goauthentik/prettier-config"
  dependency-version: 2.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: goauthentik
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-16 04:31:14 +00:00
bce70a1796 website/integrations: change nextcloud scope name to avoid confusion (#15050)
changed "profile" to "nextcloud"

Signed-off-by: Marlin <77961876+Keksmo@users.noreply.github.com>
2025-06-16 03:10:53 +02:00
e86c40a00c web/flow: cleanup WebAuthn helper functions (#14460)
* pass #1

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* pass #2

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add polyfill

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-16 02:39:50 +02:00
20e07486ee web/elements: fix typo in localeComparator (#15054)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-16 01:37:38 +02:00
0cb7cf2c96 stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#15049)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-06-15 23:54:50 +02:00
07736a90b2 translate: Updates for file locale/en/LC_MESSAGES/django.po in es (#15047)
* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

* Translate locale/en/LC_MESSAGES/django.po in es

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'es'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-06-15 22:48:33 +02:00
ec28a86259 core, web: update translations (#15048)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-06-15 22:48:21 +02:00
260800c60b blueprints: add section support for organisation (#15045)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-15 20:49:21 +02:00
ee4780394d core, web: update translations (#15043)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-06-14 02:44:35 +02:00
23b746941f web/admin: adopt ak-hidden-text (#15042)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-14 02:22:14 +02:00
3c2ce40afd web/admin: Text and Textarea Fields that "hide" their contents until prompted (#15024)
* web: Add InvalidationFlow to Radius Provider dialogues

## What

- Bugfix: adds the InvalidationFlow to the Radius Provider dialogues
  - Repairs: `{"invalidation_flow":["This field is required."]}` message, which was *not* propagated
    to the Notification.
- Nitpick: Pretties `?foo=${true}` expressions: `s/\?([^=]+)=\$\{true\}/\1/`

## Note

Yes, I know I'm going to have to do more magic when we harmonize the forms, and no, I didn't add the
Property Mappings to the wizard, and yes, I know I'm going to have pain with the *new* version of
the wizard. But this is a serious bug; you can't make Radius servers with *either* of the current
dialogues at the moment.

* This (temporary) change is needed to prevent the unit tests from failing.

\# What

\# Why

\# How

\# Designs

\# Test Steps

\# Other Notes

* Revert "This (temporary) change is needed to prevent the unit tests from failing."

This reverts commit dddde09be5.

* web/admin: Provide `hidden` text and textarea components

## Details

This commit provides two new elements (technically, since they're API-unaware), one for `<input
type="text">`, and one for `<textarea>`, that provide for the ability to create fields that are (or
can be) hidden. A new boolean attribute, `revealed`, shows the state of the component (the content
is therefore *not* revealed by default).

It also includes a third new element, `ak-visibility-toggle`, that creates a hide/show toggle with
all the right icons, styling, and eventing.  It's straightforward, and isolating it improved the
DX of everything that uses that feature by quite a bit.

Storybook stories (with autodoc documentation) have been provided for `ak-hidden-text-input`,
`ak-hidden-textarea-input`, and `ak-visibility-toggle`.

## Maintenance Notice

As a maintenance detail, the field `ak-private-text` has been renamed `ak-secret-text` to reflect
its usage, and the places where it was used have all been changed to reflect that update.

* web/component: embed styling (for now) to handle the lightDom/shadowDom/slot conflicts in HorizontalLightComponent and HorizontalFormElement

* Comments and Types. I really shouldn't have to catch this stuff with my eyeballs.

* fix typo

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-06-14 01:48:34 +02:00
2aceed285e providers/rac: fixes prompt data not being merged with connection_settings (#15037)
* Fixes line that pulls in prompt data

* fallback to old settings

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-06-13 18:54:20 +02:00
566 changed files with 8143 additions and 6615 deletions

View File

@ -94,7 +94,7 @@ gen-build: ## Extract the schema from the database
AUTHENTIK_DEBUG=true \
AUTHENTIK_TENANTS__ENABLED=true \
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
uv run ak make_blueprint_schema > blueprints/schema.json
uv run ak make_blueprint_schema --file blueprints/schema.json
AUTHENTIK_DEBUG=true \
AUTHENTIK_TENANTS__ENABLED=true \
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \

View File

@ -72,20 +72,33 @@ class Command(BaseCommand):
"additionalProperties": True,
},
"entries": {
"type": "array",
"items": {
"oneOf": [],
},
"anyOf": [
{
"type": "array",
"items": {"$ref": "#/$defs/blueprint_entry"},
},
{
"type": "object",
"additionalProperties": {
"type": "array",
"items": {"$ref": "#/$defs/blueprint_entry"},
},
},
],
},
},
"$defs": {},
"$defs": {"blueprint_entry": {"oneOf": []}},
}
def add_arguments(self, parser):
parser.add_argument("--file", type=str)
@no_translations
def handle(self, *args, **options):
def handle(self, *args, file: str, **options):
"""Generate JSON Schema for blueprints"""
self.build()
self.stdout.write(dumps(self.schema, indent=4, default=Command.json_default))
with open(file, "w") as _schema:
_schema.write(dumps(self.schema, indent=4, default=Command.json_default))
@staticmethod
def json_default(value: Any) -> Any:
@ -112,7 +125,7 @@ class Command(BaseCommand):
}
)
model_path = f"{model._meta.app_label}.{model._meta.model_name}"
self.schema["properties"]["entries"]["items"]["oneOf"].append(
self.schema["$defs"]["blueprint_entry"]["oneOf"].append(
self.template_entry(model_path, model, serializer)
)

View File

@ -1,10 +1,11 @@
version: 1
entries:
- identifiers:
name: "%(id)s"
slug: "%(id)s"
model: authentik_flows.flow
state: present
attrs:
designation: stage_configuration
title: foo
foo:
- identifiers:
name: "%(id)s"
slug: "%(id)s"
model: authentik_flows.flow
state: present
attrs:
designation: stage_configuration
title: foo

View File

@ -191,11 +191,18 @@ class Blueprint:
"""Dataclass used for a full export"""
version: int = field(default=1)
entries: list[BlueprintEntry] = field(default_factory=list)
entries: list[BlueprintEntry] | dict[str, list[BlueprintEntry]] = field(default_factory=list)
context: dict = field(default_factory=dict)
metadata: BlueprintMetadata | None = field(default=None)
def iter_entries(self) -> Iterable[BlueprintEntry]:
if isinstance(self.entries, dict):
for _section, entries in self.entries.items():
yield from entries
else:
yield from self.entries
class YAMLTag:
"""Base class for all YAML Tags"""
@ -226,7 +233,7 @@ class KeyOf(YAMLTag):
self.id_from = node.value
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
for _entry in blueprint.entries:
for _entry in blueprint.iter_entries():
if _entry.id == self.id_from and _entry._state.instance:
# Special handling for PolicyBindingModels, as they'll have a different PK
# which is used when creating policy bindings

View File

@ -384,7 +384,7 @@ class Importer:
def _apply_models(self, raise_errors=False) -> bool:
"""Apply (create/update) models yaml"""
self.__pk_map = {}
for entry in self._import.entries:
for entry in self._import.iter_entries():
model_app_label, model_name = entry.get_model(self._import).split(".")
try:
model: type[SerializerModel] = registry.get_model(model_app_label, model_name)

View File

@ -69,7 +69,6 @@ SESSION_KEY_APPLICATION_PRE = "authentik/flows/application_pre"
SESSION_KEY_GET = "authentik/flows/get"
SESSION_KEY_POST = "authentik/flows/post"
SESSION_KEY_HISTORY = "authentik/flows/history"
SESSION_KEY_AUTH_STARTED = "authentik/flows/auth_started"
QS_KEY_TOKEN = "flow_token" # nosec
QS_QUERY = "query"
@ -455,7 +454,6 @@ class FlowExecutorView(APIView):
SESSION_KEY_APPLICATION_PRE,
SESSION_KEY_PLAN,
SESSION_KEY_GET,
SESSION_KEY_AUTH_STARTED,
# We might need the initial POST payloads for later requests
# SESSION_KEY_POST,
# We don't delete the history on purpose, as a user might

View File

@ -6,8 +6,7 @@ from django.shortcuts import get_object_or_404
from ua_parser.user_agent_parser import Parse
from authentik.core.views.interface import InterfaceView
from authentik.flows.models import Flow, FlowDesignation
from authentik.flows.views.executor import SESSION_KEY_AUTH_STARTED
from authentik.flows.models import Flow
class FlowInterfaceView(InterfaceView):
@ -15,12 +14,6 @@ class FlowInterfaceView(InterfaceView):
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
flow = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
if (
not self.request.user.is_authenticated
and flow.designation == FlowDesignation.AUTHENTICATION
):
self.request.session[SESSION_KEY_AUTH_STARTED] = True
self.request.session.save()
kwargs["flow"] = flow
kwargs["flow_background_url"] = flow.background_url(self.request)
kwargs["inspector"] = "inspector" in self.request.GET

View File

@ -39,4 +39,3 @@ class AuthentikPoliciesConfig(ManagedAppConfig):
label = "authentik_policies"
verbose_name = "authentik Policies"
default = True
mountpoint = "policy/"

View File

@ -1,89 +0,0 @@
{% extends 'login/base_full.html' %}
{% load static %}
{% load i18n %}
{% block head %}
{{ block.super }}
<script>
let redirecting = false;
const checkAuth = async () => {
if (redirecting) return true;
const url = "{{ check_auth_url }}";
console.debug("authentik/policies/buffer: Checking authentication...");
try {
const result = await fetch(url, {
method: "HEAD",
});
if (result.status >= 400) {
return false
}
console.debug("authentik/policies/buffer: Continuing");
redirecting = true;
if ("{{ auth_req_method }}" === "post") {
document.querySelector("form").submit();
} else {
window.location.assign("{{ continue_url|escapejs }}");
}
} catch {
return false;
}
};
let timeout = 100;
let offset = 20;
let attempt = 0;
const main = async () => {
attempt += 1;
await checkAuth();
console.debug(`authentik/policies/buffer: Waiting ${timeout}ms...`);
setTimeout(main, timeout);
timeout += (offset * attempt);
if (timeout >= 2000) {
timeout = 2000;
}
}
document.addEventListener("visibilitychange", async () => {
if (document.hidden) return;
console.debug("authentik/policies/buffer: Checking authentication on tab activate...");
await checkAuth();
});
main();
</script>
{% endblock %}
{% block title %}
{% trans 'Waiting for authentication...' %} - {{ brand.branding_title }}
{% endblock %}
{% block card_title %}
{% trans 'Waiting for authentication...' %}
{% endblock %}
{% block card %}
<form class="pf-c-form" method="{{ auth_req_method }}" action="{{ continue_url }}">
{% if auth_req_method == "post" %}
{% for key, value in auth_req_body.items %}
<input type="hidden" name="{{ key }}" value="{{ value }}" />
{% endfor %}
{% endif %}
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<div class="pf-c-empty-state__icon">
<span class="pf-c-spinner pf-m-xl" role="progressbar">
<span class="pf-c-spinner__clipper"></span>
<span class="pf-c-spinner__lead-ball"></span>
<span class="pf-c-spinner__tail-ball"></span>
</span>
</div>
<h1 class="pf-c-title pf-m-lg">
{% trans "You're already authenticating in another tab. This page will refresh once authentication is completed." %}
</h1>
</div>
</div>
<div class="pf-c-form__group pf-m-action">
<a href="{{ auth_req_url }}" class="pf-c-button pf-m-primary pf-m-block">
{% trans "Authenticate in this tab" %}
</a>
</div>
</form>
{% endblock %}

View File

@ -1,121 +0,0 @@
from django.contrib.auth.models import AnonymousUser
from django.contrib.sessions.middleware import SessionMiddleware
from django.http import HttpResponse
from django.test import RequestFactory, TestCase
from django.urls import reverse
from authentik.core.models import Application, Provider
from authentik.core.tests.utils import create_test_flow, create_test_user
from authentik.flows.models import FlowDesignation
from authentik.flows.planner import FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import dummy_get_response
from authentik.policies.views import (
QS_BUFFER_ID,
SESSION_KEY_BUFFER,
BufferedPolicyAccessView,
BufferView,
PolicyAccessView,
)
class TestPolicyViews(TestCase):
"""Test PolicyAccessView"""
def setUp(self):
super().setUp()
self.factory = RequestFactory()
self.user = create_test_user()
def test_pav(self):
"""Test simple policy access view"""
provider = Provider.objects.create(
name=generate_id(),
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
class TestView(PolicyAccessView):
def resolve_provider_application(self):
self.provider = provider
self.application = app
def get(self, *args, **kwargs):
return HttpResponse("foo")
req = self.factory.get("/")
req.user = self.user
res = TestView.as_view()(req)
self.assertEqual(res.status_code, 200)
self.assertEqual(res.content, b"foo")
def test_pav_buffer(self):
"""Test simple policy access view"""
provider = Provider.objects.create(
name=generate_id(),
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
class TestView(BufferedPolicyAccessView):
def resolve_provider_application(self):
self.provider = provider
self.application = app
def get(self, *args, **kwargs):
return HttpResponse("foo")
req = self.factory.get("/")
req.user = AnonymousUser()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(req)
req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk)
req.session.save()
res = TestView.as_view()(req)
self.assertEqual(res.status_code, 302)
self.assertTrue(res.url.startswith(reverse("authentik_policies:buffer")))
def test_pav_buffer_skip(self):
"""Test simple policy access view (skip buffer)"""
provider = Provider.objects.create(
name=generate_id(),
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
class TestView(BufferedPolicyAccessView):
def resolve_provider_application(self):
self.provider = provider
self.application = app
def get(self, *args, **kwargs):
return HttpResponse("foo")
req = self.factory.get("/?skip_buffer=true")
req.user = AnonymousUser()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(req)
req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk)
req.session.save()
res = TestView.as_view()(req)
self.assertEqual(res.status_code, 302)
self.assertTrue(res.url.startswith(reverse("authentik_flows:default-authentication")))
def test_buffer(self):
"""Test buffer view"""
uid = generate_id()
req = self.factory.get(f"/?{QS_BUFFER_ID}={uid}")
req.user = AnonymousUser()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(req)
ts = generate_id()
req.session[SESSION_KEY_BUFFER % uid] = {
"method": "get",
"body": {},
"url": f"/{ts}",
}
req.session.save()
res = BufferView.as_view()(req)
self.assertEqual(res.status_code, 200)
self.assertIn(ts, res.render().content.decode())

View File

@ -1,14 +1,7 @@
"""API URLs"""
from django.urls import path
from authentik.policies.api.bindings import PolicyBindingViewSet
from authentik.policies.api.policies import PolicyViewSet
from authentik.policies.views import BufferView
urlpatterns = [
path("buffer", BufferView.as_view(), name="buffer"),
]
api_urlpatterns = [
("policies/all", PolicyViewSet),

View File

@ -1,37 +1,23 @@
"""authentik access helper classes"""
from typing import Any
from uuid import uuid4
from django.contrib import messages
from django.contrib.auth.mixins import AccessMixin
from django.contrib.auth.views import redirect_to_login
from django.http import HttpRequest, HttpResponse, QueryDict
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.http import urlencode
from django.http import HttpRequest, HttpResponse
from django.utils.translation import gettext as _
from django.views.generic.base import TemplateView, View
from django.views.generic.base import View
from structlog.stdlib import get_logger
from authentik.core.models import Application, Provider, User
from authentik.flows.models import Flow, FlowDesignation
from authentik.flows.planner import FlowPlan
from authentik.flows.views.executor import (
SESSION_KEY_APPLICATION_PRE,
SESSION_KEY_AUTH_STARTED,
SESSION_KEY_PLAN,
SESSION_KEY_POST,
)
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_POST
from authentik.lib.sentry import SentryIgnoredException
from authentik.policies.denied import AccessDeniedResponse
from authentik.policies.engine import PolicyEngine
from authentik.policies.types import PolicyRequest, PolicyResult
LOGGER = get_logger()
QS_BUFFER_ID = "af_bf_id"
QS_SKIP_BUFFER = "skip_buffer"
SESSION_KEY_BUFFER = "authentik/policies/pav_buffer/%s"
class RequestValidationError(SentryIgnoredException):
@ -139,65 +125,3 @@ class PolicyAccessView(AccessMixin, View):
for message in result.messages:
messages.error(self.request, _(message))
return result
def url_with_qs(url: str, **kwargs):
"""Update/set querystring of `url` with the parameters in `kwargs`. Original query string
parameters are retained"""
if "?" not in url:
return url + f"?{urlencode(kwargs)}"
url, _, qs = url.partition("?")
qs = QueryDict(qs, mutable=True)
qs.update(kwargs)
return url + f"?{urlencode(qs.items())}"
class BufferView(TemplateView):
"""Buffer view"""
template_name = "policies/buffer.html"
def get_context_data(self, **kwargs):
buf_id = self.request.GET.get(QS_BUFFER_ID)
buffer: dict = self.request.session.get(SESSION_KEY_BUFFER % buf_id)
kwargs["auth_req_method"] = buffer["method"]
kwargs["auth_req_body"] = buffer["body"]
kwargs["auth_req_url"] = url_with_qs(buffer["url"], **{QS_SKIP_BUFFER: True})
kwargs["check_auth_url"] = reverse("authentik_api:user-me")
kwargs["continue_url"] = url_with_qs(buffer["url"], **{QS_BUFFER_ID: buf_id})
return super().get_context_data(**kwargs)
class BufferedPolicyAccessView(PolicyAccessView):
"""PolicyAccessView which buffers access requests in case the user is not logged in"""
def handle_no_permission(self):
plan: FlowPlan | None = self.request.session.get(SESSION_KEY_PLAN)
authenticating = self.request.session.get(SESSION_KEY_AUTH_STARTED)
if plan:
flow = Flow.objects.filter(pk=plan.flow_pk).first()
if not flow or flow.designation != FlowDesignation.AUTHENTICATION:
LOGGER.debug("Not buffering request, no flow or flow not for authentication")
return super().handle_no_permission()
if not plan and authenticating is None:
LOGGER.debug("Not buffering request, no flow plan active")
return super().handle_no_permission()
if self.request.GET.get(QS_SKIP_BUFFER):
LOGGER.debug("Not buffering request, explicit skip")
return super().handle_no_permission()
buffer_id = str(uuid4())
LOGGER.debug("Buffering access request", bf_id=buffer_id)
self.request.session[SESSION_KEY_BUFFER % buffer_id] = {
"body": self.request.POST,
"url": self.request.build_absolute_uri(self.request.get_full_path()),
"method": self.request.method.lower(),
}
return redirect(
url_with_qs(reverse("authentik_policies:buffer"), **{QS_BUFFER_ID: buffer_id})
)
def dispatch(self, request, *args, **kwargs):
response = super().dispatch(request, *args, **kwargs)
if QS_BUFFER_ID in self.request.GET:
self.request.session.pop(SESSION_KEY_BUFFER % self.request.GET[QS_BUFFER_ID], None)
return response

View File

@ -30,7 +30,7 @@ from authentik.flows.stage import StageView
from authentik.lib.utils.time import timedelta_from_string
from authentik.lib.views import bad_request_message
from authentik.policies.types import PolicyRequest
from authentik.policies.views import BufferedPolicyAccessView, RequestValidationError
from authentik.policies.views import PolicyAccessView, RequestValidationError
from authentik.providers.oauth2.constants import (
PKCE_METHOD_PLAIN,
PKCE_METHOD_S256,
@ -326,7 +326,7 @@ class OAuthAuthorizationParams:
return code
class AuthorizationFlowInitView(BufferedPolicyAccessView):
class AuthorizationFlowInitView(PolicyAccessView):
"""OAuth2 Flow initializer, checks access to application and starts flow"""
params: OAuthAuthorizationParams

View File

@ -18,11 +18,14 @@ from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner
from authentik.flows.stage import RedirectStage
from authentik.lib.utils.time import timedelta_from_string
from authentik.policies.engine import PolicyEngine
from authentik.policies.views import BufferedPolicyAccessView
from authentik.policies.views import PolicyAccessView
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
PLAN_CONNECTION_SETTINGS = "connection_settings"
class RACStartView(BufferedPolicyAccessView):
class RACStartView(PolicyAccessView):
"""Start a RAC connection by checking access and creating a connection token"""
endpoint: Endpoint
@ -109,10 +112,15 @@ class RACFinalStage(RedirectStage):
return super().dispatch(request, *args, **kwargs)
def get_challenge(self, *args, **kwargs) -> RedirectChallenge:
settings = self.executor.plan.context.get(PLAN_CONNECTION_SETTINGS)
if not settings:
settings = self.executor.plan.context.get(PLAN_CONTEXT_PROMPT, {}).get(
PLAN_CONNECTION_SETTINGS
)
token = ConnectionToken.objects.create(
provider=self.provider,
endpoint=self.endpoint,
settings=self.executor.plan.context.get("connection_settings", {}),
settings=settings or {},
session=self.request.session["authenticatedsession"],
expires=now() + timedelta_from_string(self.provider.connection_expiry),
expiring=True,

View File

@ -35,8 +35,8 @@ REQUEST_KEY_SAML_SIG_ALG = "SigAlg"
REQUEST_KEY_SAML_RESPONSE = "SAMLResponse"
REQUEST_KEY_RELAY_STATE = "RelayState"
PLAN_CONTEXT_SAML_AUTH_N_REQUEST = "authentik/providers/saml/authn_request"
PLAN_CONTEXT_SAML_LOGOUT_REQUEST = "authentik/providers/saml/logout_request"
SESSION_KEY_AUTH_N_REQUEST = "authentik/providers/saml/authn_request"
SESSION_KEY_LOGOUT_REQUEST = "authentik/providers/saml/logout_request"
# This View doesn't have a URL on purpose, as its called by the FlowExecutor
@ -50,11 +50,10 @@ class SAMLFlowFinalView(ChallengeStageView):
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
application: Application = self.executor.plan.context[PLAN_CONTEXT_APPLICATION]
provider: SAMLProvider = get_object_or_404(SAMLProvider, pk=application.provider_id)
if PLAN_CONTEXT_SAML_AUTH_N_REQUEST not in self.executor.plan.context:
self.logger.warning("No AuthNRequest in context")
if SESSION_KEY_AUTH_N_REQUEST not in self.request.session:
return self.executor.stage_invalid()
auth_n_request: AuthNRequest = self.executor.plan.context[PLAN_CONTEXT_SAML_AUTH_N_REQUEST]
auth_n_request: AuthNRequest = self.request.session.pop(SESSION_KEY_AUTH_N_REQUEST)
try:
response = AssertionProcessor(provider, request, auth_n_request).build_response()
except SAMLException as exc:
@ -107,3 +106,6 @@ class SAMLFlowFinalView(ChallengeStageView):
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
# We'll never get here since the challenge redirects to the SP
return HttpResponseBadRequest()
def cleanup(self):
self.request.session.pop(SESSION_KEY_AUTH_N_REQUEST, None)

View File

@ -19,9 +19,9 @@ from authentik.providers.saml.exceptions import CannotHandleAssertion
from authentik.providers.saml.models import SAMLProvider
from authentik.providers.saml.processors.logout_request_parser import LogoutRequestParser
from authentik.providers.saml.views.flows import (
PLAN_CONTEXT_SAML_LOGOUT_REQUEST,
REQUEST_KEY_RELAY_STATE,
REQUEST_KEY_SAML_REQUEST,
SESSION_KEY_LOGOUT_REQUEST,
)
LOGGER = get_logger()
@ -33,10 +33,6 @@ class SAMLSLOView(PolicyAccessView):
flow: Flow
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.plan_context = {}
def resolve_provider_application(self):
self.application = get_object_or_404(Application, slug=self.kwargs["application_slug"])
self.provider: SAMLProvider = get_object_or_404(
@ -63,7 +59,6 @@ class SAMLSLOView(PolicyAccessView):
request,
{
PLAN_CONTEXT_APPLICATION: self.application,
**self.plan_context,
},
)
plan.append_stage(in_memory_stage(SessionEndStage))
@ -88,7 +83,7 @@ class SAMLSLOBindingRedirectView(SAMLSLOView):
self.request.GET[REQUEST_KEY_SAML_REQUEST],
relay_state=self.request.GET.get(REQUEST_KEY_RELAY_STATE, None),
)
self.plan_context[PLAN_CONTEXT_SAML_LOGOUT_REQUEST] = logout_request
self.request.session[SESSION_KEY_LOGOUT_REQUEST] = logout_request
except CannotHandleAssertion as exc:
Event.new(
EventAction.CONFIGURATION_ERROR,
@ -116,7 +111,7 @@ class SAMLSLOBindingPOSTView(SAMLSLOView):
payload[REQUEST_KEY_SAML_REQUEST],
relay_state=payload.get(REQUEST_KEY_RELAY_STATE, None),
)
self.plan_context[PLAN_CONTEXT_SAML_LOGOUT_REQUEST] = logout_request
self.request.session[SESSION_KEY_LOGOUT_REQUEST] = logout_request
except CannotHandleAssertion as exc:
LOGGER.info(str(exc))
return bad_request_message(self.request, str(exc))

View File

@ -15,16 +15,16 @@ from authentik.flows.models import in_memory_stage
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_SSO, FlowPlanner
from authentik.flows.views.executor import SESSION_KEY_POST
from authentik.lib.views import bad_request_message
from authentik.policies.views import BufferedPolicyAccessView
from authentik.policies.views import PolicyAccessView
from authentik.providers.saml.exceptions import CannotHandleAssertion
from authentik.providers.saml.models import SAMLBindings, SAMLProvider
from authentik.providers.saml.processors.authn_request_parser import AuthNRequestParser
from authentik.providers.saml.views.flows import (
PLAN_CONTEXT_SAML_AUTH_N_REQUEST,
REQUEST_KEY_RELAY_STATE,
REQUEST_KEY_SAML_REQUEST,
REQUEST_KEY_SAML_SIG_ALG,
REQUEST_KEY_SAML_SIGNATURE,
SESSION_KEY_AUTH_N_REQUEST,
SAMLFlowFinalView,
)
from authentik.stages.consent.stage import (
@ -35,14 +35,10 @@ from authentik.stages.consent.stage import (
LOGGER = get_logger()
class SAMLSSOView(BufferedPolicyAccessView):
class SAMLSSOView(PolicyAccessView):
"""SAML SSO Base View, which plans a flow and injects our final stage.
Calls get/post handler."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.plan_context = {}
def resolve_provider_application(self):
self.application = get_object_or_404(Application, slug=self.kwargs["application_slug"])
self.provider: SAMLProvider = get_object_or_404(
@ -72,7 +68,6 @@ class SAMLSSOView(BufferedPolicyAccessView):
PLAN_CONTEXT_CONSENT_HEADER: _("You're about to sign into %(application)s.")
% {"application": self.application.name},
PLAN_CONTEXT_CONSENT_PERMISSIONS: [],
**self.plan_context,
},
)
except FlowNonApplicableException:
@ -88,7 +83,7 @@ class SAMLSSOView(BufferedPolicyAccessView):
def post(self, request: HttpRequest, application_slug: str) -> HttpResponse:
"""GET and POST use the same handler, but we can't
override .dispatch easily because BufferedPolicyAccessView's dispatch"""
override .dispatch easily because PolicyAccessView's dispatch"""
return self.get(request, application_slug)
@ -108,7 +103,7 @@ class SAMLSSOBindingRedirectView(SAMLSSOView):
self.request.GET.get(REQUEST_KEY_SAML_SIGNATURE),
self.request.GET.get(REQUEST_KEY_SAML_SIG_ALG),
)
self.plan_context[PLAN_CONTEXT_SAML_AUTH_N_REQUEST] = auth_n_request
self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request
except CannotHandleAssertion as exc:
Event.new(
EventAction.CONFIGURATION_ERROR,
@ -142,7 +137,7 @@ class SAMLSSOBindingPOSTView(SAMLSSOView):
payload[REQUEST_KEY_SAML_REQUEST],
payload.get(REQUEST_KEY_RELAY_STATE),
)
self.plan_context[PLAN_CONTEXT_SAML_AUTH_N_REQUEST] = auth_n_request
self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request
except CannotHandleAssertion as exc:
LOGGER.info(str(exc))
return bad_request_message(self.request, str(exc))
@ -156,4 +151,4 @@ class SAMLSSOBindingInitView(SAMLSSOView):
"""Create SAML Response from scratch"""
LOGGER.debug("No SAML Request, using IdP-initiated flow.")
auth_n_request = AuthNRequestParser(self.provider).idp_initiated()
self.plan_context[PLAN_CONTEXT_SAML_AUTH_N_REQUEST] = auth_n_request
self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -6,18 +6,18 @@
# Translators:
# jcamat, 2022
# Angel, 2024
# Iamanaws, 2024
# Marcelo Elizeche Landó, 2025
# Jens L. <jens@goauthentik.io>, 2025
# Iamanaws, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
"POT-Creation-Date: 2025-06-04 00:12+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
"Last-Translator: Iamanaws, 2025\n"
"Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -111,7 +111,7 @@ msgstr "Certificado Web usado por el servidor web Core de authentik"
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr ""
msgstr "Certificados utilizados para la autenticación del cliente."
#: authentik/brands/models.py
msgid "Brand"
@ -131,7 +131,7 @@ msgstr "Descripción adicional no disponible."
#: authentik/core/api/groups.py
msgid "Cannot set group as parent of itself."
msgstr "No se puede establecer el grupo como padre de sí mismo."
msgstr "No se puede establecer un grupo como su propio padre."
#: authentik/core/api/providers.py
msgid ""
@ -183,11 +183,11 @@ msgstr "Remueve usuario del grupo"
#: authentik/core/models.py
msgid "Enable superuser status"
msgstr "Habiliar estado de \"superusuario\""
msgstr "Habilitar el estado de superusuario"
#: authentik/core/models.py
msgid "Disable superuser status"
msgstr "Deshabiliar estado de \"superusuario\""
msgstr "Deshabilitar el estado de superusuario"
#: authentik/core/models.py
msgid "User's display name."
@ -241,7 +241,7 @@ msgstr "Flujo utilizado al autorizar a este proveedor."
#: authentik/core/models.py
msgid "Flow used ending the session from a provider."
msgstr "Flujo usado para terminar la sesión de un proveedor."
msgstr "Flujo utilizado para finalizar la sesión desde un proveedor."
#: authentik/core/models.py
msgid ""
@ -273,11 +273,11 @@ msgstr "Aplicaciones"
#: authentik/core/models.py
msgid "Application Entitlement"
msgstr ""
msgstr "Derecho de Aplicación"
#: authentik/core/models.py
msgid "Application Entitlements"
msgstr ""
msgstr "Derechos de Aplicación"
#: authentik/core/models.py
msgid "Use the source-specific identifier"
@ -288,9 +288,9 @@ msgid ""
"Link to a user with identical email address. Can have security implications "
"when a source doesn't validate email addresses."
msgstr ""
"Apunta a un usuario con una dirección de correo electrónico idéntica. Puede "
"tener implicaciones de seguridad cuando una fuente no valida la dirección de"
" correo electrónico."
"Enlace a un usuario con la misma dirección de correo electrónico. Puede "
"tener implicaciones de seguridad cuando una fuente no valida las direcciones"
" de correo electrónico."
#: authentik/core/models.py
msgid ""
@ -305,8 +305,8 @@ msgid ""
"Link to a user with identical username. Can have security implications when "
"a username is used with another source."
msgstr ""
"Enlace a un usuario con un nombre de usuario idéntico. Puede tener "
"implicaciones de seguridad cuando se usa un nombre de usuario con otra "
"Enlace a un usuario con el mismo nombre de usuario. Puede tener "
"implicaciones de seguridad cuando un nombre de usuario se utiliza con otra "
"fuente."
#: authentik/core/models.py
@ -322,8 +322,8 @@ msgid ""
"Link to a group with identical name. Can have security implications when a "
"group name is used with another source."
msgstr ""
"Enlace a un grupo con un nombre idéntico. Puede tener implicaciones de "
"seguridad cuando se utiliza un nombre de grupo con otra fuente."
"Enlace a un grupo con el mismo nombre. Puede tener implicaciones de "
"seguridad cuando un nombre de grupo se utiliza con otra fuente."
#: authentik/core/models.py
msgid "Use the group name, but deny enrollment when the name already exists."
@ -385,7 +385,7 @@ msgstr "Asignaciones de Propiedades"
#: authentik/core/models.py
msgid "session data"
msgstr ""
msgstr "datos de sesión"
#: authentik/core/models.py
msgid "Session"
@ -424,7 +424,7 @@ msgstr "¡Autenticado exitosamente con {source}!"
#: authentik/core/sources/flow_manager.py
#, python-brace-format
msgid "Successfully linked {source}!"
msgstr "¡{source} vinculado exitosamente!"
msgstr "¡{source} enlazado correctamente!"
#: authentik/core/sources/flow_manager.py
msgid "Source is not configured for enrollment."
@ -476,11 +476,11 @@ msgstr ""
#: authentik/crypto/models.py
msgid "Certificate-Key Pair"
msgstr "Par de claves de certificado"
msgstr "Par Certificado-Clave"
#: authentik/crypto/models.py
msgid "Certificate-Key Pairs"
msgstr "Pares de claves de certificado"
msgstr "Pares Certificado-Clave"
#: authentik/enterprise/api.py
msgid "Enterprise is required to create/update this object."
@ -511,7 +511,7 @@ msgstr ""
#: authentik/enterprise/policies/unique_password/models.py
msgid "Number of passwords to check against."
msgstr ""
msgstr "Número de contraseñas contra las que verificar."
#: authentik/enterprise/policies/unique_password/models.py
#: authentik/policies/password/models.py
@ -521,18 +521,20 @@ msgstr "La contraseña no se ha establecido en contexto"
#: authentik/enterprise/policies/unique_password/models.py
msgid "This password has been used previously. Please choose a different one."
msgstr ""
"Esta contraseña se ha utilizado anteriormente. Por favor, elija una "
"diferente."
#: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policy"
msgstr ""
msgstr "Política de Unicidad de Contraseñas"
#: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policies"
msgstr ""
msgstr "Políticas de Unicidad de Contraseñas"
#: authentik/enterprise/policies/unique_password/models.py
msgid "User Password History"
msgstr ""
msgstr "Historial de Contraseñas del Usuario"
#: authentik/enterprise/policy.py
msgid "Enterprise required to access this feature."
@ -617,39 +619,39 @@ msgstr "Clave de firma"
#: authentik/enterprise/providers/ssf/models.py
msgid "Key used to sign the SSF Events."
msgstr ""
msgstr "Clave utilizada para firmar los eventos SSF."
#: authentik/enterprise/providers/ssf/models.py
msgid "Shared Signals Framework Provider"
msgstr ""
msgstr "Proveedor del Marco de Señales Compartidas"
#: authentik/enterprise/providers/ssf/models.py
msgid "Shared Signals Framework Providers"
msgstr ""
msgstr "Proveedores del Marco de Señales Compartidas"
#: authentik/enterprise/providers/ssf/models.py
msgid "Add stream to SSF provider"
msgstr ""
msgstr "Agregar flujo de datos al proveedor SSF"
#: authentik/enterprise/providers/ssf/models.py
msgid "SSF Stream"
msgstr ""
msgstr "Flujo de Datos SSF"
#: authentik/enterprise/providers/ssf/models.py
msgid "SSF Streams"
msgstr ""
msgstr "Flujos de Datos SSF"
#: authentik/enterprise/providers/ssf/models.py
msgid "SSF Stream Event"
msgstr ""
msgstr "Evento de Flujo de Datos SSF"
#: authentik/enterprise/providers/ssf/models.py
msgid "SSF Stream Events"
msgstr ""
msgstr "Eventos de Flujos de Datos SSF"
#: authentik/enterprise/providers/ssf/tasks.py
msgid "Failed to send request"
msgstr "Falló envio de petición"
msgstr "Error al enviar la solicitud"
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/models.py
msgid "Endpoint Authenticator Google Device Trust Connector Stage"
@ -681,26 +683,29 @@ msgid ""
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr ""
"Configura las autoridades certificadoras para validar el certificado. Esta "
"opción tiene una prioridad mayor que la opción `client_certificate` en "
"`Brand`."
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr ""
msgstr "Etapa de TLS mutuo"
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr ""
msgstr "Etapas de TLS mutuo"
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr ""
msgstr "Permisos para pasar Certificados a los puestos avanzados."
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr ""
msgstr "Se requiere certificado, pero no se proporcionó ninguno."
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr ""
msgstr "No se encontró usuario para el certificado."
#: authentik/enterprise/stages/source/models.py
msgid ""
@ -753,12 +758,16 @@ msgid ""
"Customize the body of the request. Mapping should return data that is JSON-"
"serializable."
msgstr ""
"Personaliza el cuerpo de la solicitud. El mapeo debe devolver datos que sean"
" serializables en JSON."
#: authentik/events/models.py
msgid ""
"Configure additional headers to be sent. Mapping should return a dictionary "
"of key-value pairs"
msgstr ""
"Configura encabezados adicionales para enviar. El mapeo debe devolver un "
"diccionario de pares clave-valor"
#: authentik/events/models.py
msgid ""
@ -786,7 +795,7 @@ msgstr "Transporte de notificaciones"
#: authentik/events/models.py
msgid "Notification Transports"
msgstr "Transportes de notificación"
msgstr "Medios de Notificación"
#: authentik/events/models.py
msgid "Notice"
@ -813,9 +822,9 @@ msgid ""
"Select which transports should be used to notify the user. If none are "
"selected, the notification will only be shown in the authentik UI."
msgstr ""
"Seleccione qué transportes se deben usar para notificar al usuario. Si no se"
" selecciona ninguno, la notificación solo se mostrará en la interfaz de "
"usuario de authentik."
"Selecciona qué medios se deben usar para notificar al usuario. Si no se "
"selecciona ninguno, la notificación solo se mostrará en la interfaz de "
"authentik."
#: authentik/events/models.py
msgid "Controls which severity level the created notifications will have."
@ -987,7 +996,7 @@ msgstr "Evalúa políticas durante el proceso de planeación del Flujo."
#: authentik/flows/models.py
msgid "Evaluate policies when the Stage is presented to the user."
msgstr ""
msgstr "Evaluar las políticas cuando la Etapa se presenta al usuario."
#: authentik/flows/models.py
msgid ""
@ -1034,6 +1043,8 @@ msgid ""
"When enabled, provider will not modify or create objects in the remote "
"system."
msgstr ""
"Cuando está habilitado, el proveedor no modificará ni creará objetos en el "
"sistema remoto."
#: authentik/lib/sync/outgoing/tasks.py
msgid "Starting full provider sync"
@ -1041,20 +1052,21 @@ msgstr "Iniciando sincronización completa de proveedor"
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing users"
msgstr ""
msgstr "Sincronizando usuarios"
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing groups"
msgstr ""
msgstr "Sincronizando grupos"
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
msgid "Syncing page {page} of groups"
msgstr "Sincronizando página {page} de grupos"
msgid "Syncing page {page} of {object_type}"
msgstr "Sincronizando página {page} de {object_type}"
#: authentik/lib/sync/outgoing/tasks.py
msgid "Dropping mutating request due to dry run"
msgstr ""
"Descartando solicitud de mutación debido a ejecución en modo de simulación"
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
@ -1233,7 +1245,7 @@ msgstr ""
#: authentik/policies/expiry/models.py
msgid "Password has expired."
msgstr "La contraseña ha caducado."
msgstr "La contraseña ha expirado."
#: authentik/policies/expiry/models.py
msgid "Password Expiry Policy"
@ -1271,7 +1283,7 @@ msgstr "La IP del cliente no está en un país permitido."
#: authentik/policies/geoip/models.py
msgid "Distance from previous authentication is larger than threshold."
msgstr "La distancia desde la autenticación previa es mayor que el límite."
msgstr "La distancia desde la autenticación anterior es mayor que el umbral."
#: authentik/policies/geoip/models.py
msgid "Distance is further than possible."
@ -1320,7 +1332,7 @@ msgstr "Vinculación de Políticas"
#: authentik/policies/models.py
msgid "Policy Bindings"
msgstr "Vinculaciones de políticas"
msgstr "Vinculaciones de Políticas"
#: authentik/policies/models.py
msgid ""
@ -1594,11 +1606,11 @@ msgstr "ES256 (Encriptación Asimétrica)"
#: authentik/providers/oauth2/models.py
msgid "ES384 (Asymmetric Encryption)"
msgstr ""
msgstr "ES384 (Encriptación Asimétrica)"
#: authentik/providers/oauth2/models.py
msgid "ES512 (Asymmetric Encryption)"
msgstr ""
msgstr "ES512 (Encriptación Asimétrica)"
#: authentik/providers/oauth2/models.py
msgid "Scope used by the client"
@ -1813,7 +1825,7 @@ msgstr "Valida Certificados SSL de servidores de origen"
#: authentik/providers/proxy/models.py
msgid "Internal host SSL Validation"
msgstr "Validación SSL de host interno"
msgstr "Validación SSL del host interno"
#: authentik/providers/proxy/models.py
msgid ""
@ -2027,7 +2039,7 @@ msgstr ""
#: authentik/providers/saml/models.py
msgid "AuthnContextClassRef Property Mapping"
msgstr ""
msgstr "Asignación de Propiedades de AuthnContextClassRef"
#: authentik/providers/saml/models.py
msgid ""
@ -2035,6 +2047,9 @@ msgid ""
"empty, the AuthnContextClassRef will be set based on which authentication "
"methods the user used to authenticate."
msgstr ""
"Configura cómo se creará el valor de AuthnContextClassRef. Si se deja vacío,"
" el AuthnContextClassRef se establecerá según los métodos de autenticación "
"que el usuario haya utilizado para autenticarse."
#: authentik/providers/saml/models.py
msgid ""
@ -2184,11 +2199,11 @@ msgstr "Predeterminado"
#: authentik/providers/scim/models.py
msgid "AWS"
msgstr ""
msgstr "AWS"
#: authentik/providers/scim/models.py
msgid "Slack"
msgstr ""
msgstr "Slack"
#: authentik/providers/scim/models.py
msgid "Base URL to SCIM requests, usually ends in /v2"
@ -2200,11 +2215,13 @@ msgstr "Token de Autenticación"
#: authentik/providers/scim/models.py
msgid "SCIM Compatibility Mode"
msgstr ""
msgstr "Modo de Compatibilidad SCIM"
#: authentik/providers/scim/models.py
msgid "Alter authentik behavior for vendor-specific SCIM implementations."
msgstr ""
"Modificar el comportamiento de authentik para implementaciones SCIM "
"específicas de proveedores."
#: authentik/providers/scim/models.py
msgid "SCIM Provider"
@ -2232,7 +2249,7 @@ msgstr "Roles"
#: authentik/rbac/models.py
msgid "Initial Permissions"
msgstr ""
msgstr "Permisos Iniciales"
#: authentik/rbac/models.py
msgid "System permission"
@ -2270,7 +2287,7 @@ msgstr ""
#: authentik/recovery/views.py
msgid "Used recovery-link to authenticate."
msgstr "Se usó el enlace de recuperación para autenticarse."
msgstr "Se utilizó un enlace de recuperación para autenticarse."
#: authentik/sources/kerberos/models.py
msgid "Kerberos realm"
@ -2282,7 +2299,7 @@ msgstr "krb5.conf personalizado a usar. Usa el del sistema por defecto."
#: authentik/sources/kerberos/models.py
msgid "KAdmin server type"
msgstr ""
msgstr "Tipo de servidor KAdmin"
#: authentik/sources/kerberos/models.py
msgid "Sync users from Kerberos into authentik"
@ -2290,23 +2307,24 @@ msgstr "Sincronizar usuarios desde Kerberos hacia Authentik"
#: authentik/sources/kerberos/models.py
msgid "When a user changes their password, sync it back to Kerberos"
msgstr "Cuando un usuario cambia su contraseña, sincronizarlo hacia Kerberos"
msgstr ""
"Cuando un usuario cambie su contraseña, sincronizarla de vuelta a Kerberos."
#: authentik/sources/kerberos/models.py
msgid "Principal to authenticate to kadmin for sync."
msgstr "Principal para autenticarse como kadmin para la sincronización."
msgstr "Principal para autenticarse en kadmin para la sincronización."
#: authentik/sources/kerberos/models.py
msgid "Password to authenticate to kadmin for sync"
msgstr "Contraseña para autenticarse como kadmin para la sincronización"
msgstr "Contraseña para autenticarse en kadmin para la sincronización"
#: authentik/sources/kerberos/models.py
msgid ""
"Keytab to authenticate to kadmin for sync. Must be base64-encoded or in the "
"form TYPE:residual"
msgstr ""
"Keytab para autenticarse como kadmin para la sincronización. Debe estar "
"codificado en base64 o en el formato TIPO:residual"
"Keytab para autenticarse en kadmin para la sincronización. Debe estar "
"codificado en base64 o en el formato TIPO:residuo"
#: authentik/sources/kerberos/models.py
msgid ""
@ -2322,7 +2340,7 @@ msgid ""
"HTTP@hostname"
msgstr ""
"Forzar el uso de un nombre de servidor específico para SPNEGO. Debe estar en"
" el formato HTTP@nombredelservidor"
" el formato HTTP@nombre_de_host"
#: authentik/sources/kerberos/models.py
msgid "SPNEGO keytab base64-encoded or path to keytab in the form FILE:path"
@ -2339,8 +2357,8 @@ msgid ""
"If enabled, the authentik-stored password will be updated upon login with "
"the Kerberos password backend"
msgstr ""
"Si está habilitado, la contraseña almacenada por authentik se actualizada "
"al iniciar sesión con el backend de contraseñas Kerberos"
"Si está habilitado, la contraseña almacenada en authentik se actualizará al "
"iniciar sesión con el backend de contraseñas de Kerberos."
#: authentik/sources/kerberos/models.py
msgid "Kerberos Source"
@ -2388,7 +2406,7 @@ msgid ""
msgstr ""
"\n"
" Asegúrate de que tienes entradas válidas\n"
" (se obtienen a través de kinit) \n"
" (obtenibles mediante kinit) \n"
" y de haber configurado correctamente el navegador.\n"
" Por favor, contacta a tu administrador.\n"
" "
@ -2453,6 +2471,10 @@ msgstr "DN de grupo de adición"
msgid "Consider Objects matching this filter to be Users."
msgstr "Considere que los objetos que coinciden con este filtro son usuarios."
#: authentik/sources/ldap/models.py
msgid "Attribute which matches the value of `group_membership_field`."
msgstr "Atributo que coincide con el valor de `group_membership_field`."
#: authentik/sources/ldap/models.py
msgid "Field which contains members of a group."
msgstr "Campo que contiene los miembros de un grupo."
@ -2485,12 +2507,17 @@ msgid ""
"attribute. This allows nested group resolution on systems like FreeIPA and "
"Active Directory"
msgstr ""
"Buscar la pertenencia a grupos basándose en un atributo del usuario en lugar"
" de un atributo del grupo. Esto permite la resolución de grupos anidados en "
"sistemas como FreeIPA y Active Directory"
#: authentik/sources/ldap/models.py
msgid ""
"Delete authentik users and groups which were previously supplied by this "
"source, but are now missing from it."
msgstr ""
"Eliminar usuarios y grupos de authentik que fueron proporcionados "
"previamente por esta fuente, pero que ahora están ausentes."
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
@ -2512,22 +2539,24 @@ msgstr "Asignaciones de Propiedades de Fuente de LDAP"
msgid ""
"Unique ID used while checking if this object still exists in the directory."
msgstr ""
"ID único utilizado para verificar si este objeto aún existe en el "
"directorio."
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr ""
msgstr "Conexión de Fuente LDAP de Usuario"
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connections"
msgstr ""
msgstr "Conexiones de Fuente LDAP de Usuario"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connection"
msgstr ""
msgstr "Conexión de Fuente LDAP de Grupo"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connections"
msgstr ""
msgstr "Conexiones de Fuente LDAP de Grupo"
#: authentik/sources/ldap/signals.py
msgid "Password does not match Active Directory Complexity."
@ -2539,11 +2568,11 @@ msgstr "No se recibió ningún token."
#: authentik/sources/oauth/models.py
msgid "HTTP Basic Authentication"
msgstr ""
msgstr "Autenticación Básica HTTP"
#: authentik/sources/oauth/models.py
msgid "Include the client ID and secret as request parameters"
msgstr ""
msgstr "Incluir el ID de cliente y el secreto como parámetros de la solicitud"
#: authentik/sources/oauth/models.py
msgid "Request Token URL"
@ -2590,6 +2619,8 @@ msgid ""
"How to perform authentication during an authorization_code token request "
"flow"
msgstr ""
"Cómo realizar la autenticación durante un flujo de solicitud de token con "
"authorization_code"
#: authentik/sources/oauth/models.py
msgid "OAuth Source"
@ -2907,7 +2938,7 @@ msgstr "Conexiones de Fuente de SAML de Grupo"
#: authentik/sources/saml/views.py
#, python-brace-format
msgid "Continue to {source_name}"
msgstr ""
msgstr "Continuar a {source_name}"
#: authentik/sources/scim/models.py
msgid "SCIM Source"
@ -2943,7 +2974,7 @@ msgstr "Dispositivos Duo"
#: authentik/stages/authenticator_email/models.py
msgid "Email OTP"
msgstr ""
msgstr "OTP por Correo Electrónico"
#: authentik/stages/authenticator_email/models.py
#: authentik/stages/email/models.py
@ -2964,11 +2995,11 @@ msgstr ""
#: authentik/stages/authenticator_email/models.py
msgid "Email Authenticator Setup Stage"
msgstr ""
msgstr "Etapa de Configuración del Autenticador de Correo Electrónico"
#: authentik/stages/authenticator_email/models.py
msgid "Email Authenticator Setup Stages"
msgstr ""
msgstr "Etapas de Configuración del Autenticador de Correo Electrónico"
#: authentik/stages/authenticator_email/models.py
#: authentik/stages/authenticator_email/stage.py
@ -2979,11 +3010,11 @@ msgstr ""
#: authentik/stages/authenticator_email/models.py
msgid "Email Device"
msgstr "Dispositivo de Email"
msgstr "Dispositivo de correo electrónico"
#: authentik/stages/authenticator_email/models.py
msgid "Email Devices"
msgstr "Dispositivos de Email"
msgstr "Dispositivos de correo electrónico"
#: authentik/stages/authenticator_email/stage.py
#: authentik/stages/authenticator_sms/stage.py
@ -2993,7 +3024,7 @@ msgstr "El código no coincide"
#: authentik/stages/authenticator_email/stage.py
msgid "Invalid email"
msgstr "Email Inválido"
msgstr "Correo electrónico inválido"
#: authentik/stages/authenticator_email/templates/email/email_otp.html
#: authentik/stages/email/templates/email/password_reset.html
@ -3013,6 +3044,9 @@ msgid ""
" Email MFA code.\n"
" "
msgstr ""
"\n"
" Código MFA por correo electrónico.\n"
" "
#: authentik/stages/authenticator_email/templates/email/email_otp.html
#, python-format
@ -3022,7 +3056,8 @@ msgid ""
" "
msgstr ""
"\n"
"Si no solicitaste este código, por favor ignora este correo. El código anterior es válido por %(expires)s."
" Si no solicitaste este código, por favor ignora este correo. El código anterior es válido por %(expires)s.\n"
" "
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
#: authentik/stages/email/templates/email/password_reset.txt
@ -3035,6 +3070,8 @@ msgid ""
"\n"
"Email MFA code\n"
msgstr ""
"\n"
"Código MFA por correo electrónico\n"
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
#, python-format
@ -3276,8 +3313,8 @@ msgstr "No se pudo validar el token"
msgid ""
"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)."
msgstr ""
"Compensación después de la cual caduca el consentimiento. (Formato: horas = "
"1; minutos = 2; segundos = 3)."
"Desfase después del cual expira el consentimiento. (Formato: "
"hours=1;minutes=2;seconds=3)."
#: authentik/stages/consent/models.py
msgid "Consent Stage"
@ -3297,7 +3334,7 @@ msgstr "Consentimientos del usuario"
#: authentik/stages/consent/stage.py
msgid "Invalid consent token, re-showing prompt"
msgstr ""
msgstr "Token de consentimiento inválido, mostrando el aviso nuevamente"
#: authentik/stages/deny/models.py
msgid "Deny Stage"
@ -3317,11 +3354,11 @@ msgstr "Etapas ficticias"
#: authentik/stages/email/flow.py
msgid "Continue to confirm this email address."
msgstr ""
msgstr "Continúa para confirmar esta dirección de correo electrónico."
#: authentik/stages/email/flow.py
msgid "Link was already used, please request a new link."
msgstr ""
msgstr "El enlace ya fue utilizado, por favor, solícita uno nuevo."
#: authentik/stages/email/models.py
msgid "Password Reset"
@ -3445,7 +3482,8 @@ msgid ""
" "
msgstr ""
"\n"
"Si no solicitaste un cambio de contraseña, por favor ignora este correo. El enlace anterior es válido por %(expires)s."
" Si no solicitaste un cambio de contraseña, por favor ignora este correo. El enlace anterior es válido por %(expires)s.\n"
" "
#: authentik/stages/email/templates/email/password_reset.txt
msgid ""
@ -3529,24 +3567,26 @@ msgid ""
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
" to skip straight to entering their password."
msgstr ""
"Mostrar al usuario la opción \"Recordarme en este dispositivo\", permitiendo"
" que los usuarios recurrentes pasen directamente a ingresar su contraseña."
#: authentik/stages/identification/models.py
msgid "Optional enrollment flow, which is linked at the bottom of the page."
msgstr ""
"Flujo de inscripción opcional, que está vinculado en la parte inferior de la"
" página."
"Flujo de inscripción opcional, que se enlaza en la parte inferior de la "
"página."
#: authentik/stages/identification/models.py
msgid "Optional recovery flow, which is linked at the bottom of the page."
msgstr ""
"Flujo de recuperación opcional, que está vinculado en la parte inferior de "
"la página."
"Flujo de recuperación opcional, que se enlaza en la parte inferior de la "
"página."
#: authentik/stages/identification/models.py
msgid "Optional passwordless flow, which is linked at the bottom of the page."
msgstr ""
"Flujo sin contraseña opcional, el cual está vinculado en la parte inferior "
"de la página."
"Flujo opcional sin contraseña, que se enlaza en la parte inferior de la "
"página."
#: authentik/stages/identification/models.py
msgid "Specify which sources should be shown."
@ -3780,11 +3820,11 @@ msgstr "Las contraseñas no coinciden."
#: authentik/stages/redirect/api.py
msgid "Target URL should be present when mode is Static."
msgstr ""
msgstr "La URL de destino debe estar presente cuando el modo es Estático."
#: authentik/stages/redirect/api.py
msgid "Target Flow should be present when mode is Flow."
msgstr ""
msgstr "El Flujo de Destino debe estar presente cuando el modo es Flujo."
#: authentik/stages/redirect/models.py
msgid "Redirect Stage"
@ -3841,10 +3881,6 @@ msgstr "Etapas de inicio de"
msgid "No Pending user to login."
msgstr "Ningún usuario pendiente para iniciar sesión."
#: authentik/stages/user_login/stage.py
msgid "Successfully logged in!"
msgstr "¡Se ha iniciado sesión correctamente!"
#: authentik/stages/user_logout/models.py
msgid "User Logout Stage"
msgstr "Etapa de cierre de sesión del usuario"
@ -3920,10 +3956,12 @@ msgstr ""
#: authentik/tenants/models.py
msgid "Reputation cannot decrease lower than this value. Zero or negative."
msgstr ""
"La reputación no puede disminuir por debajo de este valor. Cero o negativo."
#: authentik/tenants/models.py
msgid "Reputation cannot increase higher than this value. Zero or positive."
msgstr ""
"La reputación no puede aumentar por encima de este valor. Cero o positivo."
#: authentik/tenants/models.py
msgid "The option configures the footer links on the flow executor pages."
@ -3946,8 +3984,8 @@ msgstr "Personificación habilitada/deshabilitada globalmente."
#: authentik/tenants/models.py
msgid "Require administrators to provide a reason for impersonating a user."
msgstr ""
"Requerir a los administradores proporcionar una razón para suplantar un "
"usuario."
"Requerir que los administradores proporcionen una razón para personificar a "
"un usuario."
#: authentik/tenants/models.py
msgid "Default token duration"
@ -3959,7 +3997,7 @@ msgstr "Longitud predeterminada del token"
#: authentik/tenants/models.py
msgid "Tenant"
msgstr "inquilino"
msgstr "Inquilino"
#: authentik/tenants/models.py
msgid "Tenants"

View File

@ -17,7 +17,7 @@
"eslint-plugin-wc": "^3.0.1"
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.1",
"@goauthentik/prettier-config": "^2.0.0",
"@goauthentik/tsconfig": "^1.0.1",
"@types/eslint": "^9.6.1",
"typescript": "^5.8.3",
@ -308,9 +308,9 @@
}
},
"node_modules/@goauthentik/prettier-config": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.5.tgz",
"integrity": "sha512-3W1uJvhzBPerDao53hSXhNzB7Ev8DbGYh+gVkuku1FaUZGBpiwD/6U3ah4sny8NoRiObGQ1geF4dhNLtlRbC/Q==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-2.0.0.tgz",
"integrity": "sha512-W+PAea+pH511lC4omoyeNGkFS+/AytrCMdtN7dIUJhaufMppYHLagyvurhyb5mUCg/j4DphCcunguj6dkiRVRw==",
"dev": true,
"license": "MIT",
"engines": {

View File

@ -35,7 +35,7 @@
"eslint-plugin-wc": "^3.0.1"
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.1",
"@goauthentik/prettier-config": "^2.0.0",
"@goauthentik/tsconfig": "^1.0.1",
"@types/eslint": "^9.6.1",
"typescript": "^5.8.3",

View File

@ -410,77 +410,3 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
self.driver.find_element(By.CSS_SELECTOR, "header > h1").text,
"Permission denied",
)
@retry()
@apply_blueprint(
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint("default/flow-default-provider-authorization-implicit-consent.yaml")
@apply_blueprint("system/providers-oauth2.yaml")
@reconcile_app("authentik_crypto")
def test_authorization_consent_implied_parallel(self):
"""test OpenID Provider flow (default authorization flow with implied consent)"""
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-implicit-consent"
)
provider = OAuth2Provider.objects.create(
name=generate_id(),
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
client_secret=self.client_secret,
signing_key=create_test_cert(),
redirect_uris=[
RedirectURI(
RedirectURIMatchingMode.STRICT, "http://localhost:3000/login/generic_oauth"
)
],
authorization_flow=authorization_flow,
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
SCOPE_OFFLINE_ACCESS,
]
)
)
Application.objects.create(
name=generate_id(),
slug=self.app_slug,
provider=provider,
)
self.driver.get(self.live_server_url)
login_window = self.driver.current_window_handle
self.driver.switch_to.new_window("tab")
grafana_window = self.driver.current_window_handle
self.driver.get("http://localhost:3000")
self.driver.find_element(By.CLASS_NAME, "btn-service--oauth").click()
self.driver.switch_to.window(login_window)
self.login()
self.driver.switch_to.window(grafana_window)
self.wait_for_url("http://localhost:3000/?orgId=1")
self.driver.get("http://localhost:3000/profile")
self.assertEqual(
self.driver.find_element(By.CLASS_NAME, "page-header__title").text,
self.user.name,
)
self.assertEqual(
self.driver.find_element(By.CSS_SELECTOR, "input[name=name]").get_attribute("value"),
self.user.name,
)
self.assertEqual(
self.driver.find_element(By.CSS_SELECTOR, "input[name=email]").get_attribute("value"),
self.user.email,
)
self.assertEqual(
self.driver.find_element(By.CSS_SELECTOR, "input[name=login]").get_attribute("value"),
self.user.email,
)

View File

@ -20,7 +20,7 @@ from tests.e2e.utils import SeleniumTestCase, retry
class TestProviderSAML(SeleniumTestCase):
"""test SAML Provider flow"""
def setup_client(self, provider: SAMLProvider, force_post: bool = False, **kwargs):
def setup_client(self, provider: SAMLProvider, force_post: bool = False):
"""Setup client saml-sp container which we test SAML against"""
metadata_url = (
self.url(
@ -40,7 +40,6 @@ class TestProviderSAML(SeleniumTestCase):
"SP_ENTITY_ID": provider.issuer,
"SP_SSO_BINDING": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
"SP_METADATA_URL": metadata_url,
**kwargs,
},
)
@ -112,74 +111,6 @@ class TestProviderSAML(SeleniumTestCase):
[self.user.email],
)
@retry()
@apply_blueprint(
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint(
"default/flow-default-provider-authorization-implicit-consent.yaml",
)
@apply_blueprint(
"system/providers-saml.yaml",
)
@reconcile_app("authentik_crypto")
def test_sp_initiated_implicit_post(self):
"""test SAML Provider flow SP-initiated flow (implicit consent)"""
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-implicit-consent"
)
provider: SAMLProvider = SAMLProvider.objects.create(
name="saml-test",
acs_url="http://localhost:9009/saml/acs",
audience="authentik-e2e",
issuer="authentik-e2e",
sp_binding=SAMLBindings.POST,
authorization_flow=authorization_flow,
signing_kp=create_test_cert(),
)
provider.property_mappings.set(SAMLPropertyMapping.objects.all())
provider.save()
Application.objects.create(
name="SAML",
slug="authentik-saml",
provider=provider,
)
self.setup_client(provider, True)
self.driver.get("http://localhost:9009")
self.login()
self.wait_for_url("http://localhost:9009/")
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],
[self.user.name],
)
self.assertEqual(
body["attr"][
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"
],
[self.user.username],
)
self.assertEqual(
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/username"],
[self.user.username],
)
self.assertEqual(
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/uid"],
[str(self.user.pk)],
)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"],
[self.user.email],
)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"],
[self.user.email],
)
@retry()
@apply_blueprint(
"default/flow-default-authentication-flow.yaml",
@ -519,81 +450,3 @@ class TestProviderSAML(SeleniumTestCase):
lambda driver: driver.current_url.startswith(should_url),
f"URL {self.driver.current_url} doesn't match expected URL {should_url}",
)
@retry()
@apply_blueprint(
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint(
"default/flow-default-provider-authorization-implicit-consent.yaml",
)
@apply_blueprint(
"system/providers-saml.yaml",
)
@reconcile_app("authentik_crypto")
def test_sp_initiated_implicit_post_buffer(self):
"""test SAML Provider flow SP-initiated flow (implicit consent)"""
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-implicit-consent"
)
provider: SAMLProvider = SAMLProvider.objects.create(
name="saml-test",
acs_url=f"http://{self.host}:9009/saml/acs",
audience="authentik-e2e",
issuer="authentik-e2e",
sp_binding=SAMLBindings.POST,
authorization_flow=authorization_flow,
signing_kp=create_test_cert(),
)
provider.property_mappings.set(SAMLPropertyMapping.objects.all())
provider.save()
Application.objects.create(
name="SAML",
slug="authentik-saml",
provider=provider,
)
self.setup_client(provider, True, SP_ROOT_URL=f"http://{self.host}:9009")
self.driver.get(self.live_server_url)
login_window = self.driver.current_window_handle
self.driver.switch_to.new_window("tab")
client_window = self.driver.current_window_handle
# We need to access the SP on the same host as the IdP for SameSite cookies
self.driver.get(f"http://{self.host}:9009")
self.driver.switch_to.window(login_window)
self.login()
self.driver.switch_to.window(client_window)
self.wait_for_url(f"http://{self.host}:9009/")
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],
[self.user.name],
)
self.assertEqual(
body["attr"][
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"
],
[self.user.username],
)
self.assertEqual(
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/username"],
[self.user.username],
)
self.assertEqual(
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/uid"],
[str(self.user.pk)],
)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"],
[self.user.email],
)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"],
[self.user.email],
)

View File

@ -4,6 +4,7 @@
* @import { ThemeVarsPartial } from "storybook/internal/theming";
*/
import { createUIThemeEffect, resolveUITheme } from "@goauthentik/web/common/theme.ts";
import { addons } from "@storybook/manager-api";
import { create } from "@storybook/theming/create";

View File

@ -11,6 +11,7 @@
* } from "esbuild"
*/
import { MonoRepoRoot } from "@goauthentik/core/paths/node";
import * as fs from "node:fs/promises";
import * as path from "node:path";

View File

@ -1,4 +1,5 @@
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
import tseslint from "typescript-eslint";
// @ts-check

71
web/package-lock.json generated
View File

@ -34,7 +34,6 @@
"@sentry/browser": "^9.28.1",
"@spotlightjs/spotlight": "^3.0.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"change-case": "^5.4.4",
"chart.js": "^4.4.9",
"chartjs-adapter-date-fns": "^3.0.0",
@ -66,6 +65,7 @@
"trusted-types": "^2.0.0",
"ts-pattern": "^5.7.1",
"unist-util-visit": "^5.0.0",
"webauthn-polyfills": "^0.1.7",
"webcomponent-qr-code": "^1.2.0",
"yaml": "^2.8.0"
},
@ -74,7 +74,7 @@
"@goauthentik/core": "^1.0.0",
"@goauthentik/esbuild-plugin-live-reload": "^1.0.4",
"@goauthentik/eslint-config": "^1.0.5",
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/prettier-config": "^2.0.0",
"@goauthentik/tsconfig": "^1.0.4",
"@hcaptcha/types": "^1.0.4",
"@lit/localize-tools": "^0.8.0",
@ -1773,9 +1773,9 @@
}
},
"node_modules/@goauthentik/prettier-config": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.5.tgz",
"integrity": "sha512-3W1uJvhzBPerDao53hSXhNzB7Ev8DbGYh+gVkuku1FaUZGBpiwD/6U3ah4sny8NoRiObGQ1geF4dhNLtlRbC/Q==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-2.0.0.tgz",
"integrity": "sha512-W+PAea+pH511lC4omoyeNGkFS+/AytrCMdtN7dIUJhaufMppYHLagyvurhyb5mUCg/j4DphCcunguj6dkiRVRw==",
"dev": true,
"license": "MIT",
"engines": {
@ -4685,6 +4685,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/@simplewebauthn/types": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/@simplewebauthn/types/-/types-11.0.0.tgz",
"integrity": "sha512-b2o0wC5u2rWts31dTgBkAtSNKGX0cvL6h8QedNsKmj8O4QoLFQFR3DBVBUlpyVEhYKA+mXGUaXbcOc4JdQ3HzA==",
"license": "MIT"
},
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@ -7278,6 +7284,12 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
},
"node_modules/@types/ua-parser-js": {
"version": "0.7.39",
"resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.39.tgz",
"integrity": "sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg==",
"license": "MIT"
},
"node_modules/@types/unist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
@ -12193,8 +12205,7 @@
"node_modules/compare-versions": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
"integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==",
"dev": true
"integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg=="
},
"node_modules/compatx": {
"version": "0.1.8",
@ -27117,6 +27128,32 @@
"node": ">=8"
}
},
"node_modules/ua-parser-js": {
"version": "1.0.40",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz",
"integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/ua-parser-js"
},
{
"type": "paypal",
"url": "https://paypal.me/faisalman"
},
{
"type": "github",
"url": "https://github.com/sponsors/faisalman"
}
],
"license": "MIT",
"bin": {
"ua-parser-js": "script/cli.js"
},
"engines": {
"node": "*"
}
},
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
@ -28460,6 +28497,18 @@
"license": "MIT",
"optional": true
},
"node_modules/webauthn-polyfills": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/webauthn-polyfills/-/webauthn-polyfills-0.1.7.tgz",
"integrity": "sha512-tOA5KPHhN8j8EBA9I90bYmsEc6CAKd1SbWJzmVn0hmTfvfiNJLGGzRPlSW4fKiQPm8BC6doPQC0CnaQdhxsL3Q==",
"license": "Apache-2.0",
"dependencies": {
"@simplewebauthn/types": "^11.0.0",
"@types/ua-parser-js": "^0.7.39",
"compare-versions": "^6.1.1",
"ua-parser-js": "^1.0.39"
}
},
"node_modules/webcomponent-qr-code": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/webcomponent-qr-code/-/webcomponent-qr-code-1.2.0.tgz",
@ -29363,7 +29412,7 @@
"version": "1.0.0",
"license": "MIT",
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/prettier-config": "^2.0.0",
"@goauthentik/tsconfig": "^1.0.4",
"@types/node": "^22.15.21",
"prettier": "^3.3.3",
@ -29398,7 +29447,7 @@
"find-free-ports": "^3.1.1"
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/prettier-config": "^2.0.0",
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/node": "^22.15.21",
@ -29455,11 +29504,11 @@
"license": "MIT",
"dependencies": {
"@goauthentik/api": "^2024.6.0-1719577139",
"base64-js": "^1.5.1",
"bootstrap": "^4.6.1",
"formdata-polyfill": "^4.0.10",
"jquery": "^3.7.1",
"weakmap-polyfill": "^2.0.4"
"weakmap-polyfill": "^2.0.4",
"webauthn-polyfills": "^0.1.7"
},
"devDependencies": {
"@goauthentik/core": "^1.0.0",

View File

@ -105,7 +105,6 @@
"@sentry/browser": "^9.28.1",
"@spotlightjs/spotlight": "^3.0.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"change-case": "^5.4.4",
"chart.js": "^4.4.9",
"chartjs-adapter-date-fns": "^3.0.0",
@ -137,6 +136,7 @@
"trusted-types": "^2.0.0",
"ts-pattern": "^5.7.1",
"unist-util-visit": "^5.0.0",
"webauthn-polyfills": "^0.1.7",
"webcomponent-qr-code": "^1.2.0",
"yaml": "^2.8.0"
},
@ -145,7 +145,7 @@
"@goauthentik/core": "^1.0.0",
"@goauthentik/esbuild-plugin-live-reload": "^1.0.4",
"@goauthentik/eslint-config": "^1.0.5",
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/prettier-config": "^2.0.0",
"@goauthentik/tsconfig": "^1.0.4",
"@hcaptcha/types": "^1.0.4",
"@lit/localize-tools": "^0.8.0",

View File

@ -45,7 +45,7 @@
}
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/prettier-config": "^2.0.0",
"@goauthentik/tsconfig": "^1.0.4",
"@types/node": "^22.15.21",
"prettier": "^3.3.3",

View File

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

View File

@ -12,6 +12,7 @@ yarn add -D @goauthentik/esbuild-plugin-live-reload
```js
import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload";
import esbuild from "esbuild";
const NodeEnvironment = process.env.NODE_ENV || "development";

View File

@ -12,11 +12,11 @@
"find-free-ports": "^3.1.1"
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/prettier-config": "^2.0.0",
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/node": "^22.15.21",
"esbuild": "^0.25.4",
"esbuild": "^0.25.5",
"prettier": "^3.5.3",
"prettier-plugin-packagejson": "^2.5.14",
"typedoc": "^0.28.5",
@ -27,7 +27,7 @@
"node": ">=22"
},
"peerDependencies": {
"esbuild": "^0.25.4"
"esbuild": "^0.25.5"
}
},
"node_modules/@babel/code-frame": {
@ -586,9 +586,9 @@
}
},
"node_modules/@goauthentik/prettier-config": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.5.tgz",
"integrity": "sha512-3W1uJvhzBPerDao53hSXhNzB7Ev8DbGYh+gVkuku1FaUZGBpiwD/6U3ah4sny8NoRiObGQ1geF4dhNLtlRbC/Q==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-2.0.0.tgz",
"integrity": "sha512-W+PAea+pH511lC4omoyeNGkFS+/AytrCMdtN7dIUJhaufMppYHLagyvurhyb5mUCg/j4DphCcunguj6dkiRVRw==",
"dev": true,
"license": "MIT",
"engines": {

View File

@ -31,7 +31,7 @@
"find-free-ports": "^3.1.1"
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/prettier-config": "^2.0.0",
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/node": "^22.15.21",

View File

@ -11,11 +11,11 @@
},
"dependencies": {
"@goauthentik/api": "^2024.6.0-1719577139",
"base64-js": "^1.5.1",
"bootstrap": "^4.6.1",
"formdata-polyfill": "^4.0.10",
"jquery": "^3.7.1",
"weakmap-polyfill": "^2.0.4"
"weakmap-polyfill": "^2.0.4",
"webauthn-polyfills": "^0.1.7"
},
"devDependencies": {
"@goauthentik/core": "^1.0.0",

View File

@ -1,7 +1,9 @@
import { fromByteArray } from "base64-js";
import "formdata-polyfill";
import $ from "jquery";
import "weakmap-polyfill";
import "webauthn-polyfills";
import {
type AuthenticatorValidationChallenge,
@ -257,47 +259,9 @@ class AutosubmitStage extends Stage<AutosubmitChallenge> {
}
}
export interface Assertion {
id: string;
rawId: string;
type: string;
registrationClientExtensions: string;
response: {
clientDataJSON: string;
attestationObject: string;
};
}
export interface AuthAssertion {
id: string;
rawId: string;
type: string;
assertionClientExtensions: string;
response: {
clientDataJSON: string;
authenticatorData: string;
signature: string;
userHandle: string | null;
};
}
class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge> {
deviceChallenge?: DeviceChallenge;
b64enc(buf: Uint8Array): string {
return fromByteArray(buf).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
}
b64RawEnc(buf: Uint8Array): string {
return fromByteArray(buf).replace(/\+/g, "-").replace(/\//g, "_");
}
u8arr(input: string): Uint8Array {
return Uint8Array.from(atob(input.replace(/_/g, "/").replace(/-/g, "+")), (c) =>
c.charCodeAt(0),
);
}
checkWebAuthnSupport(): boolean {
if ("credentials" in navigator) {
return true;
@ -310,98 +274,6 @@ class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge>
return false;
}
/**
* Transforms items in the credentialCreateOptions generated on the server
* into byte arrays expected by the navigator.credentials.create() call
*/
transformCredentialCreateOptions(
credentialCreateOptions: PublicKeyCredentialCreationOptions,
userId: string,
): PublicKeyCredentialCreationOptions {
const user = credentialCreateOptions.user;
// Because json can't contain raw bytes, the server base64-encodes the User ID
// So to get the base64 encoded byte array, we first need to convert it to a regular
// string, then a byte array, re-encode it and wrap that in an array.
const stringId = decodeURIComponent(window.atob(userId));
user.id = this.u8arr(this.b64enc(this.u8arr(stringId)));
const challenge = this.u8arr(credentialCreateOptions.challenge.toString());
return Object.assign({}, credentialCreateOptions, {
challenge,
user,
});
}
/**
* Transforms the binary data in the credential into base64 strings
* for posting to the server.
* @param {PublicKeyCredential} newAssertion
*/
transformNewAssertionForServer(newAssertion: PublicKeyCredential): Assertion {
const attObj = new Uint8Array(
(newAssertion.response as AuthenticatorAttestationResponse).attestationObject,
);
const clientDataJSON = new Uint8Array(newAssertion.response.clientDataJSON);
const rawId = new Uint8Array(newAssertion.rawId);
const registrationClientExtensions = newAssertion.getClientExtensionResults();
return {
id: newAssertion.id,
rawId: this.b64enc(rawId),
type: newAssertion.type,
registrationClientExtensions: JSON.stringify(registrationClientExtensions),
response: {
clientDataJSON: this.b64enc(clientDataJSON),
attestationObject: this.b64enc(attObj),
},
};
}
transformCredentialRequestOptions(
credentialRequestOptions: PublicKeyCredentialRequestOptions,
): PublicKeyCredentialRequestOptions {
const challenge = this.u8arr(credentialRequestOptions.challenge.toString());
const allowCredentials = (credentialRequestOptions.allowCredentials || []).map(
(credentialDescriptor) => {
const id = this.u8arr(credentialDescriptor.id.toString());
return Object.assign({}, credentialDescriptor, { id });
},
);
return Object.assign({}, credentialRequestOptions, {
challenge,
allowCredentials,
});
}
/**
* Encodes the binary data in the assertion into strings for posting to the server.
* @param {PublicKeyCredential} newAssertion
*/
transformAssertionForServer(newAssertion: PublicKeyCredential): AuthAssertion {
const response = newAssertion.response as AuthenticatorAssertionResponse;
const authData = new Uint8Array(response.authenticatorData);
const clientDataJSON = new Uint8Array(response.clientDataJSON);
const rawId = new Uint8Array(newAssertion.rawId);
const sig = new Uint8Array(response.signature);
const assertionClientExtensions = newAssertion.getClientExtensionResults();
return {
id: newAssertion.id,
rawId: this.b64enc(rawId),
type: newAssertion.type,
assertionClientExtensions: JSON.stringify(assertionClientExtensions),
response: {
clientDataJSON: this.b64RawEnc(clientDataJSON),
signature: this.b64RawEnc(sig),
authenticatorData: this.b64RawEnc(authData),
userHandle: null,
},
};
}
render() {
if (this.challenge.deviceChallenges.length === 1) {
this.deviceChallenge = this.challenge.deviceChallenges[0];
@ -505,8 +377,8 @@ class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge>
`);
navigator.credentials
.get({
publicKey: this.transformCredentialRequestOptions(
this.deviceChallenge?.challenge as PublicKeyCredentialRequestOptions,
publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(
this.deviceChallenge?.challenge as PublicKeyCredentialRequestOptionsJSON,
),
})
.then((assertion) => {
@ -514,15 +386,9 @@ class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge>
throw new Error("No assertion");
}
try {
// we now have an authentication assertion! encode the byte arrays contained
// in the assertion data as strings for posting to the server
const transformedAssertionForServer = this.transformAssertionForServer(
assertion as PublicKeyCredential,
);
// post the assertion to the server for verification.
this.executor.submit({
webauthn: transformedAssertionForServer,
webauthn: (assertion as PublicKeyCredential).toJSON(),
});
} catch (err) {
throw new Error(`Error when validating assertion on server: ${err}`);

View File

@ -4,6 +4,7 @@
* @runtime node
*/
import { DistDirectoryName } from "#paths";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";

View File

@ -13,6 +13,7 @@
* @import { Stats } from "fs";
*/
import { PackageRoot } from "#paths/node";
import { spawnSync } from "node:child_process";
import { readFileSync, statSync } from "node:fs";
import path from "node:path";

View File

@ -7,9 +7,11 @@
import { mdxPlugin } from "#bundler/mdx-plugin/node";
import { createBundleDefinitions } from "#bundler/utils/node";
import { DistDirectory, EntryPoint, PackageRoot } from "#paths/node";
import { NodeEnvironment } from "@goauthentik/core/environment/node";
import { MonoRepoRoot, resolvePackage } from "@goauthentik/core/paths/node";
import { readBuildIdentifier } from "@goauthentik/core/version/node";
import { deepmerge } from "deepmerge-ts";
import esbuild from "esbuild";
import copy from "esbuild-plugin-copy";

View File

@ -7,6 +7,7 @@
* @import { Locale } from "@lit/localize-tools/src/types/locale.js"
*/
import { PackageRoot } from "#paths/node";
import { readFileSync } from "node:fs";
import path from "node:path";
import pseudolocale from "pseudolocale";

View File

@ -1,10 +1,15 @@
import { WithBrandConfig } from "#elements/mixins/branding";
import { WithLicenseSummary } from "#elements/mixins/license";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { globalAK } from "@goauthentik/common/global";
import { WithBrandConfig } from "#elements/mixins/branding";
import { WithLicenseSummary } from "#elements/mixins/license";
import "@goauthentik/elements/EmptyState";
import { ModalButton } from "@goauthentik/elements/buttons/ModalButton";
import { AdminApi, CapabilitiesEnum, LicenseSummaryStatusEnum } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { TemplateResult, css, html } from "lit";
import { customElement } from "lit/decorators.js";
@ -12,8 +17,6 @@ import { until } from "lit/directives/until.js";
import PFAbout from "@patternfly/patternfly/components/AboutModalBox/about-modal-box.css";
import { AdminApi, CapabilitiesEnum, LicenseSummaryStatusEnum } from "@goauthentik/api";
@customElement("ak-about-modal")
export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton)) {
static get styles() {

View File

@ -1,4 +1,5 @@
import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
import { spread } from "@open-wc/lit-helpers";
import { msg } from "@lit/localize";

View File

@ -1,12 +1,17 @@
import "#admin/AdminInterface/AboutModal";
import type { AboutModal } from "#admin/AdminInterface/AboutModal";
import { ROUTES } from "#admin/Routes";
import { EVENT_API_DRAWER_TOGGLE, EVENT_NOTIFICATION_DRAWER_TOGGLE } from "#common/constants";
import { configureSentry } from "#common/sentry/index";
import { me } from "#common/users";
import { WebsocketClient } from "#common/ws";
import { SidebarToggleEventDetail } from "#components/ak-page-header";
import { AuthenticatedInterface } from "#elements/AuthenticatedInterface";
import { SidebarToggleEventDetail } from "#components/ak-page-header";
import type { AboutModal } from "#admin/AdminInterface/AboutModal";
import { ROUTES } from "#admin/Routes";
import "#elements/ak-locale-context/ak-locale-context";
import "#elements/banner/EnterpriseStatusBanner";
import "#elements/banner/EnterpriseStatusBanner";
@ -14,14 +19,20 @@ import "#elements/banner/VersionBanner";
import "#elements/banner/VersionBanner";
import "#elements/messages/MessageContainer";
import "#elements/messages/MessageContainer";
import { WithCapabilitiesConfig } from "#elements/mixins/capabilities";
import "#elements/notifications/APIDrawer";
import "#elements/notifications/NotificationDrawer";
import { getURLParam, updateURLParams } from "#elements/router/RouteMatch";
import "#elements/router/RouterOutlet";
import "#elements/sidebar/Sidebar";
import "#elements/sidebar/SidebarItem";
import { CapabilitiesEnum, SessionUser, UiThemeEnum } from "@goauthentik/api";
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
import { customElement, eventOptions, property, query } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
@ -32,8 +43,6 @@ import PFNav from "@patternfly/patternfly/components/Nav/nav.css";
import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { CapabilitiesEnum, SessionUser, UiThemeEnum } from "@goauthentik/api";
import {
AdminSidebarEnterpriseEntries,
AdminSidebarEntries,

View File

@ -1,9 +1,14 @@
import { DEFAULT_CONFIG } from "#common/api/config";
import { parseAPIResponseError, pluckErrorDetail } from "#common/errors/network";
import { MessageLevel } from "#common/messages";
import "#components/ak-page-header";
import { AKElement } from "#elements/Base";
import { showMessage } from "#elements/messages/MessageContainer";
import { AdminApi } from "@goauthentik/api";
import * as Sentry from "@sentry/browser";
import { CSSResult, TemplateResult, html } from "lit";
@ -15,8 +20,6 @@ import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { AdminApi } from "@goauthentik/api";
@customElement("ak-admin-debug-page")
export class DebugPage extends AKElement {
static get styles(): CSSResult[] {

View File

@ -1,4 +1,5 @@
import "@goauthentik/admin/admin-overview/AdminOverviewPage";
import { ID_REGEX, Route, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
import { html } from "lit";

View File

@ -8,14 +8,23 @@ import "#admin/admin-overview/cards/WorkerStatusCard";
import "#admin/admin-overview/charts/AdminLoginAuthorizeChart";
import "#admin/admin-overview/charts/OutpostStatusChart";
import "#admin/admin-overview/charts/SyncStatusChart";
import { me } from "#common/users";
import "#components/ak-page-header";
import { AKElement } from "#elements/Base";
import "#elements/cards/AggregatePromiseCard";
import type { QuickAction } from "#elements/cards/QuickActionsCard";
import "#elements/cards/QuickActionsCard";
import { WithLicenseSummary } from "#elements/mixins/license";
import { paramURL } from "#elements/router/RouterOutlet";
import { SessionUser } from "@goauthentik/api";
import { createReleaseNotesURL } from "@goauthentik/core/version";
import { msg, str } from "@lit/localize";
@ -29,8 +38,6 @@ import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { SessionUser } from "@goauthentik/api";
const AdminOverviewBase = WithLicenseSummary(AKElement);
@customElement("ak-admin-overview")

View File

@ -1,8 +1,12 @@
import "#admin/admin-overview/charts/AdminModelPerDay";
import "#components/ak-page-header";
import { AKElement } from "#elements/Base";
import "#elements/cards/AggregatePromiseCard";
import { EventActions, EventsEventsVolumeListRequest } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement } from "lit/decorators.js";
@ -13,8 +17,6 @@ import PFList from "@patternfly/patternfly/components/List/list.css";
import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import { EventActions, EventsEventsVolumeListRequest } from "@goauthentik/api";
@customElement("ak-admin-dashboard-users")
export class DashboardUserPage extends AKElement {
static get styles(): CSSResult[] {

View File

@ -1,15 +1,17 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/Spinner";
import { EventTopPerUser, EventsApi } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFTable from "@patternfly/patternfly/components/Table/table.css";
import { EventTopPerUser, EventsApi } from "@goauthentik/api";
@customElement("ak-top-applications-table")
export class TopApplicationsTable extends AKElement {
@property({ attribute: false })

View File

@ -5,6 +5,7 @@ import {
parseAPIResponseError,
pluckErrorDetail,
} from "@goauthentik/common/errors/network";
import { AggregateCard } from "@goauthentik/elements/cards/AggregateCard";
import { msg } from "@lit/localize";

View File

@ -1,15 +1,16 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import {
AdminStatus,
AdminStatusCard,
} from "@goauthentik/admin/admin-overview/cards/AdminStatusCard";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AdminApi, SystemInfo } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { AdminApi, SystemInfo } from "@goauthentik/api";
type StatusContent = { icon: string; message: TemplateResult };
@customElement("ak-admin-fips-status-system")

View File

@ -1,25 +1,28 @@
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventWithContext } from "@goauthentik/common/events";
import { actionToLabel } from "@goauthentik/common/labels";
import { formatElapsedTime } from "@goauthentik/common/temporal";
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
import "@goauthentik/components/ak-event-info";
import "@goauthentik/elements/Tabs";
import "@goauthentik/elements/buttons/Dropdown";
import "@goauthentik/elements/buttons/ModalButton";
import "@goauthentik/elements/buttons/SpinnerButton";
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { Table, TableColumn } from "@goauthentik/elements/table/Table";
import { SlottedTemplateResult } from "@goauthentik/elements/types";
import { Event, EventsApi } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFCard from "@patternfly/patternfly/components/Card/card.css";
import { Event, EventsApi } from "@goauthentik/api";
@customElement("ak-recent-events")
export class RecentEventsCard extends Table<Event> {
@property()

View File

@ -1,15 +1,16 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import {
AdminStatus,
AdminStatusCard,
} from "@goauthentik/admin/admin-overview/cards/AdminStatusCard";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AdminApi, OutpostsApi, SystemInfo } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { AdminApi, OutpostsApi, SystemInfo } from "@goauthentik/api";
@customElement("ak-admin-status-system")
export class SystemStatusCard extends AdminStatusCard<SystemInfo> {
now?: Date;

View File

@ -1,15 +1,16 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import {
AdminStatus,
AdminStatusCard,
} from "@goauthentik/admin/admin-overview/cards/AdminStatusCard";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AdminApi, Version } from "@goauthentik/api";
import { msg, str } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import { AdminApi, Version } from "@goauthentik/api";
@customElement("ak-admin-status-version")
export class VersionStatusCard extends AdminStatusCard<Version> {
icon = "pf-icon pf-icon-bundle";

View File

@ -1,15 +1,16 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import {
AdminStatus,
AdminStatusCard,
} from "@goauthentik/admin/admin-overview/cards/AdminStatusCard";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AdminApi, Worker } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import { AdminApi, Worker } from "@goauthentik/api";
@customElement("ak-admin-status-card-workers")
export class WorkersStatusCard extends AdminStatusCard<Worker[]> {
icon = "pf-icon pf-icon-server";

View File

@ -1,12 +1,14 @@
import { EventChart } from "#elements/charts/EventChart";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventChart } from "#elements/charts/EventChart";
import { EventActions, EventVolume, EventsApi } from "@goauthentik/api";
import { ChartData, ChartDataset } from "chart.js";
import { msg } from "@lit/localize";
import { customElement } from "lit/decorators.js";
import { EventActions, EventVolume, EventsApi } from "@goauthentik/api";
@customElement("ak-charts-admin-login-authorization")
export class AdminLoginAuthorizeChart extends EventChart {
async apiRequest(): Promise<EventVolume[]> {

View File

@ -1,9 +1,6 @@
import { EventChart } from "#elements/charts/EventChart";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { ChartData } from "chart.js";
import { msg } from "@lit/localize";
import { customElement, property } from "lit/decorators.js";
import { EventChart } from "#elements/charts/EventChart";
import {
EventActions,
@ -12,6 +9,11 @@ import {
EventsEventsVolumeListRequest,
} from "@goauthentik/api";
import { ChartData } from "chart.js";
import { msg } from "@lit/localize";
import { customElement, property } from "lit/decorators.js";
@customElement("ak-charts-admin-model-per-day")
export class AdminModelPerDay extends EventChart {
@property()

View File

@ -1,15 +1,19 @@
import { actionToColor } from "#elements/charts/EventChart";
import { SummarizedSyncStatus } from "@goauthentik/admin/admin-overview/charts/SyncStatusChart";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { actionToColor } from "#elements/charts/EventChart";
import { AKChart } from "@goauthentik/elements/charts/Chart";
import { SummarizedSyncStatus } from "@goauthentik/admin/admin-overview/charts/SyncStatusChart";
import "@goauthentik/elements/forms/ConfirmationForm";
import { EventActions, OutpostsApi } from "@goauthentik/api";
import { ChartData, ChartOptions } from "chart.js";
import { msg } from "@lit/localize";
import { customElement } from "lit/decorators.js";
import { EventActions, OutpostsApi } from "@goauthentik/api";
@customElement("ak-admin-status-chart-outpost")
export class OutpostStatusChart extends AKChart<SummarizedSyncStatus[]> {
getChartType(): string {

View File

@ -1,12 +1,11 @@
import { actionToColor } from "#elements/charts/EventChart";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AKChart } from "@goauthentik/elements/charts/Chart";
import "@goauthentik/elements/forms/ConfirmationForm";
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { ChartData, ChartOptions } from "chart.js";
import { msg } from "@lit/localize";
import { customElement } from "lit/decorators.js";
import { actionToColor } from "#elements/charts/EventChart";
import { AKChart } from "@goauthentik/elements/charts/Chart";
import "@goauthentik/elements/forms/ConfirmationForm";
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import {
EventActions,
@ -16,6 +15,11 @@ import {
SystemTaskStatusEnum,
} from "@goauthentik/api";
import { ChartData, ChartOptions } from "chart.js";
import { msg } from "@lit/localize";
import { customElement } from "lit/decorators.js";
export interface SummarizedSyncStatus {
healthy: number;
failed: number;

View File

@ -1,5 +1,8 @@
import { AkControlElement } from "@goauthentik/elements/AkControlElement.js";
import { type Spread } from "@goauthentik/elements/types";
import { FooterLink } from "@goauthentik/api";
import { spread } from "@open-wc/lit-helpers";
import { msg } from "@lit/localize";
@ -11,8 +14,6 @@ import PFFormControl from "@patternfly/patternfly/components/FormControl/form-co
import PFInputGroup from "@patternfly/patternfly/components/InputGroup/input-group.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { FooterLink } from "@goauthentik/api";
export interface IFooterLinkInput {
footerLink: FooterLink;
}

View File

@ -1,15 +1,20 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-number-input";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input";
import "@goauthentik/elements/ak-array-input.js";
import { Form } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect";
import "@goauthentik/elements/utils/TimeDeltaHelp";
import { AdminApi, FooterLink, Settings, SettingsRequest } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property } from "lit/decorators.js";
@ -17,9 +22,8 @@ import { ifDefined } from "lit/directives/if-defined.js";
import PFList from "@patternfly/patternfly/components/List/list.css";
import { AdminApi, FooterLink, Settings, SettingsRequest } from "@goauthentik/api";
import "./AdminSettingsFooterLinks.js";
import { IFooterLinkInput, akFooterLinkInput } from "./AdminSettingsFooterLinks.js";
const DEFAULT_REPUTATION_LOWER_LIMIT = -5;

View File

@ -1,9 +1,14 @@
import "#admin/admin-settings/AdminSettingsForm";
import { AdminSettingsForm } from "#admin/admin-settings/AdminSettingsForm";
import { DEFAULT_CONFIG } from "#common/api/config";
import { AdminSettingsForm } from "#admin/admin-settings/AdminSettingsForm";
import "#components/ak-page-header";
import "#components/events/ObjectChangelog";
import { AKElement } from "#elements/Base";
import "#elements/CodeMirror";
import "#elements/EmptyState";
import "#elements/Tabs";
@ -11,6 +16,8 @@ import "#elements/buttons/ModalButton";
import "#elements/buttons/SpinnerButton/ak-spinner-button";
import "#elements/forms/ModalForm";
import { AdminApi, Settings } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { html, nothing } from "lit";
import { customElement, query, state } from "lit/decorators.js";
@ -26,8 +33,6 @@ import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { AdminApi, Settings } from "@goauthentik/api";
@customElement("ak-admin-settings")
export class AdminSettingsPage extends AKElement {
static get styles() {

View File

@ -1,10 +1,12 @@
import "@goauthentik/elements/messages/MessageContainer";
import { Meta, StoryObj, WebComponentsRenderer } from "@storybook/web-components";
import { DecoratorFunction } from "storybook/internal/types";
import { html } from "lit";
import { FooterLinkInput } from "../AdminSettingsFooterLinks.js";
import "../AdminSettingsFooterLinks.js";
// eslint-disable-next-line @typescript-eslint/no-explicit-any

View File

@ -1,4 +1,5 @@
import { render } from "@goauthentik/elements/tests/utils.js";
import { $, expect } from "@wdio/globals";
import { html } from "lit";

View File

@ -1,12 +1,14 @@
import { EventChart } from "#elements/charts/EventChart";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventChart } from "#elements/charts/EventChart";
import { EventActions, EventVolume, EventsApi } from "@goauthentik/api";
import { ChartData } from "chart.js";
import { msg } from "@lit/localize";
import { customElement, property } from "lit/decorators.js";
import { EventActions, EventVolume, EventsApi } from "@goauthentik/api";
@customElement("ak-charts-application-authorize")
export class ApplicationAuthorizeChart extends EventChart {
@property({ attribute: "application-id" })

View File

@ -1,16 +1,13 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/events/LogViewer";
import { Form } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import {
Application,
CoreApi,
@ -19,6 +16,12 @@ import {
User,
} from "@goauthentik/api";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
@customElement("ak-application-check-access-form")
export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
@property({ attribute: false })

View File

@ -1,8 +1,12 @@
import { CapabilitiesEnum, WithCapabilitiesConfig } from "#elements/mixins/capabilities";
import "@goauthentik/admin/applications/ProviderSelectModal";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { iconHelperText } from "@goauthentik/admin/helperText";
import { policyEngineModes } from "@goauthentik/admin/policies/PolicyEngineModes";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-file-input";
import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-switch-input";
@ -12,19 +16,21 @@ import "@goauthentik/elements/Alert";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/ModalForm";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/ProxyForm";
import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect/ak-search-select";
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
import { Application, CoreApi, Provider } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { TemplateResult, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { Application, CoreApi, Provider } from "@goauthentik/api";
import "./components/ak-backchannel-input";
import "./components/ak-provider-search-input";

View File

@ -1,16 +1,23 @@
import "#admin/applications/ApplicationForm";
import { DEFAULT_CONFIG } from "#common/api/config";
import "#elements/AppIcon";
import "#elements/ak-mdx/ak-mdx";
import "#elements/buttons/SpinnerButton/ak-spinner-button";
import "#elements/forms/DeleteBulkForm";
import "#elements/forms/ModalForm";
import { WithBrandConfig } from "#elements/mixins/branding";
import { getURLParam } from "#elements/router/RouteMatch";
import { PaginatedResponse } from "#elements/table/Table";
import { TableColumn } from "#elements/table/Table";
import { TablePage } from "#elements/table/TablePage";
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
import { Application, CoreApi, PoliciesApi } from "@goauthentik/api";
import MDApplication from "~docs/add-secure-apps/applications/index.md";
import { msg, str } from "@lit/localize";
@ -20,8 +27,6 @@ import { ifDefined } from "lit/directives/if-defined.js";
import PFCard from "@patternfly/patternfly/components/Card/card.css";
import { Application, CoreApi, PoliciesApi } from "@goauthentik/api";
import "./ApplicationWizardHint.js";
export const applicationListStyle = css`

View File

@ -4,16 +4,27 @@ import "#admin/applications/ApplicationForm";
import "#admin/applications/entitlements/ApplicationEntitlementPage";
import "#admin/policies/BoundPoliciesList";
import "#admin/rbac/ObjectPermissionsPage";
import { DEFAULT_CONFIG } from "#common/api/config";
import { PFSize } from "#common/enums";
import "#components/ak-page-header";
import "#components/events/ObjectChangelog";
import "#elements/AppIcon";
import { AKElement } from "#elements/Base";
import "#elements/EmptyState";
import "#elements/Tabs";
import "#elements/buttons/SpinnerButton/ak-spinner-button";
import {
Application,
CoreApi,
OutpostsApi,
RbacPermissionsAssignedByUsersListModelEnum,
} from "@goauthentik/api";
import { msg } from "@lit/localize";
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
@ -29,13 +40,6 @@ import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import {
Application,
CoreApi,
OutpostsApi,
RbacPermissionsAssignedByUsersListModelEnum,
} from "@goauthentik/api";
@customElement("ak-application-view")
export class ApplicationViewPage extends AKElement {
@property({ type: String })

View File

@ -1,13 +1,18 @@
import "@goauthentik/admin/applications/wizard/ak-application-wizard";
import {
ShowHintController,
ShowHintControllerHost,
} from "@goauthentik/components/ak-hint/ShowHintController";
import "@goauthentik/components/ak-hint/ak-hint";
import "@goauthentik/components/ak-hint/ak-hint-body";
import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/Label";
import "@goauthentik/elements/buttons/ActionButton/ak-action-button";
import { getURLParam } from "@goauthentik/elements/router/RouteMatch";
import { msg } from "@lit/localize";

View File

@ -1,15 +1,17 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/elements/buttons/SpinnerButton";
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table";
import { TableModal } from "@goauthentik/elements/table/TableModal";
import { Provider, ProvidersApi } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { Provider, ProvidersApi } from "@goauthentik/api";
@customElement("ak-provider-select-table")
export class ProviderSelectModal extends TableModal<Provider> {
checkbox = true;

View File

@ -1,15 +1,17 @@
import "@goauthentik/admin/applications/ProviderSelectModal";
import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/chips/Chip";
import "@goauthentik/elements/chips/ChipGroup";
import { Provider } from "@goauthentik/api";
import { TemplateResult, html, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { map } from "lit/directives/map.js";
import { Provider } from "@goauthentik/api";
@customElement("ak-backchannel-providers-input")
export class AkBackchannelProvidersInput extends AKElement {
// Render into the lightDOM. This effectively erases the shadowDOM nature of this component, but

View File

@ -1,13 +1,15 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { groupBy } from "@goauthentik/common/utils";
import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/forms/SearchSelect";
import { Provider, ProvidersAllListRequest, ProvidersApi } from "@goauthentik/api";
import { html, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";
import { Provider, ProvidersAllListRequest, ProvidersApi } from "@goauthentik/api";
const renderElement = (item: Provider) => item.name;
const renderValue = (item: Provider | undefined) => item?.pk;
const doGroupBy = (items: Provider[]) => groupBy(items, (item) => item.verboseName);

View File

@ -1,10 +1,18 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect";
import { ApplicationEntitlement, CoreApi } from "@goauthentik/api";
import YAML from "yaml";
import { msg } from "@lit/localize";
@ -14,8 +22,6 @@ import { customElement, property } from "lit/decorators.js";
import PFContent from "@patternfly/patternfly/components/Content/content.css";
import { ApplicationEntitlement, CoreApi } from "@goauthentik/api";
@customElement("ak-application-entitlement-form")
export class ApplicationEntitlementForm extends ModelForm<ApplicationEntitlement, string> {
async loadInstance(pk: string): Promise<ApplicationEntitlement> {

View File

@ -1,28 +1,33 @@
import "@goauthentik/admin/applications/entitlements/ApplicationEntitlementForm";
import "@goauthentik/admin/policies/BoundPoliciesList";
import { PolicyBindingCheckTarget } from "@goauthentik/admin/policies/utils";
import "@goauthentik/admin/rbac/ObjectPermissionModal";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { PFSize } from "@goauthentik/common/enums";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/Tabs";
import "@goauthentik/elements/forms/DeleteBulkForm";
import "@goauthentik/elements/forms/ModalForm";
import "@goauthentik/elements/forms/ProxyForm";
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { Table, TableColumn } from "@goauthentik/elements/table/Table";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import {
ApplicationEntitlement,
CoreApi,
RbacPermissionsAssignedByUsersListModelEnum,
} from "@goauthentik/api";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
@customElement("ak-application-entitlements-list")
export class ApplicationEntitlementsPage extends Table<ApplicationEntitlement> {
@property()

View File

@ -1,18 +1,20 @@
import { styles } from "@goauthentik/admin/applications/wizard/ApplicationWizardFormStepStyles.css.js";
import { KeyUnknown, serializeForm } from "@goauthentik/elements/forms/Form";
import { HorizontalFormElement } from "@goauthentik/elements/forms/HorizontalFormElement";
import { WizardStep } from "@goauthentik/components/ak-wizard/WizardStep.js";
import {
NavigationEventInit,
WizardNavigationEvent,
WizardUpdateEvent,
} from "@goauthentik/components/ak-wizard/events";
import { KeyUnknown, serializeForm } from "@goauthentik/elements/forms/Form";
import { HorizontalFormElement } from "@goauthentik/elements/forms/HorizontalFormElement";
import { styles } from "@goauthentik/admin/applications/wizard/ApplicationWizardFormStepStyles.css.js";
import { ValidationError } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { property, query } from "lit/decorators.js";
import { ValidationError } from "@goauthentik/api";
import {
ApplicationTransactionValidationError,
type ApplicationWizardState,

View File

@ -1,22 +1,27 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-wizard/ak-wizard-steps.js";
import { WizardUpdateEvent } from "@goauthentik/components/ak-wizard/events";
import { AKElement } from "@goauthentik/elements/Base.js";
import { WizardUpdateEvent } from "@goauthentik/components/ak-wizard/events";
import { ProvidersApi, ProxyMode } from "@goauthentik/api";
import { ContextProvider } from "@lit/context";
import { html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { ProvidersApi, ProxyMode } from "@goauthentik/api";
import { applicationWizardProvidersContext } from "./ContextIdentity";
import { providerTypeRenderers } from "./steps/ProviderChoices.js";
import "./steps/ak-application-wizard-application-step.js";
import "./steps/ak-application-wizard-bindings-step.js";
import "./steps/ak-application-wizard-edit-binding-step.js";
import "./steps/ak-application-wizard-provider-choice-step.js";
import "./steps/ak-application-wizard-provider-step.js";
import "./steps/ak-application-wizard-submit-step.js";
import { type ApplicationWizardState, type ApplicationWizardStateUpdate } from "./types";
const freshWizardState = (): ApplicationWizardState => ({

View File

@ -1,7 +1,8 @@
import { WizardCloseEvent } from "@goauthentik/components/ak-wizard/events.js";
import { ModalButton } from "@goauthentik/elements/buttons/ModalButton";
import { bound } from "@goauthentik/elements/decorators/bound.js";
import { WizardCloseEvent } from "@goauthentik/components/ak-wizard/events.js";
import { html } from "lit";
import { customElement } from "lit/decorators.js";

View File

@ -1,9 +1,9 @@
import "@goauthentik/admin/common/ak-license-notice";
import { TemplateResult, html } from "lit";
import type { TypeCreate } from "@goauthentik/api";
import { TemplateResult, html } from "lit";
type ProviderRenderer = () => TemplateResult;
export type LocalTypeCreate = TypeCreate & {

View File

@ -2,10 +2,6 @@ import {
type DescriptionPair,
renderDescriptionList,
} from "@goauthentik/components/DescriptionList.js";
import { match } from "ts-pattern";
import { msg } from "@lit/localize";
import { html } from "lit";
import {
ClientTypeEnum,
@ -22,6 +18,11 @@ import {
SCIMProvider,
} from "@goauthentik/api";
import { match } from "ts-pattern";
import { msg } from "@lit/localize";
import { html } from "lit";
import { OneOfProvider } from "../types.js";
const renderSummary = (type: string, name: string, fields: DescriptionPair[]) =>

View File

@ -1,24 +1,32 @@
import { ApplicationWizardStep } from "@goauthentik/admin/applications/wizard/ApplicationWizardStep.js";
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { policyEngineModes } from "@goauthentik/admin/policies/PolicyEngineModes";
import { camelToSnake } from "@goauthentik/common/utils.js";
import { policyEngineModes } from "@goauthentik/admin/policies/PolicyEngineModes";
import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-slug-input";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input";
import { type NavigableButton, type WizardButton } from "@goauthentik/components/ak-wizard/types";
import { type KeyUnknown } from "@goauthentik/elements/forms/Form";
import { type NavigableButton, type WizardButton } from "@goauthentik/components/ak-wizard/types";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { isSlug } from "@goauthentik/elements/router/utils.js";
import { type ApplicationRequest } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { html } from "lit";
import { customElement, query, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { type ApplicationRequest } from "@goauthentik/api";
import { ApplicationWizardStateUpdate, ValidationRecord } from "../types";
const autoTrim = (v: unknown) => (typeof v === "string" ? v.trim() : v);

View File

@ -1,15 +1,21 @@
import { ApplicationWizardStep } from "@goauthentik/admin/applications/wizard/ApplicationWizardStep.js";
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-slug-input";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input";
import { type WizardButton } from "@goauthentik/components/ak-wizard/types";
import "@goauthentik/elements/ak-table/ak-select-table.js";
import { SelectTable } from "@goauthentik/elements/ak-table/ak-select-table.js";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { P, match } from "ts-pattern";
import { msg, str } from "@lit/localize";
@ -19,6 +25,7 @@ import { customElement, query } from "lit/decorators.js";
import PFCard from "@patternfly/patternfly/components/Card/card.css";
import { makeEditButton } from "./bindings/ak-application-wizard-bindings-edit-button.js";
import "./bindings/ak-application-wizard-bindings-toolbar.js";
const COLUMNS = [

View File

@ -1,24 +1,31 @@
import { ApplicationWizardStep } from "@goauthentik/admin/applications/wizard/ApplicationWizardStep.js";
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { groupBy } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input";
import "@goauthentik/components/ak-toggle-group";
import { type NavigableButton, type WizardButton } from "@goauthentik/components/ak-wizard/types";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect";
import { type SearchSelectBase } from "@goauthentik/elements/forms/SearchSelect/SearchSelect.js";
import "@goauthentik/elements/forms/SearchSelect/ak-search-select-ez.js";
import { CoreApi, Group, PoliciesApi, Policy, PolicyBinding, User } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { html, nothing } from "lit";
import { customElement, query, state } from "lit/decorators.js";
import { CoreApi, Group, PoliciesApi, Policy, PolicyBinding, User } from "@goauthentik/api";
const withQuery = <T>(search: string | undefined, args: T) => (search ? { ...args, search } : args);
enum target {

View File

@ -1,21 +1,29 @@
import { WithLicenseSummary } from "#elements/mixins/license";
import { ApplicationWizardStep } from "@goauthentik/admin/applications/wizard/ApplicationWizardStep.js";
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import type { NavigableButton, WizardButton } from "@goauthentik/components/ak-wizard/types";
import "@goauthentik/elements/EmptyState.js";
import { bound } from "@goauthentik/elements/decorators/bound.js";
import "@goauthentik/elements/forms/FormGroup.js";
import "@goauthentik/elements/forms/HorizontalFormElement.js";
import { TypeCreateWizardPageLayouts } from "@goauthentik/elements/wizard/TypeCreateWizardPage.js";
import "@goauthentik/elements/wizard/TypeCreateWizardPage.js";
import { TypeCreate } from "@goauthentik/api";
import { consume } from "@lit/context";
import { msg } from "@lit/localize";
import { html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { TypeCreate } from "@goauthentik/api";
import { applicationWizardProvidersContext } from "../ContextIdentity";
import { type LocalTypeCreate } from "./ProviderChoices.js";

View File

@ -8,6 +8,7 @@ import { html, unsafeStatic } from "lit/static-html.js";
import { ApplicationWizardStep } from "../ApplicationWizardStep.js";
import { OneOfProvider } from "../types.js";
import { ApplicationWizardProviderForm } from "./providers/ApplicationWizardProviderForm.js";
import "./providers/ak-application-wizard-provider-for-ldap.js";
import "./providers/ak-application-wizard-provider-for-oauth.js";
import "./providers/ak-application-wizard-provider-for-proxy.js";

View File

@ -1,24 +1,14 @@
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_REFRESH } from "@goauthentik/common/constants";
import { parseAPIResponseError } from "@goauthentik/common/errors/network";
import { WizardNavigationEvent } from "@goauthentik/components/ak-wizard/events.js";
import { type WizardButton } from "@goauthentik/components/ak-wizard/types";
import { showAPIErrorMessage } from "@goauthentik/elements/messages/MessageContainer";
import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter";
import { P, match } from "ts-pattern";
import { msg } from "@lit/localize";
import { TemplateResult, css, html, nothing } from "lit";
import { customElement, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
// import { map } from "lit/directives/map.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css";
import PFProgressStepper from "@patternfly/patternfly/components/ProgressStepper/progress-stepper.css";
import PFTitle from "@patternfly/patternfly/components/Title/title.css";
import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css";
import { WizardNavigationEvent } from "@goauthentik/components/ak-wizard/events.js";
import { type WizardButton } from "@goauthentik/components/ak-wizard/types";
import {
type ApplicationRequest,
@ -34,6 +24,20 @@ import {
instanceOfValidationError,
} from "@goauthentik/api";
import { P, match } from "ts-pattern";
import { msg } from "@lit/localize";
import { TemplateResult, css, html, nothing } from "lit";
import { customElement, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
// import { map } from "lit/directives/map.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css";
import PFProgressStepper from "@patternfly/patternfly/components/ProgressStepper/progress-stepper.css";
import PFTitle from "@patternfly/patternfly/components/Title/title.css";
import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css";
import { ApplicationWizardStep } from "../ApplicationWizardStep.js";
import { OneOfProvider, isApplicationTransactionValidationError } from "../types.js";
import { providerRenderers } from "./SubmitStepOverviewRenderers.js";

View File

@ -1,12 +1,16 @@
import { camelToSnake } from "@goauthentik/common/utils.js";
import "@goauthentik/components/ak-number-input";
import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input";
import { AKElement } from "@goauthentik/elements/Base.js";
import { KeyUnknown, serializeForm } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { HorizontalFormElement } from "@goauthentik/elements/forms/HorizontalFormElement";
import { property, query } from "lit/decorators.js";

View File

@ -1,14 +1,16 @@
import { WithBrandConfig } from "#elements/mixins/branding";
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { ValidationRecord } from "@goauthentik/admin/applications/wizard/types";
import { renderForm } from "@goauthentik/admin/providers/ldap/LDAPProviderFormForm.js";
import type { LDAPProvider } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { html } from "lit";
import { customElement } from "lit/decorators.js";
import type { LDAPProvider } from "@goauthentik/api";
import { ApplicationWizardProviderForm } from "./ApplicationWizardProviderForm.js";
@customElement("ak-application-wizard-provider-for-ldap")

View File

@ -1,14 +1,16 @@
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { renderForm } from "@goauthentik/admin/providers/oauth2/OAuth2ProviderFormForm.js";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { renderForm } from "@goauthentik/admin/providers/oauth2/OAuth2ProviderFormForm.js";
import { OAuth2ProviderRequest, SourcesApi } from "@goauthentik/api";
import { type OAuth2Provider, type PaginatedOAuthSourceList } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { OAuth2ProviderRequest, SourcesApi } from "@goauthentik/api";
import { type OAuth2Provider, type PaginatedOAuthSourceList } from "@goauthentik/api";
import { ApplicationTransactionValidationError } from "../../types.js";
import { ApplicationWizardProviderForm } from "./ApplicationWizardProviderForm.js";

View File

@ -1,4 +1,7 @@
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { WizardUpdateEvent } from "@goauthentik/components/ak-wizard/events.js";
import { ValidationRecord } from "@goauthentik/admin/applications/wizard/types";
import {
ProxyModeValue,
@ -6,14 +9,13 @@ import {
type SetShowHttpBasic,
renderForm,
} from "@goauthentik/admin/providers/proxy/ProxyProviderFormForm.js";
import { WizardUpdateEvent } from "@goauthentik/components/ak-wizard/events.js";
import { ProxyMode, ProxyProvider } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { ProxyMode, ProxyProvider } from "@goauthentik/api";
import { ApplicationWizardProviderForm } from "./ApplicationWizardProviderForm";
@customElement("ak-application-wizard-provider-for-proxy")

View File

@ -1,21 +1,23 @@
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import "@goauthentik/admin/common/ak-crypto-certificate-search.js";
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import {
propertyMappingsProvider,
propertyMappingsSelector,
} from "@goauthentik/admin/providers/rac/RACProviderFormHelpers.js";
import "@goauthentik/components/ak-text-input";
import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import { FlowsInstancesListDesignationEnum, type RACProvider } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { html } from "lit";
import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { FlowsInstancesListDesignationEnum, type RACProvider } from "@goauthentik/api";
import { ApplicationWizardProviderForm } from "./ApplicationWizardProviderForm.js";
@customElement("ak-application-wizard-provider-for-rac")

View File

@ -1,14 +1,16 @@
import { WithBrandConfig } from "#elements/mixins/branding";
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { ValidationRecord } from "@goauthentik/admin/applications/wizard/types";
import { renderForm } from "@goauthentik/admin/providers/radius/RadiusProviderFormForm.js";
import { RadiusProvider } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { customElement } from "@lit/reactive-element/decorators.js";
import { html } from "lit";
import { RadiusProvider } from "@goauthentik/api";
import { ApplicationWizardProviderForm } from "./ApplicationWizardProviderForm.js";
@customElement("ak-application-wizard-provider-for-radius")

View File

@ -1,14 +1,16 @@
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { type AkCryptoCertificateSearch } from "@goauthentik/admin/common/ak-crypto-certificate-search";
import { renderForm } from "@goauthentik/admin/providers/saml/SAMLProviderFormForm.js";
import "@goauthentik/elements/forms/FormGroup";
import { SAMLProvider } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { customElement, state } from "@lit/reactive-element/decorators.js";
import { html } from "lit";
import { SAMLProvider } from "@goauthentik/api";
import { ApplicationWizardProviderForm } from "./ApplicationWizardProviderForm";
@customElement("ak-application-wizard-provider-for-saml")

View File

@ -1,13 +1,15 @@
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { renderForm } from "@goauthentik/admin/providers/scim/SCIMProviderFormForm.js";
import "@goauthentik/elements/forms/FormGroup";
import { PaginatedSCIMMappingList, type SCIMProvider } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { customElement, state } from "@lit/reactive-element/decorators.js";
import { html } from "lit";
import { PaginatedSCIMMappingList, type SCIMProvider } from "@goauthentik/api";
import { ApplicationWizardProviderForm } from "./ApplicationWizardProviderForm";
@customElement("ak-application-wizard-provider-for-scim")

View File

@ -1,12 +1,20 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { docLink } from "@goauthentik/common/global";
import "@goauthentik/components/ak-toggle-group";
import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect";
import { BlueprintFile, BlueprintInstance, ManagedApi } from "@goauthentik/api";
import YAML from "yaml";
import { msg } from "@lit/localize";
@ -16,8 +24,6 @@ import { ifDefined } from "lit/directives/if-defined.js";
import PFContent from "@patternfly/patternfly/components/Content/content.css";
import { BlueprintFile, BlueprintInstance, ManagedApi } from "@goauthentik/api";
enum blueprintSource {
file = "file",
oci = "oci",

View File

@ -1,24 +1,22 @@
import "@goauthentik/admin/blueprints/BlueprintForm";
import "@goauthentik/admin/rbac/ObjectPermissionModal";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_REFRESH } from "@goauthentik/common/constants";
import { formatElapsedTime } from "@goauthentik/common/temporal";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/buttons/ActionButton";
import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/forms/DeleteBulkForm";
import "@goauthentik/elements/forms/ModalForm";
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage";
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import {
BlueprintInstance,
BlueprintInstanceStatusEnum,
@ -26,6 +24,12 @@ import {
RbacPermissionsAssignedByUsersListModelEnum,
} from "@goauthentik/api";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
export function BlueprintStatus(blueprint?: BlueprintInstance): string {
if (!blueprint) return "";
switch (blueprint.status) {

View File

@ -1,21 +1,23 @@
import { certificateProvider, certificateSelector } from "@goauthentik/admin/brands/Certificates";
import "@goauthentik/admin/common/ak-crypto-certificate-search";
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { DefaultBrand } from "@goauthentik/common/ui/config";
import "@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-provider.js";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect";
import YAML from "yaml";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect";
import {
Application,
@ -25,6 +27,12 @@ import {
FlowsInstancesListDesignationEnum,
} from "@goauthentik/api";
import YAML from "yaml";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
@customElement("ak-brand-form")
export class BrandForm extends ModelForm<Brand, string> {
loadInstance(pk: string): Promise<Brand> {

View File

@ -1,22 +1,26 @@
import "@goauthentik/admin/brands/BrandForm";
import "@goauthentik/admin/rbac/ObjectPermissionModal";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/forms/DeleteBulkForm";
import "@goauthentik/elements/forms/ModalForm";
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage";
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
import { Brand, CoreApi, RbacPermissionsAssignedByUsersListModelEnum } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { Brand, CoreApi, RbacPermissionsAssignedByUsersListModelEnum } from "@goauthentik/api";
@customElement("ak-brand-list")
export class BrandListPage extends TablePage<Brand> {
searchEnabled(): boolean {

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "#common/api/config";
import {
DataProvision,
DualSelectPair,

View File

@ -1,14 +1,15 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AKElement } from "@goauthentik/elements/Base";
import { SearchSelect } from "@goauthentik/elements/forms/SearchSelect";
import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter";
import { CoreApi, CoreGroupsListRequest, Group } from "@goauthentik/api";
import { html } from "lit";
import { customElement } from "lit/decorators.js";
import { property, query } from "lit/decorators.js";
import { CoreApi, CoreGroupsListRequest, Group } from "@goauthentik/api";
async function fetchObjects(query?: string): Promise<Group[]> {
const args: CoreGroupsListRequest = {
ordering: "name",

View File

@ -1,12 +1,11 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { AKElement } from "@goauthentik/elements/Base";
import { SearchSelect } from "@goauthentik/elements/forms/SearchSelect";
import "@goauthentik/elements/forms/SearchSelect";
import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter";
import { html } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import "@goauthentik/elements/forms/SearchSelect";
import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter";
import {
CertificateKeyPair,
@ -14,6 +13,10 @@ import {
CryptoCertificatekeypairsListRequest,
} from "@goauthentik/api";
import { html } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
const renderElement = (item: CertificateKeyPair): string => item.name;
const renderValue = (item: CertificateKeyPair | undefined): string | undefined => item?.pk;

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