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
	