Browse Source

Validation errors standardized.

pull/248/head
Sebastian Stehle 9 years ago
parent
commit
45350acaed
  1. 4
      src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs
  2. 8
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppClients.cs
  3. 2
      src/Squidex.Domain.Apps.Entities/Assets/Guards/GuardAsset.cs
  4. 6
      src/Squidex.Domain.Apps.Entities/Rules/Guards/GuardRule.cs
  5. 18
      src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs
  6. 2
      src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs
  7. 4
      src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchema.cs
  8. 4
      src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchemaField.cs
  9. 4
      src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs
  10. 1
      src/Squidex/Areas/Api/Controllers/Users/UserManagementController.cs
  11. 37
      src/Squidex/Pipeline/ApiModelValidationAttribute.cs
  12. 4
      tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/AssetsFieldPropertiesTests.cs

4
src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs

@ -115,11 +115,11 @@ namespace Squidex.Domain.Apps.Core.Scripting
} }
catch (ParserException ex) catch (ParserException ex)
{ {
throw new ValidationException("Failed to execute script with javascript syntax error.", new ValidationError(ex.Message)); throw new ValidationException($"Failed to execute script with javascript syntax error: {ex.Message}", new ValidationError(ex.Message));
} }
catch (JavaScriptException ex) catch (JavaScriptException ex)
{ {
throw new ValidationException("Failed to execute script with javascript error.", new ValidationError(ex.Message)); throw new ValidationException($"Failed to execute script with javascript error: {ex.Message}", new ValidationError(ex.Message));
} }
} }

8
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppClients.cs

