Compare commits
72 Commits
version/20
...
web/sdk/em
Author | SHA1 | Date | |
---|---|---|---|
a407d903ab | |||
7e6f36b0b4 | |||
8dd7b0569c | |||
616be78e10 | |||
7125db1fbd | |||
8c7c7c3fee | |||
bbbd00db22 | |||
6d60c5f7c7 | |||
accf25a626 | |||
5f261bed96 | |||
4d51671f88 | |||
1c570b2502 | |||
78e4370b98 | |||
9a26111f1c | |||
02ae099bdf | |||
05fe4e5e7b | |||
24c289fdd1 | |||
cd8de3e526 | |||
243bd03785 | |||
e02cf0b3bd | |||
3018735579 | |||
6a956d149a | |||
3fd1bc6673 | |||
6bc4877702 | |||
9592b42501 | |||
517a5bc689 | |||
a19e350ca6 | |||
88577145fb | |||
bc93df1e29 | |||
9d5eb54504 | |||
d95c433027 | |||
7416c90efb | |||
34a073b0f7 | |||
86eb112a03 | |||
e48d001ea6 | |||
2070372f03 | |||
bea4679192 | |||
32d1488a56 | |||
1003c79d8c | |||
a05ed7e237 | |||
087d4f6a48 | |||
141cfe75d8 | |||
a3a13d265b | |||
9c45ec1918 | |||
59fa449abe | |||
f83c84b04d | |||
835a4097eb | |||
da43df44b2 | |||
d03b14aac4 | |||
62d990e91b | |||
6c8cfc9ef7 | |||
e93d8b1646 | |||
6faa250574 | |||
c8e4b187b8 | |||
98acca896a | |||
7dc4b70ee1 | |||
8f55d3fc07 | |||
17fb90e0af | |||
870ed99097 | |||
1c5af88ea9 | |||
461856d067 | |||
cdbf448769 | |||
0fcac0e165 | |||
40e857fdb3 | |||
7d86593d05 | |||
c95ce0a5d4 | |||
a7b31ce6de | |||
b5f4303fbd | |||
29f04ea801 | |||
7141702c9e | |||
0f30d135b6 | |||
73f326b21b |
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 2024.6.4
|
||||
current_version = 2024.8.0
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
||||
|
@ -29,9 +29,9 @@ outputs:
|
||||
imageTags:
|
||||
description: "Docker image tags"
|
||||
value: ${{ steps.ev.outputs.imageTags }}
|
||||
imageNames:
|
||||
description: "Docker image names"
|
||||
value: ${{ steps.ev.outputs.imageNames }}
|
||||
attestImageNames:
|
||||
description: "Docker image names used for attestation"
|
||||
value: ${{ steps.ev.outputs.attestImageNames }}
|
||||
imageMainTag:
|
||||
description: "Docker image main tag"
|
||||
value: ${{ steps.ev.outputs.imageMainTag }}
|
||||
|
@ -51,15 +51,24 @@ else:
|
||||
]
|
||||
|
||||
image_main_tag = image_tags[0].split(":")[-1]
|
||||
image_tags_rendered = ",".join(image_tags)
|
||||
image_names_rendered = ",".join(set(name.split(":")[0] for name in image_tags))
|
||||
|
||||
|
||||
def get_attest_image_names(image_with_tags: list[str]):
|
||||
"""Attestation only for GHCR"""
|
||||
image_tags = []
|
||||
for image_name in set(name.split(":")[0] for name in image_with_tags):
|
||||
if not image_name.startswith("ghcr.io"):
|
||||
continue
|
||||
image_tags.append(image_name)
|
||||
return ",".join(set(image_tags))
|
||||
|
||||
|
||||
with open(os.environ["GITHUB_OUTPUT"], "a+", encoding="utf-8") as _output:
|
||||
print(f"shouldBuild={should_build}", file=_output)
|
||||
print(f"sha={sha}", file=_output)
|
||||
print(f"version={version}", file=_output)
|
||||
print(f"prerelease={prerelease}", file=_output)
|
||||
print(f"imageTags={image_tags_rendered}", file=_output)
|
||||
print(f"imageNames={image_names_rendered}", file=_output)
|
||||
print(f"imageTags={','.join(image_tags)}", file=_output)
|
||||
print(f"attestImageNames={get_attest_image_names(image_tags)}", file=_output)
|
||||
print(f"imageMainTag={image_main_tag}", file=_output)
|
||||
print(f"imageMainName={image_tags[0]}", file=_output)
|
||||
|
2
.github/workflows/ci-main.yml
vendored
2
.github/workflows/ci-main.yml
vendored
@ -261,7 +261,7 @@ jobs:
|
||||
id: attest
|
||||
if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
|
||||
with:
|
||||
subject-name: ${{ steps.ev.outputs.imageNames }}
|
||||
subject-name: ${{ steps.ev.outputs.attestImageNames }}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
pr-comment:
|
||||
|
2
.github/workflows/ci-outpost.yml
vendored
2
.github/workflows/ci-outpost.yml
vendored
@ -115,7 +115,7 @@ jobs:
|
||||
id: attest
|
||||
if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
|
||||
with:
|
||||
subject-name: ${{ steps.ev.outputs.imageNames }}
|
||||
subject-name: ${{ steps.ev.outputs.attestImageNames }}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
build-binary:
|
||||
|
4
.github/workflows/release-publish.yml
vendored
4
.github/workflows/release-publish.yml
vendored
@ -58,7 +58,7 @@ jobs:
|
||||
- uses: actions/attest-build-provenance@v1
|
||||
id: attest
|
||||
with:
|
||||
subject-name: ${{ steps.ev.outputs.imageNames }}
|
||||
subject-name: ${{ steps.ev.outputs.attestImageNames }}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
build-outpost:
|
||||
@ -122,7 +122,7 @@ jobs:
|
||||
- uses: actions/attest-build-provenance@v1
|
||||
id: attest
|
||||
with:
|
||||
subject-name: ${{ steps.ev.outputs.imageNames }}
|
||||
subject-name: ${{ steps.ev.outputs.attestImageNames }}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
build-outpost-binary:
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
from os import environ
|
||||
|
||||
__version__ = "2024.6.4"
|
||||
__version__ = "2024.8.0"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
||||
|
||||
|
@ -25,3 +25,31 @@ class BrandMiddleware:
|
||||
if locale != "":
|
||||
activate(locale)
|
||||
return self.get_response(request)
|
||||
|
||||
|
||||
class BrandCORSAPIMiddleware:
|
||||
"""CORS for API requests depending on Brand"""
|
||||
|
||||
get_response: Callable[[HttpRequest], HttpResponse]
|
||||
|
||||
def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):
|
||||
self.get_response = get_response
|
||||
|
||||
def set_headers(self, request: HttpRequest, response: HttpResponse):
|
||||
response["Access-Control-Allow-Origin"] = "http://localhost:8080"
|
||||
response["Access-Control-Allow-Credentials"] = "true"
|
||||
|
||||
def __call__(self, request: HttpRequest) -> HttpResponse:
|
||||
if request.method == "OPTIONS":
|
||||
response = HttpResponse(
|
||||
status=200,
|
||||
)
|
||||
self.set_headers(request, response)
|
||||
response["Access-Control-Allow-Headers"] = (
|
||||
"authorization,sentry-trace,x-authentik-csrf,content-type"
|
||||
)
|
||||
response["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS"
|
||||
return response
|
||||
response = self.get_response(request)
|
||||
self.set_headers(request, response)
|
||||
return response
|
||||
|
@ -9,10 +9,11 @@ class Command(TenantCommand):
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("--type", type=str, required=True)
|
||||
parser.add_argument("--all", action="store_true")
|
||||
parser.add_argument("usernames", nargs="+", type=str)
|
||||
parser.add_argument("--all", action="store_true", default=False)
|
||||
parser.add_argument("usernames", nargs="*", type=str)
|
||||
|
||||
def handle_per_tenant(self, **options):
|
||||
print(options)
|
||||
new_type = UserTypes(options["type"])
|
||||
qs = (
|
||||
User.objects.exclude_anonymous()
|
||||
@ -22,6 +23,9 @@ class Command(TenantCommand):
|
||||
if options["usernames"] and options["all"]:
|
||||
self.stderr.write("--all and usernames specified, only one can be specified")
|
||||
return
|
||||
if not options["usernames"] and not options["all"]:
|
||||
self.stderr.write("--all or usernames must be specified")
|
||||
return
|
||||
if options["usernames"] and not options["all"]:
|
||||
qs = qs.filter(username__in=options["usernames"])
|
||||
updated = qs.update(type=new_type)
|
||||
|
@ -13,6 +13,7 @@
|
||||
<link rel="shortcut icon" href="{{ brand.branding_favicon }}">
|
||||
{% block head_before %}
|
||||
{% endblock %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly-base.css' %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject>
|
||||
{% versioned_script "dist/poly-%v.js" %}
|
||||
|
@ -25,4 +25,4 @@ class AuthentikEnterpriseConfig(EnterpriseConfig):
|
||||
"""Actual enterprise check, cached"""
|
||||
from authentik.enterprise.license import LicenseKey
|
||||
|
||||
return LicenseKey.cached_summary().status
|
||||
return LicenseKey.cached_summary().status.is_valid
|
||||
|
@ -117,7 +117,7 @@ class LicenseKey:
|
||||
our_cert.public_key(),
|
||||
algorithms=["ES512"],
|
||||
audience=get_license_aud(),
|
||||
options={"verify_exp": check_expiry},
|
||||
options={"verify_exp": check_expiry, "verify_signature": check_expiry},
|
||||
),
|
||||
)
|
||||
except PyJWTError:
|
||||
@ -134,7 +134,7 @@ class LicenseKey:
|
||||
exp_ts = int(mktime(lic.expiry.timetuple()))
|
||||
if total.exp == 0:
|
||||
total.exp = exp_ts
|
||||
total.exp = min(total.exp, exp_ts)
|
||||
total.exp = max(total.exp, exp_ts)
|
||||
total.license_flags.extend(lic.status.license_flags)
|
||||
return total
|
||||
|
||||
|
@ -16,12 +16,14 @@ from django.views.decorators.clickjacking import xframe_options_sameorigin
|
||||
from django.views.generic import View
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import OpenApiParameter, PolymorphicProxySerializer, extend_schema
|
||||
from rest_framework.exceptions import AuthenticationFailed
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.views import APIView
|
||||
from sentry_sdk import capture_exception, start_span
|
||||
from sentry_sdk.api import set_tag
|
||||
from structlog.stdlib import BoundLogger, get_logger
|
||||
|
||||
from authentik.api.authentication import bearer_auth, get_authorization_header
|
||||
from authentik.brands.models import Brand
|
||||
from authentik.core.models import Application
|
||||
from authentik.events.models import Event, EventAction, cleanse_dict
|
||||
@ -116,6 +118,14 @@ class FlowExecutorView(APIView):
|
||||
super().setup(request, flow_slug=flow_slug)
|
||||
self.flow = get_object_or_404(Flow.objects.select_related(), slug=flow_slug)
|
||||
self._logger = get_logger().bind(flow_slug=flow_slug)
|
||||
# Usually flows are authenticated by session, we don't really use rest_framework's
|
||||
# authentication method.
|
||||
try:
|
||||
user = bearer_auth(get_authorization_header(request))
|
||||
if user:
|
||||
request.user = user
|
||||
except AuthenticationFailed:
|
||||
pass
|
||||
set_tag("authentik.flow", self.flow.slug)
|
||||
|
||||
def handle_invalid_flow(self, exc: FlowNonApplicableException) -> HttpResponse:
|
||||
|
@ -22,6 +22,8 @@ def migrate_search_group(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||
LDAPProvider = apps.get_model("authentik_providers_ldap", "ldapprovider")
|
||||
|
||||
for provider in LDAPProvider.objects.using(db_alias).all():
|
||||
if not provider.search_group:
|
||||
continue
|
||||
for user_pk in (
|
||||
provider.search_group.users.using(db_alias).all().values_list("pk", flat=True)
|
||||
):
|
||||
|
@ -433,20 +433,21 @@ class TokenParams:
|
||||
app = Application.objects.filter(provider=self.provider).first()
|
||||
if not app or not app.provider:
|
||||
raise TokenError("invalid_grant")
|
||||
self.user, _ = User.objects.update_or_create(
|
||||
# trim username to ensure the entire username is max 150 chars
|
||||
# (22 chars being the length of the "template")
|
||||
username=f"ak-{self.provider.name[:150-22]}-client_credentials",
|
||||
defaults={
|
||||
"attributes": {
|
||||
USER_ATTRIBUTE_GENERATED: True,
|
||||
with audit_ignore():
|
||||
self.user, _ = User.objects.update_or_create(
|
||||
# trim username to ensure the entire username is max 150 chars
|
||||
# (22 chars being the length of the "template")
|
||||
username=f"ak-{self.provider.name[:150-22]}-client_credentials",
|
||||
defaults={
|
||||
"attributes": {
|
||||
USER_ATTRIBUTE_GENERATED: True,
|
||||
},
|
||||
"last_login": timezone.now(),
|
||||
"name": f"Autogenerated user from application {app.name} (client credentials)",
|
||||
"path": f"{USER_PATH_SYSTEM_PREFIX}/apps/{app.slug}",
|
||||
"type": UserTypes.SERVICE_ACCOUNT,
|
||||
},
|
||||
"last_login": timezone.now(),
|
||||
"name": f"Autogenerated user from application {app.name} (client credentials)",
|
||||
"path": f"{USER_PATH_SYSTEM_PREFIX}/apps/{app.slug}",
|
||||
"type": UserTypes.SERVICE_ACCOUNT,
|
||||
},
|
||||
)
|
||||
)
|
||||
self.__check_policy_access(app, request)
|
||||
|
||||
Event.new(
|
||||
|
@ -164,7 +164,7 @@ class SAMLProvider(Provider):
|
||||
)
|
||||
|
||||
sign_assertion = models.BooleanField(default=True)
|
||||
sign_response = models.BooleanField(default=True)
|
||||
sign_response = models.BooleanField(default=False)
|
||||
|
||||
@property
|
||||
def launch_url(self) -> str | None:
|
||||
|
@ -54,7 +54,11 @@ class TestServiceProviderMetadataParser(TestCase):
|
||||
request = self.factory.get("/")
|
||||
metadata = lxml_from_string(MetadataProcessor(provider, request).build_entity_descriptor())
|
||||
|
||||
schema = etree.XMLSchema(etree.parse("schemas/saml-schema-metadata-2.0.xsd")) # nosec
|
||||
schema = etree.XMLSchema(
|
||||
etree.parse(
|
||||
source="schemas/saml-schema-metadata-2.0.xsd", parser=etree.XMLParser()
|
||||
) # nosec
|
||||
)
|
||||
self.assertTrue(schema.validate(metadata))
|
||||
|
||||
def test_schema_want_authn_requests_signed(self):
|
||||
|
@ -47,7 +47,9 @@ class TestSchema(TestCase):
|
||||
|
||||
metadata = lxml_from_string(request)
|
||||
|
||||
schema = etree.XMLSchema(etree.parse("schemas/saml-schema-protocol-2.0.xsd")) # nosec
|
||||
schema = etree.XMLSchema(
|
||||
etree.parse("schemas/saml-schema-protocol-2.0.xsd", parser=etree.XMLParser()) # nosec
|
||||
)
|
||||
self.assertTrue(schema.validate(metadata))
|
||||
|
||||
def test_response_schema(self):
|
||||
@ -68,5 +70,7 @@ class TestSchema(TestCase):
|
||||
|
||||
metadata = lxml_from_string(response)
|
||||
|
||||
schema = etree.XMLSchema(etree.parse("schemas/saml-schema-protocol-2.0.xsd")) # nosec
|
||||
schema = etree.XMLSchema(
|
||||
etree.parse("schemas/saml-schema-protocol-2.0.xsd", parser=etree.XMLParser()) # nosec
|
||||
)
|
||||
self.assertTrue(schema.validate(metadata))
|
||||
|
@ -248,6 +248,7 @@ MIDDLEWARE = [
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"authentik.core.middleware.RequestIDMiddleware",
|
||||
"authentik.brands.middleware.BrandMiddleware",
|
||||
"authentik.brands.middleware.BrandCORSAPIMiddleware",
|
||||
"authentik.events.middleware.AuditMiddleware",
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
|
@ -30,7 +30,9 @@ class TestMetadataProcessor(TestCase):
|
||||
xml = MetadataProcessor(self.source, request).build_entity_descriptor()
|
||||
metadata = lxml_from_string(xml)
|
||||
|
||||
schema = etree.XMLSchema(etree.parse("schemas/saml-schema-metadata-2.0.xsd")) # nosec
|
||||
schema = etree.XMLSchema(
|
||||
etree.parse("schemas/saml-schema-metadata-2.0.xsd", parser=etree.XMLParser()) # nosec
|
||||
)
|
||||
self.assertTrue(schema.validate(metadata))
|
||||
|
||||
def test_metadata_consistent(self):
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -2,7 +2,7 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"$id": "https://goauthentik.io/blueprints/schema.json",
|
||||
"type": "object",
|
||||
"title": "authentik 2024.6.4 Blueprint schema",
|
||||
"title": "authentik 2024.8.0 Blueprint schema",
|
||||
"required": [
|
||||
"version",
|
||||
"entries"
|
||||
|
@ -31,7 +31,7 @@ services:
|
||||
volumes:
|
||||
- redis:/data
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.6.4}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.8.0}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
@ -52,7 +52,7 @@ services:
|
||||
- postgresql
|
||||
- redis
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.6.4}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.8.0}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
|
2
go.mod
2
go.mod
@ -18,7 +18,7 @@ require (
|
||||
github.com/gorilla/securecookie v1.1.2
|
||||
github.com/gorilla/sessions v1.4.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/jellydator/ttlcache/v3 v3.2.1
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
|
||||
github.com/pires/go-proxyproto v0.7.0
|
||||
|
4
go.sum
4
go.sum
@ -200,8 +200,8 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/jellydator/ttlcache/v3 v3.2.1 h1:eS8ljnYY7BllYGkXw/TfczWZrXUu/CH7SIkC6ugn9Js=
|
||||
github.com/jellydator/ttlcache/v3 v3.2.1/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
|
@ -29,4 +29,4 @@ func UserAgent() string {
|
||||
return fmt.Sprintf("authentik@%s", FullVersion())
|
||||
}
|
||||
|
||||
const VERSION = "2024.6.4"
|
||||
const VERSION = "2024.8.0"
|
||||
|
@ -16,7 +16,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-15 00:09+0000\n"
|
||||
"POT-Creation-Date: 2024-08-18 00:08+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Anton Babenko, 2024\n"
|
||||
"Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n"
|
||||
@ -739,7 +739,7 @@ msgstr "Правило Уведомления"
|
||||
|
||||
#: authentik/events/models.py
|
||||
msgid "Notification Rules"
|
||||
msgstr "Правило Уведомлений"
|
||||
msgstr "Правила уведомлений"
|
||||
|
||||
#: authentik/events/models.py
|
||||
msgid "Webhook Mapping"
|
||||
@ -1771,6 +1771,14 @@ msgstr "Сопоставление свойства Radius провайдера"
|
||||
msgid "Radius Provider Property Mappings"
|
||||
msgstr "Сопоставление свойств Radius провайдера"
|
||||
|
||||
#: authentik/providers/saml/api/providers.py
|
||||
msgid ""
|
||||
"With a signing keypair selected, at least one of 'Sign assertion' and 'Sign "
|
||||
"Response' must be selected."
|
||||
msgstr ""
|
||||
"При выборе пары ключей для подписи необходимо выбрать как минимум один из "
|
||||
"вариантов: 'Подписывать утверждение' или 'Подписывать ответ'."
|
||||
|
||||
#: authentik/providers/saml/api/providers.py
|
||||
msgid "Invalid XML Syntax"
|
||||
msgstr "Некорректный синтаксис XML"
|
||||
@ -1918,6 +1926,21 @@ msgstr ""
|
||||
msgid "Signing Keypair"
|
||||
msgstr "Пара ключей для подписи"
|
||||
|
||||
#: authentik/providers/saml/models.py authentik/sources/saml/models.py
|
||||
msgid ""
|
||||
"When selected, incoming assertions are encrypted by the IdP using the public"
|
||||
" key of the encryption keypair. The assertion is decrypted by the SP using "
|
||||
"the the private key."
|
||||
msgstr ""
|
||||
"При выборе этого варианта, входящие утверждения шифруются поставщиком "
|
||||
"идентификации (IdP) с использованием открытого ключа из пары ключей "
|
||||
"шифрования. Утверждение расшифровывается поставщиком услуг (SP) с "
|
||||
"использованием закрытого ключа."
|
||||
|
||||
#: authentik/providers/saml/models.py authentik/sources/saml/models.py
|
||||
msgid "Encryption Keypair"
|
||||
msgstr "Пара ключей шифрования"
|
||||
|
||||
#: authentik/providers/saml/models.py
|
||||
msgid "Default relay_state value for IDP-initiated logins"
|
||||
msgstr "Значение relay_state по умолчанию для логинов, инициированных IDP"
|
||||
@ -2446,21 +2469,6 @@ msgstr ""
|
||||
"Пара ключей, используемая для подписи исходящих ответов, направляемых "
|
||||
"провайдеру идентификационных данных."
|
||||
|
||||
#: authentik/sources/saml/models.py
|
||||
msgid ""
|
||||
"When selected, incoming assertions are encrypted by the IdP using the public"
|
||||
" key of the encryption keypair. The assertion is decrypted by the SP using "
|
||||
"the the private key."
|
||||
msgstr ""
|
||||
"При выборе этого варианта, входящие утверждения шифруются поставщиком "
|
||||
"идентификации (IdP) с использованием открытого ключа из пары ключей "
|
||||
"шифрования. Утверждение расшифровывается поставщиком услуг (SP) с "
|
||||
"использованием закрытого ключа."
|
||||
|
||||
#: authentik/sources/saml/models.py
|
||||
msgid "Encryption Keypair"
|
||||
msgstr "Пара ключей шифрования"
|
||||
|
||||
#: authentik/sources/saml/models.py
|
||||
msgid "SAML Source"
|
||||
msgstr "Источник SAML"
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2024.6.4",
|
||||
"version": "2024.8.0",
|
||||
"private": true
|
||||
}
|
||||
|
233
poetry.lock
generated
233
poetry.lock
generated
@ -1165,15 +1165,18 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "deepmerge"
|
||||
version = "1.1.1"
|
||||
description = "a toolset to deeply merge python dictionaries."
|
||||
version = "2.0"
|
||||
description = "A toolset for deeply merging Python dictionaries."
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "deepmerge-1.1.1-py3-none-any.whl", hash = "sha256:7219dad9763f15be9dcd4bcb53e00f48e4eed6f5ed8f15824223eb934bb35977"},
|
||||
{file = "deepmerge-1.1.1.tar.gz", hash = "sha256:53a489dc9449636e480a784359ae2aab3191748c920649551c8e378622f0eca4"},
|
||||
{file = "deepmerge-2.0-py3-none-any.whl", hash = "sha256:6de9ce507115cff0bed95ff0ce9ecc31088ef50cbdf09bc90a09349a318b3d00"},
|
||||
{file = "deepmerge-2.0.tar.gz", hash = "sha256:5c3d86081fbebd04dd5de03626a0607b809a98fb6ccba5770b62466fe940ff20"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["black", "build", "mypy", "pytest", "pyupgrade", "twine", "validate-pyproject[all]"]
|
||||
|
||||
[[package]]
|
||||
name = "defusedxml"
|
||||
version = "0.7.1"
|
||||
@ -1758,13 +1761,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
|
||||
|
||||
[[package]]
|
||||
name = "google-api-python-client"
|
||||
version = "2.142.0"
|
||||
version = "2.143.0"
|
||||
description = "Google API Client Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "google_api_python_client-2.142.0-py2.py3-none-any.whl", hash = "sha256:266799082bb8301f423ec204dffbffb470b502abbf29efd1f83e644d36eb5a8f"},
|
||||
{file = "google_api_python_client-2.142.0.tar.gz", hash = "sha256:a1101ac9e24356557ca22f07ff48b7f61fa5d4b4e7feeef3bda16e5dcb86350e"},
|
||||
{file = "google_api_python_client-2.143.0-py2.py3-none-any.whl", hash = "sha256:d5654134522b9b574b82234e96f7e0aeeabcbf33643fbabcd449ef0068e3a476"},
|
||||
{file = "google_api_python_client-2.143.0.tar.gz", hash = "sha256:6a75441f9078e6e2fcdf4946a153fda1e2cc81b5e9c8d6e8c0750c85c7f8a566"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -2047,13 +2050,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "8.0.0"
|
||||
version = "8.4.0"
|
||||
description = "Read metadata from Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"},
|
||||
{file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"},
|
||||
{file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"},
|
||||
{file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -3025,49 +3028,49 @@ resolved_reference = "20d69d9cc50a0fef31605b46f06da0c94f1ec3cf"
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-api"
|
||||
version = "1.26.0"
|
||||
version = "1.27.0"
|
||||
description = "OpenTelemetry Python API"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "opentelemetry_api-1.26.0-py3-none-any.whl", hash = "sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064"},
|
||||
{file = "opentelemetry_api-1.26.0.tar.gz", hash = "sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce"},
|
||||
{file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"},
|
||||
{file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
deprecated = ">=1.2.6"
|
||||
importlib-metadata = ">=6.0,<=8.0.0"
|
||||
importlib-metadata = ">=6.0,<=8.4.0"
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-sdk"
|
||||
version = "1.26.0"
|
||||
version = "1.27.0"
|
||||
description = "OpenTelemetry Python SDK"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "opentelemetry_sdk-1.26.0-py3-none-any.whl", hash = "sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897"},
|
||||
{file = "opentelemetry_sdk-1.26.0.tar.gz", hash = "sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85"},
|
||||
{file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"},
|
||||
{file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
opentelemetry-api = "1.26.0"
|
||||
opentelemetry-semantic-conventions = "0.47b0"
|
||||
opentelemetry-api = "1.27.0"
|
||||
opentelemetry-semantic-conventions = "0.48b0"
|
||||
typing-extensions = ">=3.7.4"
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-semantic-conventions"
|
||||
version = "0.47b0"
|
||||
version = "0.48b0"
|
||||
description = "OpenTelemetry Semantic Conventions"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "opentelemetry_semantic_conventions-0.47b0-py3-none-any.whl", hash = "sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063"},
|
||||
{file = "opentelemetry_semantic_conventions-0.47b0.tar.gz", hash = "sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e"},
|
||||
{file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"},
|
||||
{file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
deprecated = ">=1.2.6"
|
||||
opentelemetry-api = "1.26.0"
|
||||
opentelemetry-api = "1.27.0"
|
||||
|
||||
[[package]]
|
||||
name = "orjson"
|
||||
@ -3201,13 +3204,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pdoc"
|
||||
version = "14.6.0"
|
||||
version = "14.6.1"
|
||||
description = "API Documentation for Python Projects"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pdoc-14.6.0-py3-none-any.whl", hash = "sha256:36c42c546a317d8e3e8c0b39645f24161374de0c7066ccaae76628d721e49ba5"},
|
||||
{file = "pdoc-14.6.0.tar.gz", hash = "sha256:6e98a24c5e0ca5d188397969cf82581836eaef13f172fc3820047bfe15c61c9a"},
|
||||
{file = "pdoc-14.6.1-py3-none-any.whl", hash = "sha256:efbed433655264392c60551615a3d42b8f21e492373419756d20234c667b54bc"},
|
||||
{file = "pdoc-14.6.1.tar.gz", hash = "sha256:ee598f30d5c55dd4702086dabc412a26022acc35aa88aa382cda8ac655fead98"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -3781,13 +3784,13 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments
|
||||
|
||||
[[package]]
|
||||
name = "pytest-django"
|
||||
version = "4.8.0"
|
||||
version = "4.9.0"
|
||||
description = "A Django plugin for pytest."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-django-4.8.0.tar.gz", hash = "sha256:5d054fe011c56f3b10f978f41a8efb2e5adfc7e680ef36fb571ada1f24779d90"},
|
||||
{file = "pytest_django-4.8.0-py3-none-any.whl", hash = "sha256:ca1ddd1e0e4c227cf9e3e40a6afc6d106b3e70868fd2ac5798a22501271cd0c7"},
|
||||
{file = "pytest_django-4.9.0-py3-none-any.whl", hash = "sha256:1d83692cb39188682dbb419ff0393867e9904094a549a7d38a3154d5731b2b99"},
|
||||
{file = "pytest_django-4.9.0.tar.gz", hash = "sha256:8bf7bc358c9ae6f6fc51b6cebb190fe20212196e6807121f11bd6a3b03428314"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -4195,29 +4198,29 @@ pyasn1 = ">=0.1.3"
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.6.2-py3-none-linux_armv6l.whl", hash = "sha256:5c8cbc6252deb3ea840ad6a20b0f8583caab0c5ef4f9cca21adc5a92b8f79f3c"},
|
||||
{file = "ruff-0.6.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:17002fe241e76544448a8e1e6118abecbe8cd10cf68fde635dad480dba594570"},
|
||||
{file = "ruff-0.6.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3dbeac76ed13456f8158b8f4fe087bf87882e645c8e8b606dd17b0b66c2c1158"},
|
||||
{file = "ruff-0.6.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:094600ee88cda325988d3f54e3588c46de5c18dae09d683ace278b11f9d4d534"},
|
||||
{file = "ruff-0.6.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:316d418fe258c036ba05fbf7dfc1f7d3d4096db63431546163b472285668132b"},
|
||||
{file = "ruff-0.6.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d72b8b3abf8a2d51b7b9944a41307d2f442558ccb3859bbd87e6ae9be1694a5d"},
|
||||
{file = "ruff-0.6.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2aed7e243be68487aa8982e91c6e260982d00da3f38955873aecd5a9204b1d66"},
|
||||
{file = "ruff-0.6.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d371f7fc9cec83497fe7cf5eaf5b76e22a8efce463de5f775a1826197feb9df8"},
|
||||
{file = "ruff-0.6.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8f310d63af08f583363dfb844ba8f9417b558199c58a5999215082036d795a1"},
|
||||
{file = "ruff-0.6.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7db6880c53c56addb8638fe444818183385ec85eeada1d48fc5abe045301b2f1"},
|
||||
{file = "ruff-0.6.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1175d39faadd9a50718f478d23bfc1d4da5743f1ab56af81a2b6caf0a2394f23"},
|
||||
{file = "ruff-0.6.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5b939f9c86d51635fe486585389f54582f0d65b8238e08c327c1534844b3bb9a"},
|
||||
{file = "ruff-0.6.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d0d62ca91219f906caf9b187dea50d17353f15ec9bb15aae4a606cd697b49b4c"},
|
||||
{file = "ruff-0.6.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7438a7288f9d67ed3c8ce4d059e67f7ed65e9fe3aa2ab6f5b4b3610e57e3cb56"},
|
||||
{file = "ruff-0.6.2-py3-none-win32.whl", hash = "sha256:279d5f7d86696df5f9549b56b9b6a7f6c72961b619022b5b7999b15db392a4da"},
|
||||
{file = "ruff-0.6.2-py3-none-win_amd64.whl", hash = "sha256:d9f3469c7dd43cd22eb1c3fc16926fb8258d50cb1b216658a07be95dd117b0f2"},
|
||||
{file = "ruff-0.6.2-py3-none-win_arm64.whl", hash = "sha256:f28fcd2cd0e02bdf739297516d5643a945cc7caf09bd9bcb4d932540a5ea4fa9"},
|
||||
{file = "ruff-0.6.2.tar.gz", hash = "sha256:239ee6beb9e91feb8e0ec384204a763f36cb53fb895a1a364618c6abb076b3be"},
|
||||
{file = "ruff-0.6.3-py3-none-linux_armv6l.whl", hash = "sha256:97f58fda4e309382ad30ede7f30e2791d70dd29ea17f41970119f55bdb7a45c3"},
|
||||
{file = "ruff-0.6.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3b061e49b5cf3a297b4d1c27ac5587954ccb4ff601160d3d6b2f70b1622194dc"},
|
||||
{file = "ruff-0.6.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:34e2824a13bb8c668c71c1760a6ac7d795ccbd8d38ff4a0d8471fdb15de910b1"},
|
||||
{file = "ruff-0.6.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bddfbb8d63c460f4b4128b6a506e7052bad4d6f3ff607ebbb41b0aa19c2770d1"},
|
||||
{file = "ruff-0.6.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ced3eeb44df75353e08ab3b6a9e113b5f3f996bea48d4f7c027bc528ba87b672"},
|
||||
{file = "ruff-0.6.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47021dff5445d549be954eb275156dfd7c37222acc1e8014311badcb9b4ec8c1"},
|
||||
{file = "ruff-0.6.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d7bd20dc07cebd68cc8bc7b3f5ada6d637f42d947c85264f94b0d1cd9d87384"},
|
||||
{file = "ruff-0.6.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:500f166d03fc6d0e61c8e40a3ff853fa8a43d938f5d14c183c612df1b0d6c58a"},
|
||||
{file = "ruff-0.6.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42844ff678f9b976366b262fa2d1d1a3fe76f6e145bd92c84e27d172e3c34500"},
|
||||
{file = "ruff-0.6.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70452a10eb2d66549de8e75f89ae82462159855e983ddff91bc0bce6511d0470"},
|
||||
{file = "ruff-0.6.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:65a533235ed55f767d1fc62193a21cbf9e3329cf26d427b800fdeacfb77d296f"},
|
||||
{file = "ruff-0.6.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d2e2c23cef30dc3cbe9cc5d04f2899e7f5e478c40d2e0a633513ad081f7361b5"},
|
||||
{file = "ruff-0.6.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d8a136aa7d228975a6aee3dd8bea9b28e2b43e9444aa678fb62aeb1956ff2351"},
|
||||
{file = "ruff-0.6.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f92fe93bc72e262b7b3f2bba9879897e2d58a989b4714ba6a5a7273e842ad2f8"},
|
||||
{file = "ruff-0.6.3-py3-none-win32.whl", hash = "sha256:7a62d3b5b0d7f9143d94893f8ba43aa5a5c51a0ffc4a401aa97a81ed76930521"},
|
||||
{file = "ruff-0.6.3-py3-none-win_amd64.whl", hash = "sha256:746af39356fee2b89aada06c7376e1aa274a23493d7016059c3a72e3b296befb"},
|
||||
{file = "ruff-0.6.3-py3-none-win_arm64.whl", hash = "sha256:14a9528a8b70ccc7a847637c29e56fd1f9183a9db743bbc5b8e0c4ad60592a82"},
|
||||
{file = "ruff-0.6.3.tar.gz", hash = "sha256:183b99e9edd1ef63be34a3b51fee0a9f4ab95add123dbf89a71f7b1f0c991983"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4256,13 +4259,13 @@ django-query = ["django (>=3.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "selenium"
|
||||
version = "4.23.1"
|
||||
version = "4.24.0"
|
||||
description = "Official Python bindings for Selenium WebDriver"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "selenium-4.23.1-py3-none-any.whl", hash = "sha256:3a8d9f23dc636bd3840dd56f00c2739e32ec0c1e34a821dd553e15babef24477"},
|
||||
{file = "selenium-4.23.1.tar.gz", hash = "sha256:128d099e66284437e7128d2279176ec7a06e6ec7426e167f5d34987166bd8f46"},
|
||||
{file = "selenium-4.24.0-py3-none-any.whl", hash = "sha256:42c23f60753d5415b261b236cecbd69bd4eb5271e1563915f546b443cb6b71c6"},
|
||||
{file = "selenium-4.24.0.tar.gz", hash = "sha256:88281e5b5b90fe231868905d5ea745b9ee5e30db280b33498cc73fb0fa06d571"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -4652,13 +4655,13 @@ wsproto = ">=0.14"
|
||||
|
||||
[[package]]
|
||||
name = "twilio"
|
||||
version = "9.2.3"
|
||||
version = "9.2.4"
|
||||
description = "Twilio API client and TwiML generator"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "twilio-9.2.3-py2.py3-none-any.whl", hash = "sha256:76bfc39aa8d854510907cb7f9465814dfdea9e91ec199bb44f0785f05746f4cc"},
|
||||
{file = "twilio-9.2.3.tar.gz", hash = "sha256:da2255b5f3753cb3bf647fc6c50edbdb367ebc3cde6802806f6f863058a65f75"},
|
||||
{file = "twilio-9.2.4-py2.py3-none-any.whl", hash = "sha256:490da2518c0da370d738d436f9086b2463902707a811cd306ec8dcc8ce831758"},
|
||||
{file = "twilio-9.2.4.tar.gz", hash = "sha256:454b7d075c6bee3b64c81c39151be1f9105c695df6dbb0021b0c43e2930263e7"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -4669,13 +4672,13 @@ requests = ">=2.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "twisted"
|
||||
version = "24.3.0"
|
||||
version = "24.7.0"
|
||||
description = "An asynchronous networking framework written in Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8.0"
|
||||
files = [
|
||||
{file = "twisted-24.3.0-py3-none-any.whl", hash = "sha256:039f2e6a49ab5108abd94de187fa92377abe5985c7a72d68d0ad266ba19eae63"},
|
||||
{file = "twisted-24.3.0.tar.gz", hash = "sha256:6b38b6ece7296b5e122c9eb17da2eeab3d98a198f50ca9efd00fb03e5b4fd4ae"},
|
||||
{file = "twisted-24.7.0-py3-none-any.whl", hash = "sha256:734832ef98108136e222b5230075b1079dad8a3fc5637319615619a7725b0c81"},
|
||||
{file = "twisted-24.7.0.tar.gz", hash = "sha256:5a60147f044187a127ec7da96d170d49bcce50c6fd36f594e60f4587eff4d394"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -4684,55 +4687,26 @@ automat = ">=0.8.0"
|
||||
constantly = ">=15.1"
|
||||
hyperlink = ">=17.1.1"
|
||||
idna = {version = ">=2.4", optional = true, markers = "extra == \"tls\""}
|
||||
incremental = ">=22.10.0"
|
||||
incremental = ">=24.7.0"
|
||||
pyopenssl = {version = ">=21.0.0", optional = true, markers = "extra == \"tls\""}
|
||||
service-identity = {version = ">=18.1.0", optional = true, markers = "extra == \"tls\""}
|
||||
twisted-iocpsupport = {version = ">=1.0.2,<2", markers = "platform_system == \"Windows\""}
|
||||
typing-extensions = ">=4.2.0"
|
||||
zope-interface = ">=5"
|
||||
|
||||
[package.extras]
|
||||
all-non-platform = ["twisted[conch,http2,serial,test,tls]", "twisted[conch,http2,serial,test,tls]"]
|
||||
all-non-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
|
||||
conch = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)"]
|
||||
dev = ["coverage (>=6b1,<7)", "pyflakes (>=2.2,<3.0)", "python-subunit (>=1.4,<2.0)", "twisted[dev-release]", "twistedchecker (>=0.7,<1.0)"]
|
||||
dev = ["coverage (>=7.5,<8.0)", "cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pydoctor (>=23.9.0,<23.10.0)", "pyflakes (>=2.2,<3.0)", "pyhamcrest (>=2)", "python-subunit (>=1.4,<2.0)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "twistedchecker (>=0.7,<1.0)"]
|
||||
dev-release = ["pydoctor (>=23.9.0,<23.10.0)", "pydoctor (>=23.9.0,<23.10.0)", "sphinx (>=6,<7)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "towncrier (>=23.6,<24.0)"]
|
||||
gtk-platform = ["pygobject", "pygobject", "twisted[all-non-platform]", "twisted[all-non-platform]"]
|
||||
gtk-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pygobject", "pygobject", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
|
||||
http2 = ["h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)"]
|
||||
macos-platform = ["pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "twisted[all-non-platform]", "twisted[all-non-platform]"]
|
||||
mypy = ["mypy (>=1.8,<2.0)", "mypy-zope (>=1.0.3,<1.1.0)", "twisted[all-non-platform,dev]", "types-pyopenssl", "types-setuptools"]
|
||||
osx-platform = ["twisted[macos-platform]", "twisted[macos-platform]"]
|
||||
macos-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
|
||||
mypy = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "coverage (>=7.5,<8.0)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "idna (>=2.4)", "mypy (>=1.8,<2.0)", "mypy-zope (>=1.0.3,<1.1.0)", "priority (>=1.1.0,<2.0)", "pydoctor (>=23.9.0,<23.10.0)", "pyflakes (>=2.2,<3.0)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "python-subunit (>=1.4,<2.0)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "twistedchecker (>=0.7,<1.0)", "types-pyopenssl", "types-setuptools"]
|
||||
osx-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
|
||||
serial = ["pyserial (>=3.0)", "pywin32 (!=226)"]
|
||||
test = ["cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pyhamcrest (>=2)"]
|
||||
tls = ["idna (>=2.4)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)"]
|
||||
windows-platform = ["pywin32 (!=226)", "pywin32 (!=226)", "twisted[all-non-platform]", "twisted[all-non-platform]"]
|
||||
|
||||
[[package]]
|
||||
name = "twisted-iocpsupport"
|
||||
version = "1.0.4"
|
||||
description = "An extension for use in the twisted I/O Completion Ports reactor."
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "twisted-iocpsupport-1.0.4.tar.gz", hash = "sha256:858096c0d15e33f15ac157f455d8f86f2f2cdd223963e58c0f682a3af8362d89"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp310-cp310-win32.whl", hash = "sha256:afa2b630797f9ed2f27f3d9f55e3f72b4244911e45a8c82756f44babbf0b243e"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:0058c963c8957bcd3deda62122e89953c9de1e867a274facc9b15dde1a9f31e8"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp311-cp311-win32.whl", hash = "sha256:196f7c7ccad4ba4d1783b1c4e1d1b22d93c04275cd780bf7498d16c77319ad6e"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:4e5f97bcbabdd79cbaa969b63439b89801ea560f11d42b0a387634275c633623"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp312-cp312-win32.whl", hash = "sha256:6081bd7c2f4fcf9b383dcdb3b3385d75a26a7c9d2be25b6950c3d8ea652d2d2d"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:76f7e67cec1f1d097d1f4ed7de41be3d74546e1a4ede0c7d56e775c4dce5dfb0"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:3d306fc4d88a6bcf61ce9d572c738b918578121bfd72891625fab314549024b5"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:391ac4d6002a80e15f35adc4ad6056f4fe1c17ceb0d1f98ba01b0f4f917adfd7"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:0c1b5cf37f0b2d96cc3c9bc86fff16613b9f5d0ca565c96cf1f1fb8cfca4b81c"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:3c5dc11d72519e55f727320e3cee535feedfaee09c0f0765ed1ca7badff1ab3c"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp38-cp38-win32.whl", hash = "sha256:cc86c2ef598c15d824a243c2541c29459881c67fc3c0adb6efe2242f8f0ec3af"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c27985e949b9b1a1fb4c20c71d315c10ea0f93fdf3ccdd4a8c158b5926edd8c8"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp39-cp39-win32.whl", hash = "sha256:e311dfcb470696e3c077249615893cada598e62fa7c4e4ca090167bd2b7d331f"},
|
||||
{file = "twisted_iocpsupport-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4574eef1f3bb81501fb02f911298af3c02fe8179c31a33b361dd49180c3e644d"},
|
||||
{file = "twisted_iocpsupport-1.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:872747a3b64e2909aee59c803ccd0bceb9b75bf27915520ebd32d69687040fa2"},
|
||||
{file = "twisted_iocpsupport-1.0.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:c2712b778bacf1db434e3e065adfed3db300754186a29aecac1efae9ef4bcaff"},
|
||||
{file = "twisted_iocpsupport-1.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7c66fa0aa4236b27b3c61cb488662d85dae746a6d1c7b0d91cf7aae118445adf"},
|
||||
{file = "twisted_iocpsupport-1.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:300437af17396a945a58dcfffd77863303a8b6d9e65c6e81f1d2eed55b50d444"},
|
||||
]
|
||||
windows-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)", "twisted-iocpsupport (>=1.0.2)", "twisted-iocpsupport (>=1.0.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "txaio"
|
||||
@ -4896,46 +4870,41 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "watchdog"
|
||||
version = "4.0.2"
|
||||
version = "5.0.1"
|
||||
description = "Filesystem events monitoring"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"},
|
||||
{file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"},
|
||||
{file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"},
|
||||
{file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"},
|
||||
{file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"},
|
||||
{file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"},
|
||||
{file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"},
|
||||
{file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"},
|
||||
{file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"},
|
||||
{file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"},
|
||||
{file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"},
|
||||
{file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"},
|
||||
{file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"},
|
||||
{file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"},
|
||||
{file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"},
|
||||
{file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"},
|
||||
{file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"},
|
||||
{file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"},
|
||||
{file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"},
|
||||
{file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"},
|
||||
{file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"},
|
||||
{file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"},
|
||||
{file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"},
|
||||
{file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"},
|
||||
{file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"},
|
||||
{file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"},
|
||||
{file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"},
|
||||
{file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"},
|
||||
{file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"},
|
||||
{file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"},
|
||||
{file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"},
|
||||
{file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"},
|
||||
{file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"},
|
||||
{file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"},
|
||||
{file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"},
|
||||
{file = "watchdog-5.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a6b8c6c82ada78479a0df568d27d69aa07105aba9301ac66d1ae162645f4ba34"},
|
||||
{file = "watchdog-5.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e8ca9b7f5f03d2f0556a43db1e9adf1e5af6adf52e0890f781324514b67a612"},
|
||||
{file = "watchdog-5.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c92812a358eabebe92b12b9290d16dc95c8003654658f6b2676c9a2103a73ceb"},
|
||||
{file = "watchdog-5.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a03a6ccb846ead406a25a0b702d0a6b88fdfa77becaf907cfcfce7737ebbda1f"},
|
||||
{file = "watchdog-5.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39f0de161a822402f0f00c68b82349a4d71c9814e749148ca2b083a25606dbf9"},
|
||||
{file = "watchdog-5.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5541a8765c4090decb4dba55d3dceb57724748a717ceaba8dc4f213edb0026e0"},
|
||||
{file = "watchdog-5.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e321f1561adea30e447130882efe451af519646178d04189d6ba91a8cd7d88a5"},
|
||||
{file = "watchdog-5.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c4ae0b3e95455fa9d959aa3b253c87845ad454ef188a4bf5a69cab287c131216"},
|
||||
{file = "watchdog-5.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b2d56425dfa0c1e6f8a510f21d3d54ef7fe50bbc29638943c2cb1394b7b49156"},
|
||||
{file = "watchdog-5.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:70e30116849f4ec52240eb1fad83d27e525eae179bfe1c09b3bf120163d731b6"},
|
||||
{file = "watchdog-5.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f66df2c152edf5a2fe472bb2f8a5d562165bcf6cf9686cee5d75e524c21ca895"},
|
||||
{file = "watchdog-5.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6bb68d9adb9c45f0dc1c2b12f4fb6eab0463a8f9741e371e4ede6769064e0785"},
|
||||
{file = "watchdog-5.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6fbb4dd5ace074a2969825fde10034b35b31efcb6973defb22eb945b1d3acc37"},
|
||||
{file = "watchdog-5.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:753c6a4c1eea9d3b96cd58159b49103e66cb288216a414ab9ad234ccc7642ec2"},
|
||||
{file = "watchdog-5.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:20a28c8b0b3edf4ea2b27fb3527fc0a348e983f22a4317d316bb561524391932"},
|
||||
{file = "watchdog-5.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a1cd7c919940b15f253db8279a579fb81e4e4e434b39b11a1cb7f54fe3fa46a6"},
|
||||
{file = "watchdog-5.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a791dfc050ed24b82f7f100ae794192594fe863a7e9bdafcdfa5c6e405a981e5"},
|
||||
{file = "watchdog-5.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8ba1472b5fa7c644e49641f70d7ccc567f70b54d776defa5d6f755dc2edc3fbb"},
|
||||
{file = "watchdog-5.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b21e6601efe8453514c2fc21aca57fb5413c3d8b157bfe520b05b57b1788a167"},
|
||||
{file = "watchdog-5.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:763c6f82bb65504b47d4aea268462b2fb662676676356e04787f332a11f03eb0"},
|
||||
{file = "watchdog-5.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:664917cd513538728875a42d5654584b533da88cf06680452c98e73b45466968"},
|
||||
{file = "watchdog-5.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:39e828c4270452b966bc9d814911a3c7e24c62d726d2a3245f5841664ff56b5e"},
|
||||
{file = "watchdog-5.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:59ec6111f3750772badae3403ef17263489ed6f27ac01ec50c0244b2afa258fb"},
|
||||
{file = "watchdog-5.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f3006361dba2005552cc8aa49c44d16a10e0a1939bb3286e888a14f722122808"},
|
||||
{file = "watchdog-5.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:72dbdffe4aa0c36c59f4a5190bceeb7fdfdf849ab98a562b3a783a64cc6dacdd"},
|
||||
{file = "watchdog-5.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c93aa24899cb4e8a51492c7ccc420bea45ced502fe9ef2e83f9ab1107e5a13b5"},
|
||||
{file = "watchdog-5.0.1-py3-none-win32.whl", hash = "sha256:2b8cd627b76194e725ed6f48d9524b1ad93a51a0dc3bd0225c56023716245091"},
|
||||
{file = "watchdog-5.0.1-py3-none-win_amd64.whl", hash = "sha256:4eaebff2f938f5325788cef26521891b2d8ecc8e7852aa123a9b458815f93875"},
|
||||
{file = "watchdog-5.0.1-py3-none-win_ia64.whl", hash = "sha256:9b1b32f89f95162f09aea6e15d9384f6e0490152f10d7ed241f8a85cddc50658"},
|
||||
{file = "watchdog-5.0.1.tar.gz", hash = "sha256:f0180e84e6493ef7c82e051334e8c9b00ffd89fa9de5e0613d3c267f6ccf2d38"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "authentik"
|
||||
version = "2024.6.4"
|
||||
version = "2024.8.0"
|
||||
description = ""
|
||||
authors = ["authentik Team <hello@goauthentik.io>"]
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: authentik
|
||||
version: 2024.6.4
|
||||
version: 2024.8.0
|
||||
description: Making authentication simple.
|
||||
contact:
|
||||
email: hello@goauthentik.io
|
||||
|
4270
tests/wdio/package-lock.json
generated
4270
tests/wdio/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,13 @@
|
||||
{
|
||||
"name": "@goauthentik/web-tests",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"chromedriver": "^128.0.1",
|
||||
"lockfile-lint": "^4.14.0",
|
||||
"syncpack": "^13.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/mocha": "^10.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "^7.17.0",
|
||||
"@typescript-eslint/parser": "^7.17.0",
|
||||
"@wdio/cli": "^9.0.3",
|
||||
@ -19,19 +23,20 @@
|
||||
"typescript": "^5.5.4",
|
||||
"wdio-wait-for": "^3.0.11"
|
||||
},
|
||||
"scripts": {
|
||||
"wdio": "wdio run ./wdio.conf.ts",
|
||||
"lint:precommit": "eslint --max-warnings 0 --config ./.eslintrc.precommit.json $(git status --porcelain . | grep '^[AM?][M?]' | cut -d'/' -f3- | grep -E '\\.(ts|js|tsx|jsx)$')",
|
||||
"lint": "eslint . --max-warnings 0 --fix",
|
||||
"lint:spelling": "codespell -D - -D $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-dictionary.txt -I $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-words.txt ./test -s",
|
||||
"precommit": "run-s lint:precommit lint:spelling prettier",
|
||||
"prettier-check": "prettier --check .",
|
||||
"prettier": "prettier --write ."
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"dependencies": {
|
||||
"chromedriver": "^128.0.0"
|
||||
}
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"lint": "eslint . --max-warnings 0 --fix",
|
||||
"lint:lockfile": "lockfile-lint --path package.json --type npm --allowed-hosts npm --validate-https",
|
||||
"lint:package": "syncpack format -i ' '",
|
||||
"lint:precommit": "eslint --max-warnings 0 --config ./.eslintrc.precommit.json $(git status --porcelain . | grep '^[AM?][M?]' | cut -d'/' -f3- | grep -E '\\.(ts|js|tsx|jsx)$')",
|
||||
"lint:spelling": "codespell -D - -D $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-dictionary.txt -I $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-words.txt ./test -s",
|
||||
"precommit": "run-s lint:precommit lint:spelling prettier",
|
||||
"prettier": "prettier --write .",
|
||||
"prettier-check": "prettier --check .",
|
||||
"wdio": "wdio run ./wdio.conf.ts"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
@ -1,25 +1,11 @@
|
||||
import Page from "../pageobjects/page.js";
|
||||
import { browser } from "@wdio/globals";
|
||||
|
||||
const CLICK_TIME_DELAY = 250;
|
||||
|
||||
export default class AdminPage extends Page {
|
||||
public get pageHeader() {
|
||||
return $('>>>ak-page-header slot[name="header"]');
|
||||
public async pageHeader() {
|
||||
return await $("ak-page-header").$('slot[name="header"]');
|
||||
}
|
||||
|
||||
async openApplicationsListPage() {
|
||||
await this.open("if/admin/#/core/applications");
|
||||
}
|
||||
|
||||
public open(path: string) {
|
||||
return browser.url(`http://localhost:9000/${path}`);
|
||||
}
|
||||
|
||||
public pause(selector?: string) {
|
||||
if (selector) {
|
||||
return $(selector).waitForDisplayed();
|
||||
}
|
||||
return browser.pause(CLICK_TIME_DELAY);
|
||||
}
|
||||
}
|
||||
|
@ -27,24 +27,24 @@ class ApplicationWizardView extends AdminPage {
|
||||
radius = RadiusForm;
|
||||
app = ApplicationForm;
|
||||
|
||||
get wizardTitle() {
|
||||
return $(">>>ak-wizard-frame .pf-c-wizard__header h1.pf-c-title");
|
||||
async wizardTitle() {
|
||||
return await $("ak-wizard-frame").$(".pf-c-wizard__title");
|
||||
}
|
||||
|
||||
get providerList() {
|
||||
return $(">>>ak-application-wizard-authentication-method-choice");
|
||||
async providerList() {
|
||||
return await $("ak-application-wizard-authentication-method-choice");
|
||||
}
|
||||
|
||||
get nextButton() {
|
||||
return $(">>>ak-wizard-frame footer button.pf-m-primary");
|
||||
async nextButton() {
|
||||
return await $("ak-wizard-frame").$("footer button.pf-m-primary");
|
||||
}
|
||||
|
||||
async getProviderType(type: string) {
|
||||
return await this.providerList.$(`>>>input[value="${type}"]`);
|
||||
return await this.providerList().$(`input[value="${type}"]`);
|
||||
}
|
||||
|
||||
get successMessage() {
|
||||
return $('>>>[data-commit-state="success"]');
|
||||
async successMessage() {
|
||||
return await $('[data-commit-state="success"]');
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,8 +65,10 @@ const providerValues: Pair[] = [
|
||||
providerValues.forEach(([value, name]: Pair) => {
|
||||
Object.defineProperties(ApplicationWizardView.prototype, {
|
||||
[name]: {
|
||||
get: function () {
|
||||
return this.providerList.$(`>>>input[value="${value}"]`);
|
||||
get: async function () {
|
||||
return await (
|
||||
await this.providerList()
|
||||
).$(`div[data-ouid-component-name="${value}"]`);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -9,8 +9,8 @@ class ApplicationsListPage extends AdminPage {
|
||||
* define selectors using getter methods
|
||||
*/
|
||||
|
||||
get startWizardButton() {
|
||||
return $('>>>ak-wizard-frame button[slot="trigger"]');
|
||||
async startWizardButton() {
|
||||
return await $("ak-application-wizard").$('button[slot="trigger"]');
|
||||
}
|
||||
|
||||
async open() {
|
||||
|
@ -2,16 +2,16 @@ import Page from "../page.js";
|
||||
import { $ } from "@wdio/globals";
|
||||
|
||||
export class ApplicationForm extends Page {
|
||||
get name() {
|
||||
return $('>>>ak-form-element-horizontal input[name="name"]');
|
||||
async name() {
|
||||
return await $('ak-text-input[name="name"]').$("input");
|
||||
}
|
||||
|
||||
get uiSettings() {
|
||||
return $('>>>ak-form-group button[aria-label="UI Settings"]');
|
||||
async uiSettings() {
|
||||
return await $("ak-form-group").$('button[aria-label="UI Settings"]');
|
||||
}
|
||||
|
||||
get launchUrl() {
|
||||
return $('>>>input[name="metaLaunchUrl"]');
|
||||
async launchUrl() {
|
||||
return await $('input[name="metaLaunchUrl"]');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,14 @@ import { $ } from "@wdio/globals";
|
||||
export class ForwardProxyForm extends Page {
|
||||
async setAuthorizationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'ak-flow-search[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
selector,
|
||||
);
|
||||
}
|
||||
|
||||
get externalHost() {
|
||||
return $('>>>input[name="externalHost"]');
|
||||
return $('input[name="externalHost"]');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import Page from "../page.js";
|
||||
|
||||
export class LdapForm extends Page {
|
||||
async setBindFlow(selector: string) {
|
||||
async setBindFlow(_selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-branded-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'ak-search-select-view[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
"default-authentication-flow",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ import { $ } from "@wdio/globals";
|
||||
export class OauthForm extends Page {
|
||||
async setAuthorizationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'ak-flow-search[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
`${selector}`,
|
||||
);
|
||||
}
|
||||
|
||||
get providerName() {
|
||||
return $('>>>ak-form-element-horizontal[name="name"] input');
|
||||
async providerName() {
|
||||
return await $('ak-form-element-horizontal[name="name"]').$("input");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@ import Page from "../page.js";
|
||||
export class RadiusForm extends Page {
|
||||
async setAuthenticationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-branded-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'ak-branded-flow-search[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
selector,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ import { $ } from "@wdio/globals";
|
||||
export class SamlForm extends Page {
|
||||
async setAuthorizationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'ak-flow-search[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
selector,
|
||||
);
|
||||
}
|
||||
|
||||
get acsUrl() {
|
||||
return $('>>>input[name="acsUrl"]');
|
||||
return $('input[name="acsUrl"]');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,11 @@ import Page from "../page.js";
|
||||
|
||||
export class ScimForm extends Page {
|
||||
get url() {
|
||||
return $('>>>input[name="url"]');
|
||||
return $('input[name="url"]');
|
||||
}
|
||||
|
||||
get token() {
|
||||
return $('>>>input[name="token"]');
|
||||
return $('input[name="token"]');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,18 +4,18 @@ import { $ } from "@wdio/globals";
|
||||
export class TransparentProxyForm extends Page {
|
||||
async setAuthorizationFlow(selector: string) {
|
||||
await this.searchSelect(
|
||||
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
|
||||
'ak-flow-search[name="authorizationFlow"]',
|
||||
"authorizationFlow",
|
||||
`button*=${selector}`,
|
||||
selector,
|
||||
);
|
||||
}
|
||||
|
||||
get externalHost() {
|
||||
return $('>>>input[name="externalHost"]');
|
||||
return $('input[name="externalHost"]');
|
||||
}
|
||||
|
||||
get internalHost() {
|
||||
return $('>>>input[name="internalHost"]');
|
||||
return $('input[name="internalHost"]');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,20 +9,20 @@ class LoginPage extends Page {
|
||||
/**
|
||||
* Selectors
|
||||
*/
|
||||
get inputUsername() {
|
||||
return $('>>>input[name="uidField"]');
|
||||
async inputUsername() {
|
||||
return await $('input[name="uidField"]');
|
||||
}
|
||||
|
||||
get inputPassword() {
|
||||
return $('>>>input[name="password"]');
|
||||
async inputPassword() {
|
||||
return await $('input[name="password"]');
|
||||
}
|
||||
|
||||
get btnSubmit() {
|
||||
return $('>>>button[type="submit"]');
|
||||
async btnSubmit() {
|
||||
return await $('button[type="submit"]');
|
||||
}
|
||||
|
||||
get authFailure() {
|
||||
return $(">>>h4.pf-c-alert__title");
|
||||
async authFailure() {
|
||||
return await $(".pf-m-error");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,17 +30,15 @@ class LoginPage extends Page {
|
||||
*/
|
||||
|
||||
async username(username: string) {
|
||||
await this.inputUsername.waitForClickable();
|
||||
await this.inputUsername.setValue(username);
|
||||
await this.btnSubmit.waitForEnabled();
|
||||
await this.btnSubmit.click();
|
||||
await (await this.inputUsername()).setValue(username);
|
||||
await (await this.btnSubmit()).waitForEnabled();
|
||||
await (await this.btnSubmit()).click();
|
||||
}
|
||||
|
||||
async password(password: string) {
|
||||
await this.inputPassword.waitForClickable();
|
||||
await this.inputPassword.setValue(password);
|
||||
await this.btnSubmit.waitForEnabled();
|
||||
await this.btnSubmit.click();
|
||||
await (await this.inputPassword()).setValue(password);
|
||||
await (await this.btnSubmit()).waitForEnabled();
|
||||
await (await this.btnSubmit()).click();
|
||||
}
|
||||
|
||||
async login(username: string, password: string) {
|
||||
@ -48,7 +46,7 @@ class LoginPage extends Page {
|
||||
await this.pause();
|
||||
await this.password(password);
|
||||
await this.pause();
|
||||
await this.pause(">>>div.header h1");
|
||||
await this.pause("div.header h1");
|
||||
return UserLibraryPage;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { browser } from "@wdio/globals";
|
||||
import { Key } from "webdriverio";
|
||||
|
||||
const CLICK_TIME_DELAY = 250;
|
||||
|
||||
@ -11,15 +12,15 @@ export default class Page {
|
||||
* Opens a sub page of the page
|
||||
* @param path path of the sub page (e.g. /path/to/page.html)
|
||||
*/
|
||||
public open(path: string) {
|
||||
return browser.url(`http://localhost:9000/${path}`);
|
||||
public async open(path: string) {
|
||||
return await browser.url(`http://localhost:9000/${path}`);
|
||||
}
|
||||
|
||||
public pause(selector?: string) {
|
||||
public async pause(selector?: string) {
|
||||
if (selector) {
|
||||
return $(selector).waitForDisplayed();
|
||||
return await $(selector).waitForDisplayed();
|
||||
}
|
||||
return browser.pause(CLICK_TIME_DELAY);
|
||||
return await browser.pause(CLICK_TIME_DELAY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -33,10 +34,20 @@ export default class Page {
|
||||
|
||||
async searchSelect(searchSelector: string, managedSelector: string, buttonSelector: string) {
|
||||
const inputBind = await $(searchSelector);
|
||||
await inputBind.click();
|
||||
const searchBlock = await $(`>>>div[data-managed-for="${managedSelector}"]`);
|
||||
const target = searchBlock.$(buttonSelector);
|
||||
return await target.click();
|
||||
const inputMain = await inputBind.$('input[type="text"]');
|
||||
await inputMain.click();
|
||||
const searchBlock = await (
|
||||
await $(`div[data-managed-for="${managedSelector}"]`).$("ak-list-select")
|
||||
).shadow$$("button");
|
||||
let target: WebdriverIO.Element;
|
||||
for (const button of searchBlock) {
|
||||
if ((await button.getText()).includes(buttonSelector)) {
|
||||
target = button;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await (await target).click();
|
||||
await browser.keys(Key.Tab);
|
||||
}
|
||||
|
||||
public async logout() {
|
||||
|
@ -9,13 +9,13 @@ class UserLibraryPage extends Page {
|
||||
* define selectors using getter methods
|
||||
*/
|
||||
|
||||
public get pageHeader() {
|
||||
return $('>>>h1[aria-level="1"]');
|
||||
public async pageHeader() {
|
||||
return await $('h1[aria-level="1"]');
|
||||
}
|
||||
|
||||
public async goToAdmin() {
|
||||
await $('>>>a[href="/if/admin"]').click();
|
||||
await $(">>>ak-admin-overview").waitForDisplayed();
|
||||
await $('a[href="/if/admin"]').click();
|
||||
return await $("ak-admin-overview").waitForDisplayed();
|
||||
}
|
||||
}
|
||||
|
||||
|
15
tests/wdio/test/specs/bad-logins-2.ts
Normal file
15
tests/wdio/test/specs/bad-logins-2.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import LoginPage from "../pageobjects/login.page.js";
|
||||
import { BAD_PASSWORD, GOOD_USERNAME } from "../utils/constants.js";
|
||||
import { expect } from "@wdio/globals";
|
||||
|
||||
describe("Log into authentik", () => {
|
||||
it("should fail on a bad password", async () => {
|
||||
await LoginPage.open();
|
||||
await LoginPage.username(GOOD_USERNAME);
|
||||
await LoginPage.pause();
|
||||
await LoginPage.password(BAD_PASSWORD);
|
||||
const failure = await LoginPage.authFailure();
|
||||
await expect(failure).toBeDisplayedInViewport();
|
||||
await expect(failure).toHaveText("Invalid password");
|
||||
});
|
||||
});
|
@ -1,21 +1,15 @@
|
||||
import LoginPage from "../pageobjects/login.page.js";
|
||||
import { BAD_PASSWORD, BAD_USERNAME, GOOD_USERNAME } from "../utils/constants.js";
|
||||
import { BAD_USERNAME, GOOD_PASSWORD } from "../utils/constants.js";
|
||||
import { expect } from "@wdio/globals";
|
||||
|
||||
describe("Log into authentik", () => {
|
||||
it("should fail on a bad username", async () => {
|
||||
await LoginPage.open();
|
||||
await LoginPage.username(BAD_USERNAME);
|
||||
const failure = await LoginPage.authFailure;
|
||||
expect(failure).toHaveText("Failed to authenticate.");
|
||||
});
|
||||
|
||||
it("should fail on a bad password", async () => {
|
||||
await LoginPage.open();
|
||||
await LoginPage.username(GOOD_USERNAME);
|
||||
await LoginPage.pause();
|
||||
await LoginPage.password(BAD_PASSWORD);
|
||||
const failure = await LoginPage.authFailure;
|
||||
expect(failure).toHaveText("Failed to authenticate.");
|
||||
await LoginPage.password(GOOD_PASSWORD);
|
||||
const failure = await LoginPage.authFailure();
|
||||
await expect(failure).toBeDisplayedInViewport();
|
||||
await expect(failure).toHaveText("Invalid password");
|
||||
});
|
||||
});
|
||||
|
@ -10,25 +10,27 @@ async function reachTheProvider(title: string) {
|
||||
await ApplicationsListPage.logout();
|
||||
await login();
|
||||
await ApplicationsListPage.open();
|
||||
await expect(await ApplicationsListPage.pageHeader).toHaveText("Applications");
|
||||
await ApplicationsListPage.pause("ak-page-header");
|
||||
await expect(await ApplicationsListPage.pageHeader()).toBeDisplayed();
|
||||
await expect(await ApplicationsListPage.pageHeader()).toHaveText("Applications");
|
||||
|
||||
await ApplicationsListPage.startWizardButton.click();
|
||||
await ApplicationWizardView.wizardTitle.waitForDisplayed();
|
||||
await expect(await ApplicationWizardView.wizardTitle).toHaveText("New application");
|
||||
await (await ApplicationsListPage.startWizardButton()).click();
|
||||
await (await ApplicationWizardView.wizardTitle()).waitForDisplayed();
|
||||
await expect(await ApplicationWizardView.wizardTitle()).toHaveText("New application");
|
||||
|
||||
await ApplicationWizardView.app.name.setValue(`${title} - ${newPrefix}`);
|
||||
await ApplicationWizardView.app.uiSettings.scrollIntoView();
|
||||
await ApplicationWizardView.app.uiSettings.click();
|
||||
await ApplicationWizardView.app.launchUrl.scrollIntoView();
|
||||
await ApplicationWizardView.app.launchUrl.setValue("http://example.goauthentik.io");
|
||||
await (await ApplicationWizardView.app.name()).setValue(`${title} - ${newPrefix}`);
|
||||
await (await ApplicationWizardView.app.uiSettings()).scrollIntoView();
|
||||
await (await ApplicationWizardView.app.uiSettings()).click();
|
||||
await (await ApplicationWizardView.app.launchUrl()).scrollIntoView();
|
||||
await (await ApplicationWizardView.app.launchUrl()).setValue("http://example.goauthentik.io");
|
||||
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
return await ApplicationWizardView.pause();
|
||||
}
|
||||
|
||||
async function getCommitMessage() {
|
||||
await ApplicationWizardView.successMessage.waitForDisplayed();
|
||||
return await ApplicationWizardView.successMessage;
|
||||
await (await ApplicationWizardView.successMessage()).waitForDisplayed();
|
||||
return await ApplicationWizardView.successMessage();
|
||||
}
|
||||
|
||||
const SUCCESS_MESSAGE = "Your application has been saved";
|
||||
@ -38,97 +40,97 @@ describe("Configure Applications with the Application Wizard", () => {
|
||||
it("Should configure a simple LDAP Application", async () => {
|
||||
await reachTheProvider("New LDAP Application");
|
||||
|
||||
await ApplicationWizardView.providerList.waitForDisplayed();
|
||||
await ApplicationWizardView.ldapProvider.scrollIntoView();
|
||||
await ApplicationWizardView.ldapProvider.click();
|
||||
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
||||
await (await ApplicationWizardView.ldapProvider).scrollIntoView();
|
||||
await (await ApplicationWizardView.ldapProvider).click();
|
||||
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await ApplicationWizardView.ldap.setBindFlow("default-authentication-flow");
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
});
|
||||
|
||||
it("Should configure a simple Oauth2 Application", async () => {
|
||||
await reachTheProvider("New Oauth2 Application");
|
||||
|
||||
await ApplicationWizardView.providerList.waitForDisplayed();
|
||||
await ApplicationWizardView.oauth2Provider.scrollIntoView();
|
||||
await ApplicationWizardView.oauth2Provider.click();
|
||||
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
||||
await (await ApplicationWizardView.oauth2Provider).scrollIntoView();
|
||||
await (await ApplicationWizardView.oauth2Provider).click();
|
||||
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await ApplicationWizardView.oauth.setAuthorizationFlow(EXPLICIT_CONSENT);
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
});
|
||||
|
||||
it("Should configure a simple SAML Application", async () => {
|
||||
await reachTheProvider("New SAML Application");
|
||||
|
||||
await ApplicationWizardView.providerList.waitForDisplayed();
|
||||
await ApplicationWizardView.samlProvider.scrollIntoView();
|
||||
await ApplicationWizardView.samlProvider.click();
|
||||
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
||||
await (await ApplicationWizardView.samlProvider).scrollIntoView();
|
||||
await (await ApplicationWizardView.samlProvider).click();
|
||||
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await ApplicationWizardView.saml.setAuthorizationFlow(EXPLICIT_CONSENT);
|
||||
await ApplicationWizardView.saml.acsUrl.setValue("http://example.com:8000/");
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
});
|
||||
|
||||
it("Should configure a simple SCIM Application", async () => {
|
||||
await reachTheProvider("New SCIM Application");
|
||||
|
||||
await ApplicationWizardView.providerList.waitForDisplayed();
|
||||
await ApplicationWizardView.scimProvider.scrollIntoView();
|
||||
await ApplicationWizardView.scimProvider.click();
|
||||
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
||||
await (await ApplicationWizardView.scimProvider).scrollIntoView();
|
||||
await (await ApplicationWizardView.scimProvider).click();
|
||||
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await ApplicationWizardView.scim.url.setValue("http://example.com:8000/");
|
||||
await ApplicationWizardView.scim.token.setValue("a-very-basic-token");
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
});
|
||||
|
||||
it("Should configure a simple Radius Application", async () => {
|
||||
await reachTheProvider("New Radius Application");
|
||||
|
||||
await ApplicationWizardView.providerList.waitForDisplayed();
|
||||
await ApplicationWizardView.radiusProvider.scrollIntoView();
|
||||
await ApplicationWizardView.radiusProvider.click();
|
||||
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
||||
await (await ApplicationWizardView.radiusProvider).scrollIntoView();
|
||||
await (await ApplicationWizardView.radiusProvider).click();
|
||||
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await ApplicationWizardView.radius.setAuthenticationFlow("default-authentication-flow");
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
});
|
||||
|
||||
it("Should configure a simple Transparent Proxy Application", async () => {
|
||||
await reachTheProvider("New Transparent Proxy Application");
|
||||
|
||||
await ApplicationWizardView.providerList.waitForDisplayed();
|
||||
await ApplicationWizardView.proxyProviderProxy.scrollIntoView();
|
||||
await ApplicationWizardView.proxyProviderProxy.click();
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
||||
await (await ApplicationWizardView.proxyProviderProxy).scrollIntoView();
|
||||
await (await ApplicationWizardView.proxyProviderProxy).click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await ApplicationWizardView.transparentProxy.setAuthorizationFlow(EXPLICIT_CONSENT);
|
||||
@ -139,19 +141,19 @@ describe("Configure Applications with the Application Wizard", () => {
|
||||
"http://internal.example.com",
|
||||
);
|
||||
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
});
|
||||
|
||||
it("Should configure a simple Forward Proxy Application", async () => {
|
||||
await reachTheProvider("New Forward Proxy Application");
|
||||
|
||||
await ApplicationWizardView.providerList.waitForDisplayed();
|
||||
await ApplicationWizardView.proxyProviderForwardsingle.scrollIntoView();
|
||||
await ApplicationWizardView.proxyProviderForwardsingle.click();
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.providerList()).waitForDisplayed();
|
||||
await (await ApplicationWizardView.proxyProviderForwardsingle).scrollIntoView();
|
||||
await (await ApplicationWizardView.proxyProviderForwardsingle).click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await ApplicationWizardView.forwardProxy.setAuthorizationFlow(EXPLICIT_CONSENT);
|
||||
@ -159,9 +161,9 @@ describe("Configure Applications with the Application Wizard", () => {
|
||||
"http://external.example.com",
|
||||
);
|
||||
|
||||
await ApplicationWizardView.nextButton.click();
|
||||
await (await ApplicationWizardView.nextButton()).click();
|
||||
await ApplicationWizardView.pause();
|
||||
|
||||
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
|
||||
});
|
||||
});
|
||||
|
@ -6,5 +6,5 @@ import { expect } from "@wdio/globals";
|
||||
export const login = async () => {
|
||||
await LoginPage.open();
|
||||
await LoginPage.login(GOOD_USERNAME, GOOD_PASSWORD);
|
||||
await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
|
||||
await expect(await UserLibraryPage.pageHeader()).toHaveText("My applications");
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
"moduleResolution": "node",
|
||||
"module": "ESNext",
|
||||
"target": "es2022",
|
||||
"types": ["node", "@wdio/globals/types", "expect-webdriverio", "@wdio/mocha-framework"],
|
||||
"types": ["node", "@wdio/globals/types", "expect-webdriverio", "@wdio/mocha-framework", "@types/mocha"],
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
|
@ -41,6 +41,7 @@ const definitions = {
|
||||
|
||||
const otherFiles = [
|
||||
["node_modules/@patternfly/patternfly/patternfly.min.css", "."],
|
||||
["node_modules/@patternfly/patternfly/patternfly-base.css", "."],
|
||||
["node_modules/@patternfly/patternfly/assets/**", ".", "node_modules/@patternfly/patternfly/"],
|
||||
["src/custom.css", "."],
|
||||
["src/common/styles/**", "."],
|
||||
@ -79,6 +80,12 @@ const interfaces = [
|
||||
["polyfill/poly.ts", "."],
|
||||
];
|
||||
|
||||
const extraTargets = [
|
||||
["sdk/index.ts", "sdk", { entryNames: "[dir]/[name]" }],
|
||||
["sdk/user-settings.ts", "sdk/user-settings", { entryNames: "[dir]/[name]" }],
|
||||
["sdk/flow.ts", "sdk/flow", { entryNames: "[dir]/[name]" }],
|
||||
];
|
||||
|
||||
const baseArgs = {
|
||||
bundle: true,
|
||||
write: true,
|
||||
@ -101,7 +108,11 @@ function getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
async function buildOneSource(source, dest) {
|
||||
function getAllTargets() {
|
||||
return [...interfaces, ...extraTargets];
|
||||
}
|
||||
|
||||
async function buildSingleTarget(source, dest, options) {
|
||||
const DIST = path.join(__dirname, "./dist", dest);
|
||||
console.log(`[${new Date(Date.now()).toISOString()}] Starting build for target ${source}`);
|
||||
|
||||
@ -112,6 +123,7 @@ async function buildOneSource(source, dest) {
|
||||
entryPoints: [`./src/${source}`],
|
||||
entryNames: `[dir]/[name]-${getVersion()}`,
|
||||
outdir: DIST,
|
||||
...options,
|
||||
});
|
||||
const end = Date.now();
|
||||
console.log(
|
||||
@ -124,8 +136,10 @@ async function buildOneSource(source, dest) {
|
||||
}
|
||||
}
|
||||
|
||||
async function buildAuthentik(interfaces) {
|
||||
await Promise.allSettled(interfaces.map(([source, dest]) => buildOneSource(source, dest)));
|
||||
async function buildTargets(targets) {
|
||||
await Promise.allSettled(
|
||||
targets.map(([source, dest, options]) => buildSingleTarget(source, dest, options)),
|
||||
);
|
||||
}
|
||||
|
||||
let timeoutId = null;
|
||||
@ -135,7 +149,7 @@ function debouncedBuild() {
|
||||
}
|
||||
timeoutId = setTimeout(() => {
|
||||
console.clear();
|
||||
buildAuthentik(interfaces);
|
||||
buildTargets(getAllTargets());
|
||||
}, 250);
|
||||
}
|
||||
|
||||
@ -143,7 +157,7 @@ if (process.argv.length > 2 && (process.argv[2] === "-h" || process.argv[2] ===
|
||||
console.log(`Build the authentikUI
|
||||
|
||||
options:
|
||||
-w, --watch: Build all ${interfaces.length} interfaces
|
||||
-w, --watch: Build all ${getAllTargets().length} interfaces
|
||||
-p, --proxy: Build only the polyfills and the loading application
|
||||
-h, --help: This help message
|
||||
`);
|
||||
@ -163,11 +177,11 @@ if (process.argv.length > 2 && (process.argv[2] === "-w" || process.argv[2] ===
|
||||
});
|
||||
} else if (process.argv.length > 2 && (process.argv[2] === "-p" || process.argv[2] === "--proxy")) {
|
||||
// There's no watch-for-proxy, sorry.
|
||||
await buildAuthentik(
|
||||
await buildTargets(
|
||||
interfaces.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)),
|
||||
);
|
||||
process.exit(0);
|
||||
} else {
|
||||
// And the fallback: just build it.
|
||||
await buildAuthentik(interfaces);
|
||||
await buildTargets(interfaces);
|
||||
}
|
||||
|
994
web/package-lock.json
generated
994
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,15 +11,15 @@
|
||||
"@floating-ui/dom": "^1.6.9",
|
||||
"@formatjs/intl-listformat": "^7.5.7",
|
||||
"@fortawesome/fontawesome-free": "^6.6.0",
|
||||
"@goauthentik/api": "^2024.6.3-1724414734",
|
||||
"@goauthentik/api": "^2024.8.0-1725367323",
|
||||
"@lit/context": "^1.1.2",
|
||||
"@lit/localize": "^0.12.2",
|
||||
"@lit/reactive-element": "^2.0.4",
|
||||
"@lit/task": "^1.0.1",
|
||||
"@open-wc/lit-helpers": "^0.7.0",
|
||||
"@patternfly/elements": "^4.0.0",
|
||||
"@patternfly/elements": "^4.0.1",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@sentry/browser": "^8.26.0",
|
||||
"@sentry/browser": "^8.27.0",
|
||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"chart.js": "^4.4.4",
|
||||
@ -32,7 +32,7 @@
|
||||
"guacamole-common-js": "^1.5.0",
|
||||
"lit": "^3.2.0",
|
||||
"md-front-matter": "^1.0.4",
|
||||
"mermaid": "^11.0.2",
|
||||
"mermaid": "^11.1.0",
|
||||
"rapidoc": "^9.3.4",
|
||||
"showdown": "^2.1.0",
|
||||
"style-mod": "^4.1.2",
|
||||
@ -57,7 +57,7 @@
|
||||
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
|
||||
"@lit/localize-tools": "^0.8.0",
|
||||
"@rollup/plugin-replace": "^5.0.7",
|
||||
"@spotlightjs/spotlight": "^2.3.0",
|
||||
"@spotlightjs/spotlight": "^2.3.2",
|
||||
"@storybook/addon-essentials": "^8.2.9",
|
||||
"@storybook/addon-links": "^8.2.9",
|
||||
"@storybook/api": "^7.6.17",
|
||||
@ -71,6 +71,7 @@
|
||||
"@types/eslint__js": "^8.42.3",
|
||||
"@types/grecaptcha": "^3.0.9",
|
||||
"@types/guacamole-common-js": "1.5.2",
|
||||
"@types/node": "^22.5.0",
|
||||
"@types/showdown": "^2.0.6",
|
||||
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
||||
"@typescript-eslint/parser": "^8.0.1",
|
||||
@ -90,6 +91,7 @@
|
||||
"github-slugger": "^2.0.0",
|
||||
"glob": "^11.0.0",
|
||||
"globals": "^15.9.0",
|
||||
"knip": "^5.27.4",
|
||||
"lit-analyzer": "^2.0.3",
|
||||
"lockfile-lint": "^4.14.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
@ -107,7 +109,7 @@
|
||||
"tslib": "^2.7.0",
|
||||
"turnstile-types": "^1.2.2",
|
||||
"typescript": "^5.5.4",
|
||||
"typescript-eslint": "^8.2.0",
|
||||
"typescript-eslint": "^8.4.0",
|
||||
"vite-tsconfig-paths": "^5.0.1",
|
||||
"wdio-wait-for": "^3.0.11",
|
||||
"wireit": "^0.14.8"
|
||||
@ -120,9 +122,9 @@
|
||||
"@esbuild/darwin-arm64": "^0.23.0",
|
||||
"@esbuild/linux-amd64": "^0.18.11",
|
||||
"@esbuild/linux-arm64": "^0.23.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.21.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.21.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.21.0"
|
||||
"@rollup/rollup-darwin-arm64": "4.21.2",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.21.2",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.21.2"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@ -135,6 +137,7 @@
|
||||
"extract-locales": "wireit",
|
||||
"format": "wireit",
|
||||
"lint": "wireit",
|
||||
"lint:imports": "wireit",
|
||||
"lint:lockfile": "wireit",
|
||||
"lint:nightmare": "wireit",
|
||||
"lint:package": "wireit",
|
||||
@ -149,8 +152,7 @@
|
||||
"storybook:build": "wireit",
|
||||
"storybook:build-import-map": "wireit",
|
||||
"test": "wireit",
|
||||
"test-view": "wireit",
|
||||
"test-watch": "npx wdio run ./wdio.conf.ts --autoCompileOpts.tsNodeOpts.project=tsconfig.test.json --watch",
|
||||
"test-watch": "wireit",
|
||||
"tsc": "wireit",
|
||||
"watch": "run-s build-locales esbuild:watch"
|
||||
},
|
||||
@ -250,6 +252,9 @@
|
||||
"lint:components": {
|
||||
"command": "lit-analyzer src"
|
||||
},
|
||||
"lint:imports": {
|
||||
"command": "knip --config scripts/knip.config.ts"
|
||||
},
|
||||
"lint:types": {
|
||||
"command": "tsc --noEmit -p .",
|
||||
"dependencies": [
|
||||
@ -330,7 +335,7 @@
|
||||
"TS_NODE_PROJECT": "tsconfig.test.json"
|
||||
}
|
||||
},
|
||||
"test-view": {
|
||||
"test-watch": {
|
||||
"command": "wdio run ./wdio.conf.ts",
|
||||
"env": {
|
||||
"TS_NODE_PROJECT": "tsconfig.test.json"
|
||||
|
@ -14,18 +14,18 @@
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-swc": "^0.3.1",
|
||||
"@swc/cli": "^0.4.0",
|
||||
"@swc/core": "^1.7.18",
|
||||
"@swc/core": "^1.7.23",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/jquery": "^3.5.30",
|
||||
"lockfile-lint": "^4.14.0",
|
||||
"prettier": "^3.3.2",
|
||||
"rollup": "^4.21.0",
|
||||
"rollup": "^4.21.2",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"wireit": "^0.14.8"
|
||||
},
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"@swc/core": "^1.7.18",
|
||||
"@swc/core": "^1.7.23",
|
||||
"@swc/core-darwin-arm64": "^1.6.13",
|
||||
"@swc/core-darwin-x64": "^1.6.13",
|
||||
"@swc/core-linux-arm-gnueabihf": "^1.6.13",
|
||||
|
48
web/scripts/knip.config.ts
Normal file
48
web/scripts/knip.config.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { type KnipConfig } from "knip";
|
||||
|
||||
const config: KnipConfig = {
|
||||
"entry": [
|
||||
"./src/admin/AdminInterface/AdminInterface.ts",
|
||||
"./src/user/UserInterface.ts",
|
||||
"./src/flow/FlowInterface.ts",
|
||||
"./src/standalone/api-browser/index.ts",
|
||||
"./src/enterprise/rac/index.ts",
|
||||
"./src/standalone/loading/index.ts",
|
||||
"./src/polyfill/poly.ts",
|
||||
],
|
||||
"project": ["src/**/*.ts", "src/**/*.js", "./scripts/*.mjs", ".storybook/*.ts"],
|
||||
// "ignore": ["src/**/*.test.ts", "src/**/*.stories.ts"],
|
||||
// Prevent Knip from complaining about web components, which export their classes but also
|
||||
// export their registration, and we don't always use both.
|
||||
"ignoreExportsUsedInFile": true,
|
||||
"typescript": {
|
||||
config: ["tsconfig.json"],
|
||||
},
|
||||
"wireit": {
|
||||
config: ["package.json"],
|
||||
},
|
||||
"storybook": {
|
||||
config: [".storybook/{main,test-runner}.{js,ts}"],
|
||||
entry: [
|
||||
".storybook/{manager,preview}.{js,jsx,ts,tsx}",
|
||||
"**/*.@(mdx|stories.@(mdx|js|jsx|mjs|ts|tsx))",
|
||||
],
|
||||
project: [".storybook/**/*.{js,jsx,ts,tsx}"],
|
||||
},
|
||||
"eslint": {
|
||||
entry: [
|
||||
"eslint.config.mjs",
|
||||
"scripts/eslint.precommit.mjs",
|
||||
"scripts/eslint.nightmare.mjs",
|
||||
"scripts/eslint-precommit.mjs",
|
||||
"scripts/eslint-nightmare.mjs",
|
||||
"scripts/eslint.mjs",
|
||||
],
|
||||
config: ["package.json"],
|
||||
},
|
||||
"webdriver-io": {
|
||||
config: ["wdio.conf.js"],
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
3057
web/sfe/package-lock.json
generated
3057
web/sfe/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,28 +0,0 @@
|
||||
{
|
||||
"name": "@goauthentik/web-sfe",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@goauthentik/api": "^2024.6.3-1724414734",
|
||||
"base64-js": "^1.5.1",
|
||||
"bootstrap": "^4.6.1",
|
||||
"formdata-polyfill": "^4.0.10",
|
||||
"jquery": "^3.7.1",
|
||||
"weakmap-polyfill": "^2.0.4"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup -c rollup.config.js --bundleConfigAsCjs",
|
||||
"watch": "rollup -w -c rollup.config.js --bundleConfigAsCjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^26.0.1",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-swc": "^0.3.1",
|
||||
"@swc/cli": "^0.4.0",
|
||||
"@swc/core": "^1.7.18",
|
||||
"@types/jquery": "^3.5.30",
|
||||
"rollup": "^4.21.0",
|
||||
"rollup-plugin-copy": "^3.5.0"
|
||||
}
|
||||
}
|
@ -21,10 +21,20 @@ export class ApplicationWizardAuthenticationMethodChoice extends WithLicenseSumm
|
||||
const selectedTypes = providerModelsList.filter(
|
||||
(t) => t.formName === this.wizard.providerModel,
|
||||
);
|
||||
|
||||
// As a hack, the Application wizard has separate provider paths for our three types of
|
||||
// proxy providers. This patch swaps the form we want to be directed to on page 3 from the
|
||||
// modelName to the formName, so we get the right one. This information isn't modified
|
||||
// or forwarded, so the proxy-plus-subtype is correctly mapped on submission.
|
||||
const typesForWizard = providerModelsList.map((provider) => ({
|
||||
...provider,
|
||||
modelName: provider.formName,
|
||||
}));
|
||||
|
||||
return providerModelsList.length > 0
|
||||
? html`<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-wizard-page-type-create
|
||||
.types=${providerModelsList}
|
||||
.types=${typesForWizard}
|
||||
layout=${TypeCreateWizardPageLayouts.grid}
|
||||
.selectedType=${selectedTypes.length > 0 ? selectedTypes[0] : undefined}
|
||||
@select=${(ev: CustomEvent<LocalTypeCreate>) => {
|
||||
|
@ -265,7 +265,7 @@ export class ApplicationWizardAuthenticationByOauth extends BaseProviderPanel {
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selected=${provider?.jwksSources}
|
||||
.selected=${provider?.jwksSources ?? []}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-provider>
|
||||
|
@ -230,7 +230,7 @@ export class AkTypeProxyApplicationWizardPage extends BaseProviderPanel {
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selected=${this.instance?.jwksSources}
|
||||
.selected=${this.instance?.jwksSources ?? []}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-provider>
|
||||
|
@ -97,7 +97,8 @@ export class OutpostForm extends ModelForm<Outpost, string> {
|
||||
embedded = false;
|
||||
|
||||
@state()
|
||||
providers?: DataProvider;
|
||||
providers: DataProvider = providerProvider(this.type);
|
||||
|
||||
defaultConfig?: OutpostDefaultConfig;
|
||||
|
||||
async loadInstance(pk: string): Promise<Outpost> {
|
||||
@ -113,6 +114,7 @@ export class OutpostForm extends ModelForm<Outpost, string> {
|
||||
this.defaultConfig = await new OutpostsApi(
|
||||
DEFAULT_CONFIG,
|
||||
).outpostsInstancesDefaultSettingsRetrieve();
|
||||
this.providers = providerProvider(this.type);
|
||||
}
|
||||
|
||||
getSuccessMessage(): string {
|
||||
|
@ -117,7 +117,7 @@ export class EventMatcherPolicyForm extends BasePolicyForm<EventMatcherPolicy> {
|
||||
/>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"Matches Event's Client IP (strict matching, for network matching use an Expression Policy.",
|
||||
"Matches Event's Client IP (strict matching, for network matching use an Expression Policy).",
|
||||
)}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
|
@ -7,6 +7,9 @@ export function renderSourceIcon(name: string, iconUrl: string | undefined | nul
|
||||
const url = iconUrl.replaceAll("fa://", "");
|
||||
return html`<i class="fas ${url}" title="${name}"></i>`;
|
||||
}
|
||||
if (window.authentik_sdk?.base) {
|
||||
return html`<img src="${window.authentik_sdk?.base}${iconUrl}" alt="${name}" />`;
|
||||
}
|
||||
return html`<img src="${iconUrl}" alt="${name}" />`;
|
||||
}
|
||||
return icon;
|
||||
|
@ -46,7 +46,8 @@ async function makeSourcesSelector(instanceSources: string[] | undefined) {
|
||||
|
||||
return localSources
|
||||
? ([pk, _]: DualSelectPair) => localSources.has(pk)
|
||||
: ([_0, _1, _2, source]: DualSelectPair<Source>) =>
|
||||
: // Creating a new instance, auto-select built-in source only when no other sources exist
|
||||
([_0, _1, _2, source]: DualSelectPair<Source>) =>
|
||||
source !== undefined && source.component === "";
|
||||
}
|
||||
|
||||
@ -75,11 +76,11 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
|
||||
stageUuid: this.instance.pk || "",
|
||||
identificationStageRequest: data,
|
||||
});
|
||||
} else {
|
||||
return new StagesApi(DEFAULT_CONFIG).stagesIdentificationCreate({
|
||||
identificationStageRequest: data,
|
||||
});
|
||||
}
|
||||
|
||||
return new StagesApi(DEFAULT_CONFIG).stagesIdentificationCreate({
|
||||
identificationStageRequest: data,
|
||||
});
|
||||
}
|
||||
|
||||
isUserFieldSelected(field: UserFieldsEnum): boolean {
|
||||
@ -232,12 +233,12 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
|
||||
?required=${true}
|
||||
name="sources"
|
||||
>
|
||||
<ak-dual-select-provider-dynamic-selected
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${sourcesProvider}
|
||||
.selected=${makeSourcesSelector(this.instance?.sources)}
|
||||
.selector=${makeSourcesSelector(this.instance?.sources)}
|
||||
available-label="${msg("Available Stages")}"
|
||||
selected-label="${msg("Selected Stages")}"
|
||||
></ak-dual-select-provider-dynamic-selected>
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"Select sources should be shown for users to authenticate with. This only affects web-based sources, not LDAP.",
|
||||
|
@ -2,6 +2,7 @@ import {
|
||||
CSRFMiddleware,
|
||||
EventMiddleware,
|
||||
LoggingMiddleware,
|
||||
SDKMiddleware,
|
||||
} from "@goauthentik/common/api/middleware";
|
||||
import { EVENT_LOCALE_REQUEST, VERSION } from "@goauthentik/common/constants";
|
||||
import { globalAK } from "@goauthentik/common/global";
|
||||
@ -67,8 +68,18 @@ export function getMetaContent(key: string): string {
|
||||
return metaEl.content;
|
||||
}
|
||||
|
||||
export function apiBase(): string {
|
||||
if (process.env.AK_API_BASE_PATH) {
|
||||
return process.env.AK_API_BASE_PATH;
|
||||
}
|
||||
if (window.authentik_sdk?.base) {
|
||||
return window.authentik_sdk?.base;
|
||||
}
|
||||
return window.location.origin;
|
||||
}
|
||||
|
||||
export const DEFAULT_CONFIG = new Configuration({
|
||||
basePath: (process.env.AK_API_BASE_PATH || window.location.origin) + "/api/v3",
|
||||
basePath: `${apiBase()}/api/v3`,
|
||||
headers: {
|
||||
"sentry-trace": getMetaContent("sentry-trace"),
|
||||
},
|
||||
@ -76,6 +87,7 @@ export const DEFAULT_CONFIG = new Configuration({
|
||||
new CSRFMiddleware(),
|
||||
new EventMiddleware(),
|
||||
new LoggingMiddleware(globalAK().brand),
|
||||
new SDKMiddleware(),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -44,6 +44,21 @@ export class CSRFMiddleware implements Middleware {
|
||||
}
|
||||
}
|
||||
|
||||
export class SDKMiddleware implements Middleware {
|
||||
token?: string;
|
||||
constructor() {
|
||||
this.token = window.authentik_sdk?.token;
|
||||
}
|
||||
pre?(context: RequestContext): Promise<FetchParams | void> {
|
||||
if (this.token) {
|
||||
context.init.credentials = "include";
|
||||
// @ts-ignore
|
||||
context.init.headers["Authorization"] = `Bearer ${this.token}`;
|
||||
}
|
||||
return Promise.resolve(context);
|
||||
}
|
||||
}
|
||||
|
||||
export class EventMiddleware implements Middleware {
|
||||
post?(context: ResponseContext): Promise<Response | void> {
|
||||
const request: RequestInfo = {
|
||||
|
@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
|
||||
export const ERROR_CLASS = "pf-m-danger";
|
||||
export const PROGRESS_CLASS = "pf-m-in-progress";
|
||||
export const CURRENT_CLASS = "pf-m-current";
|
||||
export const VERSION = "2024.6.4";
|
||||
export const VERSION = "2024.8.0";
|
||||
export const TITLE_DEFAULT = "authentik";
|
||||
export const ROUTE_SEPARATOR = ";";
|
||||
|
||||
|
@ -1,4 +1,11 @@
|
||||
import { Config, ConfigFromJSON, CurrentBrand, CurrentBrandFromJSON } from "@goauthentik/api";
|
||||
import {
|
||||
Config,
|
||||
ConfigFromJSON,
|
||||
CurrentBrand,
|
||||
CurrentBrandFromJSON,
|
||||
ErrorReportingConfigFromJSON,
|
||||
UiThemeEnum,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
export interface GlobalAuthentik {
|
||||
_converted?: boolean;
|
||||
@ -28,9 +35,12 @@ export function globalAK(): GlobalAuthentik {
|
||||
return {
|
||||
config: ConfigFromJSON({
|
||||
capabilities: [],
|
||||
error_reporting: ErrorReportingConfigFromJSON({}),
|
||||
}),
|
||||
brand: CurrentBrandFromJSON({
|
||||
matched_domain: window.location.host,
|
||||
ui_footer_links: [],
|
||||
ui_theme: window.authentik_sdk?.forceTheme ?? UiThemeEnum.Automatic,
|
||||
}),
|
||||
versionFamily: "",
|
||||
versionSubdomain: "",
|
||||
@ -40,6 +50,10 @@ export function globalAK(): GlobalAuthentik {
|
||||
return ak;
|
||||
}
|
||||
|
||||
export function isEmbedded() {
|
||||
return !!window.authentik_sdk;
|
||||
}
|
||||
|
||||
export function docLink(path: string): string {
|
||||
const ak = globalAK();
|
||||
// Default case or beta build which should always point to latest
|
||||
|
@ -21,9 +21,12 @@ export class WebsocketClient {
|
||||
|
||||
connect(): void {
|
||||
if (navigator.webdriver) return;
|
||||
const wsUrl = `${window.location.protocol.replace("http", "ws")}//${
|
||||
let wsUrl = `${window.location.protocol.replace("http", "ws")}//${
|
||||
window.location.host
|
||||
}/ws/client/`;
|
||||
if (window.authentik_sdk?.base) {
|
||||
wsUrl = `${window.authentik_sdk?.base.replace("http", "ws")}/ws/client/`;
|
||||
}
|
||||
this.messageSocket = new WebSocket(wsUrl);
|
||||
this.messageSocket.addEventListener("open", () => {
|
||||
console.debug(`authentik/ws: connected to ${wsUrl}`);
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { isEmbedded } from "@goauthentik/common/global";
|
||||
import { UIConfig, uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { ModalOrchestrationController } from "@goauthentik/elements/controllers/ModalOrchestrationController.js";
|
||||
import { ensureCSSStyleSheet } from "@goauthentik/elements/utils/ensureCSSStyleSheet";
|
||||
|
||||
import { state } from "lit/decorators.js";
|
||||
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import PFVariables from "@patternfly/patternfly/base/patternfly-variables.css";
|
||||
|
||||
import type { Config, CurrentBrand, LicenseSummary } from "@goauthentik/api";
|
||||
import { UiThemeEnum } from "@goauthentik/api";
|
||||
@ -43,7 +44,10 @@ export class Interface extends AKElement implements AkInterface {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
document.adoptedStyleSheets = [...document.adoptedStyleSheets, ensureCSSStyleSheet(PFBase)];
|
||||
document.adoptedStyleSheets = [
|
||||
...document.adoptedStyleSheets,
|
||||
ensureCSSStyleSheet(PFVariables),
|
||||
];
|
||||
this[brandContext] = new BrandContextController(this);
|
||||
this[configContext] = new ConfigContextController(this);
|
||||
this[modalController] = new ModalOrchestrationController(this);
|
||||
@ -61,7 +65,9 @@ export class Interface extends AKElement implements AkInterface {
|
||||
// Instead of calling ._activateTheme() twice, we insert the root document in the call
|
||||
// since multiple calls to ._activateTheme() would not do anything after the first call
|
||||
// as the theme is already enabled.
|
||||
roots.unshift(document as unknown as DocumentOrShadowRoot);
|
||||
if (!isEmbedded()) {
|
||||
roots.unshift(document as unknown as DocumentOrShadowRoot);
|
||||
}
|
||||
super._activateTheme(theme, ...roots);
|
||||
}
|
||||
|
||||
|
@ -50,3 +50,9 @@ export class AkDualSelectDynamic extends AkDualSelectProvider {
|
||||
></ak-dual-select>`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-dual-select-dynamic-selected": AkDualSelectDynamic;
|
||||
}
|
||||
}
|
||||
|
@ -69,9 +69,19 @@ export class TypeCreateWizardPage extends WithLicenseSummary(WizardPage) {
|
||||
}
|
||||
|
||||
renderGrid(): TemplateResult {
|
||||
return html`<div class="pf-l-grid pf-m-gutter">
|
||||
return html`<div
|
||||
class="pf-l-grid pf-m-gutter"
|
||||
data-ouid-component-type="ak-type-create-grid"
|
||||
>
|
||||
${this.types.map((type, idx) => {
|
||||
const requiresEnterprise = type.requiresEnterprise && !this.hasEnterpriseLicense;
|
||||
|
||||
// It's valid to pass in a local modelName or the full name with application
|
||||
// part. If the latter, we only want the part after the dot to appear as our
|
||||
// OUIA tag for test automation.
|
||||
const componentName = type.modelName.includes(".")
|
||||
? (type.modelName.split(".")[1] ?? "--unknown--")
|
||||
: type.modelName;
|
||||
return html`<div
|
||||
class="pf-l-grid__item pf-m-3-col pf-c-card ${requiresEnterprise
|
||||
? "pf-m-non-selectable-raised"
|
||||
@ -79,6 +89,8 @@ export class TypeCreateWizardPage extends WithLicenseSummary(WizardPage) {
|
||||
? "pf-m-selected-raised"
|
||||
: ""}"
|
||||
tabindex=${idx}
|
||||
data-ouid-component-type="ak-type-create-grid-card"
|
||||
data-ouid-component-name=${componentName}
|
||||
@click=${() => {
|
||||
if (requiresEnterprise) {
|
||||
return;
|
||||
@ -107,10 +119,17 @@ export class TypeCreateWizardPage extends WithLicenseSummary(WizardPage) {
|
||||
}
|
||||
|
||||
renderList(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
return html`<form
|
||||
class="pf-c-form pf-m-horizontal"
|
||||
data-ouid-component-type="ak-type-create-list"
|
||||
>
|
||||
${this.types.map((type) => {
|
||||
const requiresEnterprise = type.requiresEnterprise && !this.hasEnterpriseLicense;
|
||||
return html`<div class="pf-c-radio">
|
||||
return html`<div
|
||||
class="pf-c-radio"
|
||||
data-ouid-component-type="ak-type-create-list-card"
|
||||
data-ouid-component-name=${type.modelName.split(".")[1] ?? "--unknown--"}
|
||||
>
|
||||
<input
|
||||
class="pf-c-radio__input"
|
||||
type="radio"
|
||||
|
@ -4,7 +4,7 @@ import {
|
||||
EVENT_FLOW_INSPECTOR_TOGGLE,
|
||||
TITLE_DEFAULT,
|
||||
} from "@goauthentik/common/constants";
|
||||
import { globalAK } from "@goauthentik/common/global";
|
||||
import { globalAK, isEmbedded } from "@goauthentik/common/global";
|
||||
import { configureSentry } from "@goauthentik/common/sentry";
|
||||
import { first } from "@goauthentik/common/utils";
|
||||
import { WebsocketClient } from "@goauthentik/common/ws";
|
||||
@ -84,6 +84,7 @@ export class FlowExecutor extends Interface implements StageHost {
|
||||
return [PFBase, PFLogin, PFDrawer, PFButton, PFTitle, PFList, PFBackgroundImage].concat(css`
|
||||
:host {
|
||||
--pf-c-login__main-body--PaddingBottom: var(--pf-global--spacer--2xl);
|
||||
position: relative;
|
||||
}
|
||||
.pf-c-background-image::before {
|
||||
--pf-c-background-image--BackgroundImage: var(--ak-flow-background);
|
||||
@ -95,9 +96,6 @@ export class FlowExecutor extends Interface implements StageHost {
|
||||
.ak-hidden {
|
||||
display: none;
|
||||
}
|
||||
:host {
|
||||
position: relative;
|
||||
}
|
||||
.pf-c-drawer__content {
|
||||
background-color: transparent;
|
||||
}
|
||||
@ -262,10 +260,13 @@ export class FlowExecutor extends Interface implements StageHost {
|
||||
this.challenge = challenge as ChallengeTypes;
|
||||
}
|
||||
|
||||
setShadowStyles(value: ContextualFlowInfo) {
|
||||
setBackgroundImage(value: ContextualFlowInfo) {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
if (isEmbedded()) {
|
||||
return;
|
||||
}
|
||||
this.shadowRoot
|
||||
?.querySelectorAll<HTMLDivElement>(".pf-c-background-image")
|
||||
.forEach((bg) => {
|
||||
@ -276,7 +277,7 @@ export class FlowExecutor extends Interface implements StageHost {
|
||||
// DOM post-processing has to happen after the render.
|
||||
updated(changedProperties: PropertyValues<this>) {
|
||||
if (changedProperties.has("flowInfo") && this.flowInfo !== undefined) {
|
||||
this.setShadowStyles(this.flowInfo);
|
||||
this.setBackgroundImage(this.flowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,56 +460,63 @@ export class FlowExecutor extends Interface implements StageHost {
|
||||
}
|
||||
}
|
||||
|
||||
renderCard() {
|
||||
return html`<div class="pf-c-login ${this.getLayout()}">
|
||||
<div class="${this.getLayoutClass()}">
|
||||
<div class="pf-c-login__main">
|
||||
${this.loading && this.challenge
|
||||
? html`<ak-loading-overlay></ak-loading-overlay>`
|
||||
: nothing}
|
||||
${isEmbedded()
|
||||
? nothing
|
||||
: html` <div class="pf-c-login__main-header pf-c-brand ak-brand">
|
||||
<img
|
||||
src="${themeImage(
|
||||
first(
|
||||
this.brand?.brandingLogo,
|
||||
globalAK()?.brand.brandingLogo,
|
||||
DefaultBrand.brandingLogo,
|
||||
),
|
||||
)}"
|
||||
alt="authentik Logo"
|
||||
/>
|
||||
</div>`}
|
||||
${until(this.renderChallenge())}
|
||||
</div>
|
||||
${isEmbedded()
|
||||
? nothing
|
||||
: html` <footer class="pf-c-login__footer">
|
||||
<ul class="pf-c-list pf-m-inline">
|
||||
${this.brand?.uiFooterLinks?.map((link) => {
|
||||
if (link.href) {
|
||||
return html`<li>
|
||||
<a href="${link.href}">${link.name}</a>
|
||||
</li>`;
|
||||
}
|
||||
return html`<li>
|
||||
<span>${link.name}</span>
|
||||
</li>`;
|
||||
})}
|
||||
<li>
|
||||
<span>${msg("Powered by authentik")}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>`}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
if (isEmbedded()) {
|
||||
return this.renderCard();
|
||||
}
|
||||
return html` <ak-locale-context>
|
||||
<div class="pf-c-background-image"></div>
|
||||
<div class="pf-c-page__drawer">
|
||||
<div class="pf-c-drawer ${this.inspectorOpen ? "pf-m-expanded" : "pf-m-collapsed"}">
|
||||
<div class="pf-c-drawer__main">
|
||||
<div class="pf-c-drawer__content">
|
||||
<div class="pf-c-drawer__body">
|
||||
<div class="pf-c-login ${this.getLayout()}">
|
||||
<div class="${this.getLayoutClass()}">
|
||||
<div class="pf-c-login__main">
|
||||
${this.loading && this.challenge
|
||||
? html`<ak-loading-overlay></ak-loading-overlay>`
|
||||
: nothing}
|
||||
<div
|
||||
class="pf-c-login__main-header pf-c-brand ak-brand"
|
||||
>
|
||||
<img
|
||||
src="${themeImage(
|
||||
first(
|
||||
this.brand?.brandingLogo,
|
||||
globalAK()?.brand.brandingLogo,
|
||||
DefaultBrand.brandingLogo,
|
||||
),
|
||||
)}"
|
||||
alt="authentik Logo"
|
||||
/>
|
||||
</div>
|
||||
${until(this.renderChallenge())}
|
||||
</div>
|
||||
<footer class="pf-c-login__footer">
|
||||
<ul class="pf-c-list pf-m-inline">
|
||||
${this.brand?.uiFooterLinks?.map((link) => {
|
||||
if (link.href) {
|
||||
return html`<li>
|
||||
<a href="${link.href}">${link.name}</a>
|
||||
</li>`;
|
||||
}
|
||||
return html`<li>
|
||||
<span>${link.name}</span>
|
||||
</li>`;
|
||||
})}
|
||||
<li>
|
||||
<span>${msg("Powered by authentik")}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-drawer__body">${this.renderCard()}</div>
|
||||
</div>
|
||||
${until(this.renderInspector())}
|
||||
</div>
|
||||
|
@ -99,6 +99,7 @@ export class IdentificationStage extends BaseStage<
|
||||
createHelperForm(): void {
|
||||
const compatMode = "ShadyDOM" in window;
|
||||
this.form = document.createElement("form");
|
||||
this.form.style.display = "none";
|
||||
document.documentElement.appendChild(this.form);
|
||||
// Only add the additional username input if we're in a shadow dom
|
||||
// otherwise it just confuses browsers
|
||||
|
8
web/src/global.d.ts
vendored
8
web/src/global.d.ts
vendored
@ -12,3 +12,11 @@ declare namespace Intl {
|
||||
public format: (items: string[]) => string;
|
||||
}
|
||||
}
|
||||
|
||||
declare interface Window {
|
||||
authentik_sdk?: {
|
||||
base: string;
|
||||
token?: string;
|
||||
forceTheme?: string;
|
||||
};
|
||||
}
|
||||
|
19
web/src/sdk/common.ts
Normal file
19
web/src/sdk/common.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Interface } from "@goauthentik/elements/Interface/Interface";
|
||||
|
||||
import { html } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
|
||||
import { UiThemeEnum, UiThemeEnumFromJSON } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-sdk-interface")
|
||||
export class SDKInterface extends Interface {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
async getTheme(): Promise<UiThemeEnum> {
|
||||
return UiThemeEnumFromJSON(window.authentik_sdk?.forceTheme) || UiThemeEnum.Automatic;
|
||||
}
|
||||
}
|
34
web/src/sdk/flow.ts
Normal file
34
web/src/sdk/flow.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import "@goauthentik/elements/messages/MessageContainer";
|
||||
import { FlowExecutor } from "@goauthentik/flow/FlowExecutor";
|
||||
// Statically import some stages to speed up load speed
|
||||
import "@goauthentik/flow/stages/access_denied/AccessDeniedStage";
|
||||
// Import webauthn-related stages to prevent issues on safari
|
||||
// Which is overly sensitive to allowing things only in the context of a
|
||||
// user interaction
|
||||
import "@goauthentik/flow/stages/authenticator_validate/AuthenticatorValidateStage";
|
||||
import "@goauthentik/flow/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage";
|
||||
import "@goauthentik/flow/stages/autosubmit/AutosubmitStage";
|
||||
import "@goauthentik/flow/stages/captcha/CaptchaStage";
|
||||
import "@goauthentik/flow/stages/identification/IdentificationStage";
|
||||
import "@goauthentik/flow/stages/password/PasswordStage";
|
||||
import "@goauthentik/sdk/common";
|
||||
// end of stage import
|
||||
|
||||
import { html, nothing } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
import { until } from "lit/directives/until.js";
|
||||
|
||||
|
||||
@customElement("ak-embedded-flow-executor")
|
||||
export class EmbeddedFlowExecutor extends FlowExecutor {
|
||||
renderCard() {
|
||||
return html`<div class="pf-c-login">
|
||||
<div class="pf-c-login__main">
|
||||
${this.loading && this.challenge
|
||||
? html`<ak-loading-overlay></ak-loading-overlay>`
|
||||
: nothing}
|
||||
${until(this.renderChallenge())}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
}
|
2
web/src/sdk/index.ts
Normal file
2
web/src/sdk/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
import "@goauthentik/sdk/flow";
|
||||
import "@goauthentik/sdk/user-settings";
|
3
web/src/sdk/user-settings.ts
Normal file
3
web/src/sdk/user-settings.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import "@goauthentik/elements/messages/MessageContainer";
|
||||
import "@goauthentik/sdk/common";
|
||||
import "@goauthentik/user/user-settings/UserSettingsPage";
|
@ -21,6 +21,7 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import {
|
||||
ChallengeTypes,
|
||||
CoreApi,
|
||||
FlowChallengeResponseRequest,
|
||||
FlowErrorChallenge,
|
||||
FlowsApi,
|
||||
@ -82,8 +83,11 @@ export class UserSettingsFlowExecutor
|
||||
});
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
this.flowSlug = this.brand?.flowUserSettings;
|
||||
async firstUpdated(): Promise<void> {
|
||||
if (!this.brand) {
|
||||
this.brand = await new CoreApi(DEFAULT_CONFIG).coreBrandsCurrentRetrieve();
|
||||
}
|
||||
this.flowSlug = this.brand.flowUserSettings;
|
||||
if (!this.flowSlug) {
|
||||
return;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
"@goauthentik/flow/*": ["./src/flow/*"],
|
||||
"@goauthentik/locales/*": ["./src/locales/*"],
|
||||
"@goauthentik/polyfill/*": ["./src/polyfill/*"],
|
||||
"@goauthentik/sdk/*": ["./src/sdk/*"],
|
||||
"@goauthentik/standalone/*": ["./src/standalone/*"],
|
||||
"@goauthentik/user/*": ["./src/user/*"]
|
||||
}
|
||||
|
@ -8,6 +8,12 @@ import tsconfigPaths from "vite-tsconfig-paths";
|
||||
const isProdBuild = process.env.NODE_ENV === "production";
|
||||
const apiBasePath = process.env.AK_API_BASE_PATH || "";
|
||||
const runHeadless = process.env.CI !== undefined;
|
||||
const maxInstances =
|
||||
process.env.MAX_INSTANCES !== undefined
|
||||
? parseInt(process.env.MAX_INSTANCES, 10)
|
||||
: runHeadless
|
||||
? 10
|
||||
: 1;
|
||||
|
||||
export const config: Options.Testrunner = {
|
||||
//
|
||||
@ -81,7 +87,7 @@ export const config: Options.Testrunner = {
|
||||
// and 30 processes will get spawned. The property handles how many capabilities
|
||||
// from the same test should run tests.
|
||||
//
|
||||
maxInstances: 10,
|
||||
maxInstances,
|
||||
//
|
||||
// If you have trouble getting all important capabilities together, check out the
|
||||
// Sauce Labs platform configurator - a great tool to configure your capabilities:
|
||||
|
@ -1831,10 +1831,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>Ordnen Sie erstellte Ereignisse diesem Aktionstyp zu. Wenn es leer gelassen wird, werden alle Aktionstypen abgeglichen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>Stimmt mit der Client-IP des Ereignisses überein (strenge Übereinstimmung, verwenden Sie für die Netzwerkübereinstimmung eine Ausdrucksrichtlinie.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
<target>Übereinstimmungsereignisse, die von der ausgewählten Anwendung erstellt wurden. Wenn es leer gelassen wird, werden alle Anwendungen abgeglichen.</target>
|
||||
@ -6890,6 +6886,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -1917,10 +1917,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>Match created events with this action type. When left empty, all action types will be matched.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
<target>Match events created by selected application. When left empty, all applications are matched.</target>
|
||||
@ -7155,6 +7151,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -1799,10 +1799,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>Haga coincidir los eventos creados con este tipo de acción. Cuando se deja vacío, todos los tipos de acción coincidirán.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>Coincide con la IP del cliente del evento (coincidencia estricta, para la coincidencia de red, use una política de expresión</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
<target>Coincidir con eventos creados por la aplicación seleccionada. Cuando se deja vacío, todas las solicitudes coinciden.</target>
|
||||
@ -6807,6 +6803,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -2389,11 +2389,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>Inclure les événements créés avec ce type d'action. S'il est laissé vide, tous les types d'action seront inclus.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>Inclure l'adresse IP du client de l'évènement (correspondante stricte, pour un correspondance sur le réseau utiliser une politique d'expression)</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
@ -9052,6 +9047,9 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -2383,11 +2383,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>생성된 이벤트를 이 작업 유형과 일치시킵니다. 비워두면 모든 액션 유형이 일치합니다.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>이벤트의 클라이언트 IP를 일치시킵니다 (엄격 일치, 네트워크 일치의 경우 표현식 정책 사용.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
@ -8726,6 +8721,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -2371,11 +2371,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>Match gecreëerde gebeurtenissen met dit actietype. Wanneer leeg gelaten, worden alle actietypen gematcht.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>Matcht de cliënt IP van een gebeurtenis (strikt matchen, voor netwerk matchen gebruik een Expressie Beleid).</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
@ -8571,6 +8566,9 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -2391,11 +2391,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>Dopasuj utworzone zdarzenia do tego typu akcji. Jeśli pozostawisz to puste, wszystkie typy akcji zostaną dopasowane.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>Dopasowuje adres IP klienta zdarzenia (ścisłe dopasowanie, do dopasowywania sieci należy użyć zasady wyrażeń.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
@ -8991,6 +8986,9 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -2371,11 +2371,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>Màţćĥ ćŕēàţēď ēvēńţś ŵĩţĥ ţĥĩś àćţĩōń ţŷƥē. Ŵĥēń ĺēƒţ ēmƥţŷ, àĺĺ àćţĩōń ţŷƥēś ŵĩĺĺ ƀē màţćĥēď.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>Màţćĥēś Ēvēńţ'ś Ćĺĩēńţ ĨƤ (śţŕĩćţ màţćĥĩńĝ, ƒōŕ ńēţŵōŕķ màţćĥĩńĝ ũśē àń Ēxƥŕēśśĩōń Ƥōĺĩćŷ.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
@ -8954,4 +8949,7 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body></file></xliff>
|
||||
|
@ -2391,11 +2391,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>Сопоставлять созданные события с данным типом действия. Если оставить пустым, будут сопоставлены все типы действий.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>Сопоставляет IP-адрес клиента события (строгое сопоставление, для сетевого сопоставления используйте политику выражений.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
@ -9055,6 +9050,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -1798,10 +1798,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>Oluşturulan olayları bu eylem türüyle eşleştirin. Boş bırakıldığında tüm eylem türleri eşleştirilir.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>Olayın İstemci IP'siyle eşleşir (katı eşleştirme, ağ eşleştirme için bir İfade İlkesi kullanın.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
<target>Seçilen uygulama tarafından oluşturulan olayları eşleştir. Boş bırakıldığında, tüm uygulamalar eşleştirilir.</target>
|
||||
@ -6800,6 +6796,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -1666,9 +1666,6 @@
|
||||
<trans-unit id="s890810efbe103cbc">
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
</trans-unit>
|
||||
@ -5737,6 +5734,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -2390,11 +2390,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>将创建的事件与此操作类型匹配。留空时,所有操作类型都将匹配。</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>匹配事件的客户端 IP(严格匹配,要网络匹配请使用表达式策略)。</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
@ -8998,66 +8993,91 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa42be520242dec2a">
|
||||
<source>Available Sources</source>
|
||||
<target>可用源</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s876e75cf2c07b38e">
|
||||
<source>Selected Sources</source>
|
||||
<target>已选源</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s3b579c4bb6b447ae">
|
||||
<source>Successfully triggered sync.</source>
|
||||
<target>已成功触发同步。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s05073d2537b45d1a">
|
||||
<source>Sync</source>
|
||||
<target>同步</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="se9da93aa2e6cce21">
|
||||
<source>Sync User</source>
|
||||
<target>同步用户</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7bd456df0becbbff">
|
||||
<source>Available Stages</source>
|
||||
<target>可用阶段</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf80798d2f56b540b">
|
||||
<source>Selected Stages</source>
|
||||
<target>已选阶段</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf651943c3ddff635">
|
||||
<source>Available Fields</source>
|
||||
<target>可用字段</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s80ba9c5ebb7826a9">
|
||||
<source>Selected Fields</source>
|
||||
<target>已选字段</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s26733a6289ca6f1a">
|
||||
<source>Available Transports</source>
|
||||
<target>可用传输</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa65f772cfc5aa67e">
|
||||
<source>Selected Transports</source>
|
||||
<target>已选传输</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd923f95605fed7b2">
|
||||
<source>Expired</source>
|
||||
<target>已过期</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s86959994f28077dc">
|
||||
<source>Expiring soon</source>
|
||||
<target>即将过期</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc60a5fba70bf5a53">
|
||||
<source>Unlicensed</source>
|
||||
<target>未许可</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4f9880ce82953741">
|
||||
<source>Read Only</source>
|
||||
<target>只读</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4220dda46d622211">
|
||||
<source>Valid</source>
|
||||
<target>有效</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdc94711a2eb66a45">
|
||||
<source>Current license status</source>
|
||||
<target>当前许可证状态</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="se10fb73c1f1039c5">
|
||||
<source>Overall license status</source>
|
||||
<target>总体许可证状态</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc4804358f202968c">
|
||||
<source>Internal user usage</source>
|
||||
<target>内部用户用量</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s087d6f07b52b30ec">
|
||||
<source><x id="0" equiv-text="${internalUserPercentage < Infinity ? internalUserPercentage : "∞"}"/>%</source>
|
||||
<target><x id="0" equiv-text="${internalUserPercentage < Infinity ? internalUserPercentage : "∞"}"/>%</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
<target>外部用户用量</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
<target>匹配事件的客户端 IP(严格匹配,要网络匹配请使用表达式策略)。</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -1816,10 +1816,6 @@
|
||||
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
|
||||
<target>将创建的事件与此操作类型匹配。留空时,所有操作类型都将匹配。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfab527528ea64618">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
|
||||
<target>匹配事件的客户端 IP(严格匹配),对于网络匹配,请使用表达式策略。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5a15a8f39c699273">
|
||||
<source>Match events created by selected application. When left empty, all applications are matched.</source>
|
||||
<target>匹配选定应用程序创建的事件。如果留空,则匹配所有应用程序。</target>
|
||||
@ -6848,6 +6844,9 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sae72e1569d34fb02">
|
||||
<source>External user usage</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa82f8948649d0989">
|
||||
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy).</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user