*: fix api errors raised in general validate() to specify a field (#6663)
* *: fix api errors raised in general validate() to specify a field Signed-off-by: Jens Langhammer <jens@goauthentik.io> * remove required flag for tls server name for ldap provider Signed-off-by: Jens Langhammer <jens@goauthentik.io> * attempt to make timing test less flaky Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
		| @ -9,6 +9,7 @@ from drf_spectacular.plumbing import ( | |||||||
| ) | ) | ||||||
| from drf_spectacular.settings import spectacular_settings | from drf_spectacular.settings import spectacular_settings | ||||||
| from drf_spectacular.types import OpenApiTypes | from drf_spectacular.types import OpenApiTypes | ||||||
|  | from rest_framework.settings import api_settings | ||||||
|  |  | ||||||
| from authentik.api.pagination import PAGINATION_COMPONENT_NAME, PAGINATION_SCHEMA | from authentik.api.pagination import PAGINATION_COMPONENT_NAME, PAGINATION_SCHEMA | ||||||
|  |  | ||||||
| @ -31,7 +32,7 @@ GENERIC_ERROR = build_object_type( | |||||||
| VALIDATION_ERROR = build_object_type( | VALIDATION_ERROR = build_object_type( | ||||||
|     description=_("Validation Error"), |     description=_("Validation Error"), | ||||||
|     properties={ |     properties={ | ||||||
|         "non_field_errors": build_array_type(build_standard_type(OpenApiTypes.STR)), |         api_settings.NON_FIELD_ERRORS_KEY: build_array_type(build_standard_type(OpenApiTypes.STR)), | ||||||
|         "code": build_standard_type(OpenApiTypes.STR), |         "code": build_standard_type(OpenApiTypes.STR), | ||||||
|     }, |     }, | ||||||
|     required=[], |     required=[], | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ class ApplyBlueprintMetaSerializer(PassiveSerializer): | |||||||
|         required = attrs["required"] |         required = attrs["required"] | ||||||
|         instance = BlueprintInstance.objects.filter(**identifiers).first() |         instance = BlueprintInstance.objects.filter(**identifiers).first() | ||||||
|         if not instance and required: |         if not instance and required: | ||||||
|             raise ValidationError("Required blueprint does not exist") |             raise ValidationError({"identifiers": "Required blueprint does not exist"}) | ||||||
|         self.blueprint_instance = instance |         self.blueprint_instance = instance | ||||||
|         return super().validate(attrs) |         return super().validate(attrs) | ||||||
|  |  | ||||||
|  | |||||||
| @ -47,7 +47,7 @@ class TokenSerializer(ManagedSerializer, ModelSerializer): | |||||||
|             attrs.setdefault("user", request.user) |             attrs.setdefault("user", request.user) | ||||||
|         attrs.setdefault("intent", TokenIntents.INTENT_API) |         attrs.setdefault("intent", TokenIntents.INTENT_API) | ||||||
|         if attrs.get("intent") not in [TokenIntents.INTENT_API, TokenIntents.INTENT_APP_PASSWORD]: |         if attrs.get("intent") not in [TokenIntents.INTENT_API, TokenIntents.INTENT_APP_PASSWORD]: | ||||||
|             raise ValidationError(f"Invalid intent {attrs.get('intent')}") |             raise ValidationError({"intent": f"Invalid intent {attrs.get('intent')}"}) | ||||||
|         return attrs |         return attrs | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ class NotificationTransportSerializer(ModelSerializer): | |||||||
|         mode = attrs.get("mode") |         mode = attrs.get("mode") | ||||||
|         if mode in [TransportMode.WEBHOOK, TransportMode.WEBHOOK_SLACK]: |         if mode in [TransportMode.WEBHOOK, TransportMode.WEBHOOK_SLACK]: | ||||||
|             if "webhook_url" not in attrs or attrs.get("webhook_url", "") == "": |             if "webhook_url" not in attrs or attrs.get("webhook_url", "") == "": | ||||||
|                 raise ValidationError("Webhook URL may not be empty.") |                 raise ValidationError({"webhook_url": "Webhook URL may not be empty."}) | ||||||
|         return attrs |         return attrs | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  | |||||||
| @ -59,7 +59,9 @@ class ProxyProviderSerializer(ProviderSerializer): | |||||||
|             attrs.get("mode", ProxyMode.PROXY) == ProxyMode.PROXY |             attrs.get("mode", ProxyMode.PROXY) == ProxyMode.PROXY | ||||||
|             and attrs.get("internal_host", "") == "" |             and attrs.get("internal_host", "") == "" | ||||||
|         ): |         ): | ||||||
|             raise ValidationError(_("Internal host cannot be empty when forward auth is disabled.")) |             raise ValidationError( | ||||||
|  |                 {"internal_host": _("Internal host cannot be empty when forward auth is disabled.")} | ||||||
|  |             ) | ||||||
|         return attrs |         return attrs | ||||||
|  |  | ||||||
|     def create(self, validated_data: dict): |     def create(self, validated_data: dict): | ||||||
|  | |||||||
| @ -69,7 +69,7 @@ class ProxyProviderTests(APITestCase): | |||||||
|         self.assertEqual(response.status_code, 400) |         self.assertEqual(response.status_code, 400) | ||||||
|         self.assertJSONEqual( |         self.assertJSONEqual( | ||||||
|             response.content.decode(), |             response.content.decode(), | ||||||
|             {"non_field_errors": ["Internal host cannot be empty when forward auth is disabled."]}, |             {"internal_host": ["Internal host cannot be empty when forward auth is disabled."]}, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def test_create_defaults(self): |     def test_create_defaults(self): | ||||||
|  | |||||||
| @ -44,7 +44,11 @@ class LDAPSourceSerializer(SourceSerializer): | |||||||
|                 sources = sources.exclude(pk=self.instance.pk) |                 sources = sources.exclude(pk=self.instance.pk) | ||||||
|             if sources.exists(): |             if sources.exists(): | ||||||
|                 raise ValidationError( |                 raise ValidationError( | ||||||
|                     "Only a single LDAP Source with password synchronization is allowed" |                     { | ||||||
|  |                         "sync_users_password": ( | ||||||
|  |                             "Only a single LDAP Source with password synchronization is allowed" | ||||||
|  |                         ) | ||||||
|  |                     } | ||||||
|                 ) |                 ) | ||||||
|         return super().validate(attrs) |         return super().validate(attrs) | ||||||
|  |  | ||||||
|  | |||||||
| @ -63,7 +63,7 @@ class OAuthSourceSerializer(SourceSerializer): | |||||||
|                 well_known_config.raise_for_status() |                 well_known_config.raise_for_status() | ||||||
|             except RequestException as exc: |             except RequestException as exc: | ||||||
|                 text = exc.response.text if exc.response else str(exc) |                 text = exc.response.text if exc.response else str(exc) | ||||||
|                 raise ValidationError(text) |                 raise ValidationError({"oidc_well_known_url": text}) | ||||||
|             config = well_known_config.json() |             config = well_known_config.json() | ||||||
|             try: |             try: | ||||||
|                 attrs["authorization_url"] = config["authorization_endpoint"] |                 attrs["authorization_url"] = config["authorization_endpoint"] | ||||||
| @ -71,7 +71,9 @@ class OAuthSourceSerializer(SourceSerializer): | |||||||
|                 attrs["profile_url"] = config["userinfo_endpoint"] |                 attrs["profile_url"] = config["userinfo_endpoint"] | ||||||
|                 attrs["oidc_jwks_url"] = config["jwks_uri"] |                 attrs["oidc_jwks_url"] = config["jwks_uri"] | ||||||
|             except (IndexError, KeyError) as exc: |             except (IndexError, KeyError) as exc: | ||||||
|                 raise ValidationError(f"Invalid well-known configuration: {exc}") |                 raise ValidationError( | ||||||
|  |                     {"oidc_well_known_url": f"Invalid well-known configuration: {exc}"} | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|         jwks_url = attrs.get("oidc_jwks_url") |         jwks_url = attrs.get("oidc_jwks_url") | ||||||
|         if jwks_url and jwks_url != "": |         if jwks_url and jwks_url != "": | ||||||
| @ -80,7 +82,7 @@ class OAuthSourceSerializer(SourceSerializer): | |||||||
|                 jwks_config.raise_for_status() |                 jwks_config.raise_for_status() | ||||||
|             except RequestException as exc: |             except RequestException as exc: | ||||||
|                 text = exc.response.text if exc.response else str(exc) |                 text = exc.response.text if exc.response else str(exc) | ||||||
|                 raise ValidationError(text) |                 raise ValidationError({"jwks_url": text}) | ||||||
|             config = jwks_config.json() |             config = jwks_config.json() | ||||||
|             attrs["oidc_jwks"] = config |             attrs["oidc_jwks"] = config | ||||||
|  |  | ||||||
|  | |||||||
| @ -99,6 +99,7 @@ class TestUserLoginStage(FlowTestCase): | |||||||
|         session[SESSION_KEY_PLAN] = plan |         session[SESSION_KEY_PLAN] = plan | ||||||
|         session.save() |         session.save() | ||||||
|  |  | ||||||
|  |         before_request = now() | ||||||
|         response = self.client.get( |         response = self.client.get( | ||||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) |             reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) | ||||||
|         ) |         ) | ||||||
| @ -108,7 +109,7 @@ class TestUserLoginStage(FlowTestCase): | |||||||
|         session_key = self.client.session.session_key |         session_key = self.client.session.session_key | ||||||
|         session = AuthenticatedSession.objects.filter(session_key=session_key).first() |         session = AuthenticatedSession.objects.filter(session_key=session_key).first() | ||||||
|         self.assertAlmostEqual( |         self.assertAlmostEqual( | ||||||
|             session.expires.timestamp() - now().timestamp(), |             session.expires.timestamp() - before_request.timestamp(), | ||||||
|             timedelta_from_string(self.stage.session_duration).total_seconds(), |             timedelta_from_string(self.stage.session_duration).total_seconds(), | ||||||
|             delta=1, |             delta=1, | ||||||
|         ) |         ) | ||||||
|  | |||||||
| @ -36,7 +36,7 @@ class TenantSerializer(ModelSerializer): | |||||||
|             if self.instance: |             if self.instance: | ||||||
|                 tenants = tenants.exclude(pk=self.instance.pk) |                 tenants = tenants.exclude(pk=self.instance.pk) | ||||||
|             if tenants.exists(): |             if tenants.exists(): | ||||||
|                 raise ValidationError("Only a single Tenant can be set as default.") |                 raise ValidationError({"default": "Only a single Tenant can be set as default."}) | ||||||
|         return super().validate(attrs) |         return super().validate(attrs) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  | |||||||
| @ -217,7 +217,6 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> { | |||||||
|                     </ak-form-element-horizontal> |                     </ak-form-element-horizontal> | ||||||
|                     <ak-form-element-horizontal |                     <ak-form-element-horizontal | ||||||
|                         label=${msg("TLS Server name")} |                         label=${msg("TLS Server name")} | ||||||
|                         ?required=${true} |  | ||||||
|                         name="tlsServerName" |                         name="tlsServerName" | ||||||
|                     > |                     > | ||||||
|                         <input |                         <input | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Jens L
					Jens L