@ -21,7 +21,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
if (string.IsNullOrWhiteSpace(command.Id)) if (string.IsNullOrWhiteSpace(command.Id))
{ {
error(new ValidationError("Client id must be defined.", nameof(command.Id))); error(new ValidationError("Client id is required.", nameof(command.Id)));
} }
else if (clients.ContainsKey(command.Id)) else if (clients.ContainsKey(command.Id))
{ {
@ -40,7 +40,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
if (string.IsNullOrWhiteSpace(command.Id)) if (string.IsNullOrWhiteSpace(command.Id))
{ {
error(new ValidationError("Client id must be defined.", nameof(command.Id))); error(new ValidationError("Client id is required.", nameof(command.Id)));
} }
}); });
} }
@ -55,12 +55,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{ {
if (string.IsNullOrWhiteSpace(command.Id)) if (string.IsNullOrWhiteSpace(command.Id))
{ {
error(new ValidationError("Client id must be defined.", nameof(command.Id))); error(new ValidationError("Client id is required.", nameof(command.Id)));
} }
if (string.IsNullOrWhiteSpace(command.Name) && command.Permission == null) if (string.IsNullOrWhiteSpace(command.Name) && command.Permission == null)
{ {
error(new ValidationError("Either name or permission must be defined.", nameof(command.Name), nameof(command.Permission))); error(new ValidationError("Either name or permission is required.", nameof(command.Name), nameof(command.Permission)));
} }
if (command.Permission.HasValue && !command.Permission.Value.IsEnumValue()) if (command.Permission.HasValue && !command.Permission.Value.IsEnumValue())

2
src/Squidex.Domain.Apps.Entities/Assets/Guards/GuardAsset.cs

@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Guards
{ {
if (string.IsNullOrWhiteSpace(command.FileName)) if (string.IsNullOrWhiteSpace(command.FileName))
{ {
error(new ValidationError("Name must be defined.", nameof(command.FileName))); error(new ValidationError("Name is required.", nameof(command.FileName)));
} }
if (string.Equals(command.FileName, oldName)) if (string.Equals(command.FileName, oldName))

6
src/Squidex.Domain.Apps.Entities/Rules/Guards/GuardRule.cs

@ -22,7 +22,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
{ {
if (command.Trigger == null) if (command.Trigger == null)
{ {
error(new ValidationError("Trigger must be defined.", nameof(command.Trigger))); error(new ValidationError("Trigger is required.", nameof(command.Trigger)));
} }
else else
{ {
@ -33,7 +33,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
if (command.Action == null) if (command.Action == null)
{ {
error(new ValidationError("Trigger must be defined.", nameof(command.Action))); error(new ValidationError("Trigger is required.", nameof(command.Action)));
} }
else else
{ {
@ -52,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
{ {
if (command.Trigger == null && command.Action == null) if (command.Trigger == null && command.Action == null)
{ {
error(new ValidationError("Either trigger or action must be defined.", nameof(command.Trigger), nameof(command.Action))); error(new ValidationError("Either trigger or action is required.", nameof(command.Trigger), nameof(command.Action)));
} }
if (command.Trigger != null) if (command.Trigger != null)

18
src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs

@ -31,17 +31,17 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
if (string.IsNullOrWhiteSpace(action.ApiKey)) if (string.IsNullOrWhiteSpace(action.ApiKey))
{ {
errors.Add(new ValidationError("Api key must be defined.", nameof(action.ApiKey))); errors.Add(new ValidationError("Api key is required.", nameof(action.ApiKey)));
} }
if (string.IsNullOrWhiteSpace(action.AppId)) if (string.IsNullOrWhiteSpace(action.AppId))
{ {
errors.Add(new ValidationError("Application ID key must be defined.", nameof(action.AppId))); errors.Add(new ValidationError("Application ID key is required.", nameof(action.AppId)));
} }
if (string.IsNullOrWhiteSpace(action.IndexName)) if (string.IsNullOrWhiteSpace(action.IndexName))
{ {
errors.Add(new ValidationError("Index name must be defined.", nameof(action.ApiKey))); errors.Add(new ValidationError("Index name is required.", nameof(action.IndexName)));
} }
return Task.FromResult<IEnumerable<ValidationError>>(errors); return Task.FromResult<IEnumerable<ValidationError>>(errors);
@ -53,12 +53,12 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
if (string.IsNullOrWhiteSpace(action.ConnectionString)) if (string.IsNullOrWhiteSpace(action.ConnectionString))
{ {
errors.Add(new ValidationError("Connection string must be defined.", nameof(action.ConnectionString))); errors.Add(new ValidationError("Connection string is required.", nameof(action.ConnectionString)));
} }
if (string.IsNullOrWhiteSpace(action.Queue)) if (string.IsNullOrWhiteSpace(action.Queue))
{ {
errors.Add(new ValidationError("Queue must be defined.", nameof(action.Queue))); errors.Add(new ValidationError("Queue is required.", nameof(action.Queue)));
} }
else if (!Regex.IsMatch(action.Queue, "^[a-z][a-z0-9]{2,}(\\-[a-z0-9]+)*$")) else if (!Regex.IsMatch(action.Queue, "^[a-z][a-z0-9]{2,}(\\-[a-z0-9]+)*$"))
{ {
@ -74,12 +74,12 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
if (string.IsNullOrWhiteSpace(action.ApiKey)) if (string.IsNullOrWhiteSpace(action.ApiKey))
{ {
errors.Add(new ValidationError("Api key must be defined.", nameof(action.ApiKey))); errors.Add(new ValidationError("Api key is required.", nameof(action.ApiKey)));
} }
if (string.IsNullOrWhiteSpace(action.ServiceId)) if (string.IsNullOrWhiteSpace(action.ServiceId))
{ {
errors.Add(new ValidationError("Service name must be defined.", nameof(action.ServiceId))); errors.Add(new ValidationError("Service ID is required.", nameof(action.ServiceId)));
} }
return Task.FromResult<IEnumerable<ValidationError>>(errors); return Task.FromResult<IEnumerable<ValidationError>>(errors);
@ -91,7 +91,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
if (action.WebhookUrl == null || !action.WebhookUrl.IsAbsoluteUri) if (action.WebhookUrl == null || !action.WebhookUrl.IsAbsoluteUri)
{ {
errors.Add(new ValidationError("Webhook Url must be specified and absolute.", nameof(action.WebhookUrl))); errors.Add(new ValidationError("Webhook Url is required and must be an absolute URL.", nameof(action.WebhookUrl)));
} }
return Task.FromResult<IEnumerable<ValidationError>>(errors); return Task.FromResult<IEnumerable<ValidationError>>(errors);
@ -103,7 +103,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards
if (action.Url == null || !action.Url.IsAbsoluteUri) if (action.Url == null || !action.Url.IsAbsoluteUri)
{ {
errors.Add(new ValidationError("Url must be specified and absolute.", nameof(action.Url))); errors.Add(new ValidationError("Url is required and must be an absolute URL.", nameof(action.Url)));
} }
return Task.FromResult<IEnumerable<ValidationError>>(errors); return Task.FromResult<IEnumerable<ValidationError>>(errors);

2
src/Squidex.Domain.Apps.Entities/Schemas/Guards/FieldPropertiesValidator.cs

@ -57,7 +57,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards
if (properties.AspectWidth.HasValue != properties.AspectHeight.HasValue) if (properties.AspectWidth.HasValue != properties.AspectHeight.HasValue)
{ {
yield return new ValidationError("Aspect width and height must be defined.", yield return new ValidationError("Aspect width and height is required.",
nameof(properties.AspectWidth), nameof(properties.AspectWidth),
nameof(properties.AspectHeight)); nameof(properties.AspectHeight));
} }

4
src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchema.cs

@ -52,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards
if (field.Properties == null) if (field.Properties == null)
{ {
error(new ValidationError("Properties must be defined.", $"{prefix}.{nameof(field.Properties)}")); error(new ValidationError("Properties is required.", $"{prefix}.{nameof(field.Properties)}"));
} }
var propertyErrors = FieldPropertiesValidator.Validate(field.Properties); var propertyErrors = FieldPropertiesValidator.Validate(field.Properties);
@ -79,7 +79,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards
{ {
if (command.FieldIds == null) if (command.FieldIds == null)
{ {
error(new ValidationError("Field ids must be specified.", nameof(command.FieldIds))); error(new ValidationError("Field ids is required.", nameof(command.FieldIds)));
} }
if (command.FieldIds.Count != schema.Fields.Count || command.FieldIds.Any(x => !schema.FieldsById.ContainsKey(x))) if (command.FieldIds.Count != schema.Fields.Count || command.FieldIds.Any(x => !schema.FieldsById.ContainsKey(x)))

4
src/Squidex.Domain.Apps.Entities/Schemas/Guards/GuardSchemaField.cs

@ -32,7 +32,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards
if (command.Properties == null) if (command.Properties == null)
{ {
error(new ValidationError("Properties must be defined.", nameof(command.Properties))); error(new ValidationError("Properties is required.", nameof(command.Properties)));
} }
var propertyErrors = FieldPropertiesValidator.Validate(command.Properties); var propertyErrors = FieldPropertiesValidator.Validate(command.Properties);
@ -57,7 +57,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards
{ {
if (command.Properties == null) if (command.Properties == null)
{ {
error(new ValidationError("Properties must be defined.", nameof(command.Properties))); error(new ValidationError("Properties is required.", nameof(command.Properties)));
} }
var propertyErrors = FieldPropertiesValidator.Validate(command.Properties); var propertyErrors = FieldPropertiesValidator.Validate(command.Properties);

4
src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs

@ -146,7 +146,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
/// 400 => Asset exceeds the maximum size. /// 400 => Asset exceeds the maximum size.
/// </returns> /// </returns>
/// <remarks> /// <remarks>
/// You can only upload one file at a time. The mime type of the file is not calculated by Squidex and must be defined correctly. /// You can only upload one file at a time. The mime type of the file is not calculated by Squidex and is required correctly.
/// </remarks> /// </remarks>
[MustBeAppEditor] [MustBeAppEditor]
[HttpPost] [HttpPost]
@ -248,7 +248,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
{ {
if (file.Count != 1) if (file.Count != 1)
{ {
var error = new ValidationError($"Can only upload one file, found {file.Count}."); var error = new ValidationError($"Can only upload one file, found {file.Count} files.");
throw new ValidationException("Cannot create asset.", error); throw new ValidationException("Cannot create asset.", error);
} }

1
src/Squidex/Areas/Api/Controllers/Users/UserManagementController.cs

@ -24,6 +24,7 @@ namespace Squidex.Areas.Api.Controllers.Users
{ {
[ApiAuthorize] [ApiAuthorize]
[ApiExceptionFilter] [ApiExceptionFilter]
[ApiModelValidation]
[MustBeAdministrator] [MustBeAdministrator]
[SwaggerIgnore] [SwaggerIgnore]
public sealed class UserManagementController : ApiController public sealed class UserManagementController : ApiController

37
src/Squidex/Pipeline/ApiModelValidationAttribute.cs

@ -0,0 +1,37 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Filters;
using Squidex.Infrastructure;
namespace Squidex.Pipeline
{
public sealed class ApiModelValidationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
var errors = new List<ValidationError>();
foreach (var m in context.ModelState)
{
foreach (var e in m.Value.Errors)
{
if (!string.IsNullOrWhiteSpace(e.ErrorMessage))
{
errors.Add(new ValidationError(e.ErrorMessage, m.Key));
}
}
}
throw new ValidationException("The model is not valid.", errors);
}
}
}
}

4
tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Guards/FieldProperties/AssetsFieldPropertiesTests.cs

@ -82,7 +82,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties
errors.ShouldBeEquivalentTo( errors.ShouldBeEquivalentTo(
new List<ValidationError> new List<ValidationError>
{ {
new ValidationError("Aspect width and height must be defined.", "AspectWidth", "AspectHeight") new ValidationError("Aspect width and height is required.", "AspectWidth", "AspectHeight")
}); });
} }
@ -96,7 +96,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Guards.FieldProperties
errors.ShouldBeEquivalentTo( errors.ShouldBeEquivalentTo(
new List<ValidationError> new List<ValidationError>
{ {
new ValidationError("Aspect width and height must be defined.", "AspectWidth", "AspectHeight") new ValidationError("Aspect width and height is required.", "AspectWidth", "AspectHeight")
}); });
} }
} }

Loading…
Cancel
Save