diff --git a/backend/i18n/source/backend_en.json b/backend/i18n/source/backend_en.json
index 935b70e91..156c82c7c 100644
--- a/backend/i18n/source/backend_en.json
+++ b/backend/i18n/source/backend_en.json
@@ -1,12 +1,12 @@
{
- "annotations_AbsoluteUrl": "The field {name|lower} must be an absolute URL.",
- "annotations_Compare": "The field {name|lower} must be the same as {other|lower}.",
- "annotations_EmailAddress": "The field {name|lower} is not a valid email address.",
- "annotations_Range": "The field {name|lower} must be between {min} and {max}.",
- "annotations_RegularExpression": "The field {name|lower} is not.",
- "annotations_Required": "The field {name|lower} is required.",
- "annotations_StringLength": "The field {name|lower} must be a string with a maximum length of {max}.",
- "annotations_StringLengthMinimum": "The field {name|lower} must be a string with a minimum length of {min} and a maximum length of {max}.",
+ "annotations_AbsoluteUrl": "The field '{name|lower}' must be an absolute URL.",
+ "annotations_Compare": "The field '{name|lower}' must be the same as {other|lower}.",
+ "annotations_EmailAddress": "The field '{name|lower}' is not a valid email address.",
+ "annotations_Range": "The field '{name|lower}' must be between {min} and {max}.",
+ "annotations_RegularExpression": "The field '{name|lower}' is not.",
+ "annotations_Required": "The field '{name|lower}' is required.",
+ "annotations_StringLength": "The field '{name|lower}' must be a string with a maximum length of {max}.",
+ "annotations_StringLengthMinimum": "The field '{name|lower}' must be a string with a minimum length of {min} and a maximum length of {max}.",
"apps.clients.idAlreadyExists": "A client with the same id already exists.",
"apps.contributors.cannotChangeYourself": "You cannot change your own role.",
"apps.contributors.maxReached": "You have reached the maximum number of contributors for your plan.",
diff --git a/backend/i18n/source/backend_it.json b/backend/i18n/source/backend_it.json
index 7b916255e..0927d6b3f 100644
--- a/backend/i18n/source/backend_it.json
+++ b/backend/i18n/source/backend_it.json
@@ -1,12 +1,12 @@
{
- "annotations_AbsoluteUrl": "Il campo {name|lower} deve essere un URL assoluto.",
- "annotations_Compare": "Il campo {name|lower} deve essere uguale a {other|lower}.",
- "annotations_EmailAddress": "Il campo {name|lower} non è un indirizzo email valido.",
- "annotations_Range": "Il campo {name|lower} deve essere tra {min} e {max}.",
- "annotations_RegularExpression": "Il campo {name|lower} non è.",
+ "annotations_AbsoluteUrl": "Il campo '{name|lower}' deve essere un URL assoluto.",
+ "annotations_Compare": "Il campo '{name|lower}' deve essere uguale a {other|lower}.",
+ "annotations_EmailAddress": "Il campo '{name|lower}' non è un indirizzo email valido.",
+ "annotations_Range": "Il campo '{name|lower}' deve essere tra {min} e {max}.",
+ "annotations_RegularExpression": "Il campo '{name|lower}' non è.",
"annotations_Required": "Il campo è {name|lower} obbligatorio.",
- "annotations_StringLength": "Il campo {name|lower} deve essere una stringa avente una lunghezza massima di {max}.",
- "annotations_StringLengthMinimum": "Il campo {name|lower} deve essere una stringa avente lunghezza minima di {min} e massima di {max}.",
+ "annotations_StringLength": "Il campo '{name|lower}' deve essere una stringa avente una lunghezza massima di {max}.",
+ "annotations_StringLengthMinimum": "Il campo '{name|lower}' deve essere una stringa avente lunghezza minima di {min} e massima di {max}.",
"apps.clients.idAlreadyExists": "Un client con lo stesso id esiste già.",
"apps.contributors.cannotChangeYourself": "Non puoi cambiare il tuo ruolo.",
"apps.contributors.maxReached": "Hai raggiunto il numero massimo di contributori previsto per il tuo piano.",
@@ -117,6 +117,7 @@
"common.success": "Successo",
"common.text": "Testo",
"common.trigger": "Trigger",
+ "common.url": "URL",
"common.warning": "Warning",
"common.workflow": "Workflow",
"common.workflowStep": "Step",
diff --git a/backend/i18n/source/backend_nl.json b/backend/i18n/source/backend_nl.json
index f77316df3..91ecc2ab8 100644
--- a/backend/i18n/source/backend_nl.json
+++ b/backend/i18n/source/backend_nl.json
@@ -1,12 +1,12 @@
{
- "annotations_AbsoluteUrl": "Het veld {name|lower} moet een absolute URL zijn.",
- "annotations_Compare": "Het veld {name|lower} moet hetzelfde zijn als {other|lower}.",
- "annotations_EmailAddress": "Het veld {name|lower} is geen geldig e-mailadres.",
- "annotations_Range": "Het veld {name|lower} moet tussen {min} en {max} zijn.",
- "annotations_RegularExpression": "Het veld {name|lower} is niet.",
- "annotations_Required": "Het veld {name|lower} is verplicht.",
- "annotations_StringLength": "Het veld {name|lower} moet een string zijn met een maximale lengte van {max}.",
- "annotations_StringLengthMinimum": "Het veld {name|lower} moet een string zijn met een minimum lengte van {min} en een maximum lengte van {max}.",
+ "annotations_AbsoluteUrl": "Het veld '{name|lower}' moet een absolute URL zijn.",
+ "annotations_Compare": "Het veld '{name|lower}' moet hetzelfde zijn als {other|lower}.",
+ "annotations_EmailAddress": "Het veld '{name|lower}' is geen geldig e-mailadres.",
+ "annotations_Range": "Het veld '{name|lower}' moet tussen {min} en {max} zijn.",
+ "annotations_RegularExpression": "Het veld '{name|lower}' is niet.",
+ "annotations_Required": "Het veld '{name|lower}' is verplicht.",
+ "annotations_StringLength": "Het veld '{name|lower}' moet een string zijn met een maximale lengte van {max}.",
+ "annotations_StringLengthMinimum": "Het veld '{name|lower}' moet een string zijn met een minimum lengte van {min} en een maximum lengte van {max}.",
"apps.clients.idAlreadyExists": "Er bestaat al een client met dezelfde id.",
"apps.contributors.cannotChangeYourself": "Je kunt jouw eigen rol niet wijzigen.",
"apps.contributors.maxReached": "Je heeft het maximale aantal bijdragers voor jouw plan bereikt.",
@@ -114,6 +114,7 @@
"common.signup": "Aanmelden",
"common.text": "Tekst",
"common.trigger": "Trigger",
+ "common.url": "URL",
"common.workflow": "Workflow",
"common.workflowStep": "Stap",
"common.workflowTransition": "Overgang",
diff --git a/backend/src/Squidex.Shared/Texts.it.resx b/backend/src/Squidex.Shared/Texts.it.resx
index 72de2ad4b..8bb3b6cf5 100644
--- a/backend/src/Squidex.Shared/Texts.it.resx
+++ b/backend/src/Squidex.Shared/Texts.it.resx
@@ -59,34 +59,34 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- Il campo {name|lower} deve essere un URL assoluto.
+ Il campo '{name|lower}' deve essere un URL assoluto.
- Il campo {0} deve essere un URL assoluto.
+ Il campo '{0}' deve essere un URL assoluto.
- Il campo {name|lower} deve essere uguale a {other|lower}.
+ Il campo '{name|lower}' deve essere uguale a {other|lower}.
- Il campo {0} deve essere uguale a {1}.
+ Il campo '{0}' deve essere uguale a {1}.
- Il campo {name|lower} non è un indirizzo email valido.
+ Il campo '{name|lower}' non è un indirizzo email valido.
- Il campo {0} non è un indirizzo email valido.
+ Il campo '{0}' non è un indirizzo email valido.
- Il campo {name|lower} deve essere tra {min} e {max}.
+ Il campo '{name|lower}' deve essere tra {min} e {max}.
- Il campo {0} deve essere tra {1} e {2}.
+ Il campo '{0}' deve essere tra {1} e {2}.
- Il campo {name|lower} non è.
+ Il campo '{name|lower}' non è.
- Il campo {0} non è.
+ Il campo '{0}' non è.
Il campo è {name|lower} obbligatorio.
@@ -95,16 +95,16 @@
Il campo è {0} obbligatorio.
- Il campo {name|lower} deve essere una stringa avente una lunghezza massima di {max}.
+ Il campo '{name|lower}' deve essere una stringa avente una lunghezza massima di {max}.
- Il campo {0} deve essere una stringa avente una lunghezza massima di {1}.
+ Il campo '{0}' deve essere una stringa avente una lunghezza massima di {1}.
- Il campo {name|lower} deve essere una stringa avente lunghezza minima di {min} e massima di {max}.
+ Il campo '{name|lower}' deve essere una stringa avente lunghezza minima di {min} e massima di {max}.
- Il campo {0} deve essere una stringa avente lunghezza minima di {1} e massima di {2}.
+ Il campo '{0}' deve essere una stringa avente lunghezza minima di {1} e massima di {2}.
Un client con lo stesso id esiste già.
@@ -604,9 +604,6 @@
Deve seguire il pattern.
-
- La geolocalizzazione può avere come campi solamente come latitudine e longitudine.
-
Contiene un collegamento '{id}' non valido.
@@ -631,9 +628,6 @@
Deve essere tra {min} e {max} parola(e).
-
- Il workflow del contenuto impedisce la pubblicazione.
-
Il workflow non consente le modifiche per lo stato {status}
diff --git a/backend/src/Squidex.Shared/Texts.nl.resx b/backend/src/Squidex.Shared/Texts.nl.resx
index f65134dbd..90f4eec3e 100644
--- a/backend/src/Squidex.Shared/Texts.nl.resx
+++ b/backend/src/Squidex.Shared/Texts.nl.resx
@@ -59,52 +59,52 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- Het veld {name|lower} moet een absolute URL zijn.
+ Het veld '{name|lower}' moet een absolute URL zijn.
- Het veld {0} moet een absolute URL zijn.
+ Het veld '{0}' moet een absolute URL zijn.
- Het veld {name|lower} moet hetzelfde zijn als {other|lower}.
+ Het veld '{name|lower}' moet hetzelfde zijn als {other|lower}.
- Het veld {0} moet hetzelfde zijn als {1}.
+ Het veld '{0}' moet hetzelfde zijn als {1}.
- Het veld {name|lower} is geen geldig e-mailadres.
+ Het veld '{name|lower}' is geen geldig e-mailadres.
- Het veld {0} is geen geldig e-mailadres.
+ Het veld '{0}' is geen geldig e-mailadres.
- Het veld {name|lower} moet tussen {min} en {max} zijn.
+ Het veld '{name|lower}' moet tussen {min} en {max} zijn.
- Het veld {0} moet tussen {1} en {2} zijn.
+ Het veld '{0}' moet tussen {1} en {2} zijn.
- Het veld {name|lower} is niet.
+ Het veld '{name|lower}' is niet.
- Het veld {0} is niet.
+ Het veld '{0}' is niet.
- Het veld {name|lower} is verplicht.
+ Het veld '{name|lower}' is verplicht.
- Het veld {0} is verplicht.
+ Het veld '{0}' is verplicht.
- Het veld {name|lower} moet een string zijn met een maximale lengte van {max}.
+ Het veld '{name|lower}' moet een string zijn met een maximale lengte van {max}.
- Het veld {0} moet een string zijn met een maximale lengte van {1}.
+ Het veld '{0}' moet een string zijn met een maximale lengte van {1}.
- Het veld {name|lower} moet een string zijn met een minimum lengte van {min} en een maximum lengte van {max}.
+ Het veld '{name|lower}' moet een string zijn met een minimum lengte van {min} en een maximum lengte van {max}.
- Het veld {0} moet een string zijn met een minimum lengte van {1} en een maximum lengte van {2}.
+ Het veld '{0}' moet een string zijn met een minimum lengte van {1} en een maximum lengte van {2}.
Er bestaat al een client met dezelfde id.
@@ -604,9 +604,6 @@
Moet het patroon volgen.
-
- Geolocation can only have latitude and longitude property.
-
Bevat ongeldige referentie '{id}'.
@@ -631,9 +628,6 @@
Moet tussen {min} en {max} woord (en) bevatten.
-
- Contentworkflow verhindert publiceren.
-
De werkstroom staat geen updates toe met status {status}
diff --git a/backend/src/Squidex.Shared/Texts.resx b/backend/src/Squidex.Shared/Texts.resx
index 0cc451444..39f1f41e1 100644
--- a/backend/src/Squidex.Shared/Texts.resx
+++ b/backend/src/Squidex.Shared/Texts.resx
@@ -59,52 +59,52 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- The field {name|lower} must be an absolute URL.
+ The field '{name|lower}' must be an absolute URL.
- The field {0} must be an absolute URL.
+ The field '{0}' must be an absolute URL.
- The field {name|lower} must be the same as {other|lower}.
+ The field '{name|lower}' must be the same as {other|lower}.
- The field {0} must be the same as {1}.
+ The field '{0}' must be the same as {1}.
- The field {name|lower} is not a valid email address.
+ The field '{name|lower}' is not a valid email address.
- The field {0} is not a valid email address.
+ The field '{0}' is not a valid email address.
- The field {name|lower} must be between {min} and {max}.
+ The field '{name|lower}' must be between {min} and {max}.
- The field {0} must be between {1} and {2}.
+ The field '{0}' must be between {1} and {2}.
- The field {name|lower} is not.
+ The field '{name|lower}' is not.
- The field {0} is not.
+ The field '{0}' is not.
- The field {name|lower} is required.
+ The field '{name|lower}' is required.
- The field {0} is required.
+ The field '{0}' is required.
- The field {name|lower} must be a string with a maximum length of {max}.
+ The field '{name|lower}' must be a string with a maximum length of {max}.
- The field {0} must be a string with a maximum length of {1}.
+ The field '{0}' must be a string with a maximum length of {1}.
- The field {name|lower} must be a string with a minimum length of {min} and a maximum length of {max}.
+ The field '{name|lower}' must be a string with a minimum length of {min} and a maximum length of {max}.
- The field {0} must be a string with a minimum length of {1} and a maximum length of {2}.
+ The field '{0}' must be a string with a minimum length of {1} and a maximum length of {2}.
A client with the same id already exists.
@@ -604,9 +604,6 @@
Must follow the pattern.
-
- Geolocation can only have latitude and longitude property.
-
Reference '{id}' not found.
@@ -631,9 +628,6 @@
Must have between {min} and {max} word(s).
-
- Content workflow prevents publishing.
-
The workflow does not allow updates at status {status}
diff --git a/backend/src/Squidex.Web/ApiModelValidationAttribute.cs b/backend/src/Squidex.Web/ApiModelValidationAttribute.cs
index c5abf1801..dc192e9d7 100644
--- a/backend/src/Squidex.Web/ApiModelValidationAttribute.cs
+++ b/backend/src/Squidex.Web/ApiModelValidationAttribute.cs
@@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding;
using Newtonsoft.Json;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
+using Squidex.Text;
namespace Squidex.Web
{
@@ -50,11 +51,18 @@ namespace Squidex.Web
}
else
{
+ var properties = Array.Empty();
+
+ if (!string.IsNullOrWhiteSpace(key))
+ {
+ properties = new[] { key.ToCamelCase() };
+ }
+
foreach (var error in value.Errors)
{
if (!string.IsNullOrWhiteSpace(error.ErrorMessage) && ShouldExpose(error))
{
- errors.Add(new ValidationError(error.ErrorMessage));
+ errors.Add(new ValidationError(error.ErrorMessage, properties));
}
else if (error.Exception is JsonException jsonException)
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/RestoreRequestDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/RestoreRequestDto.cs
index 01fa64122..7ffd28a81 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/RestoreRequestDto.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Backups/Models/RestoreRequestDto.cs
@@ -16,7 +16,7 @@ namespace Squidex.Areas.Api.Controllers.Backups.Models
/// The name of the app.
///
[LocalizedRegularExpression("^[a-z0-9]+(\\-[a-z0-9]+)*$")]
- public string Name { get; set; }
+ public string? Name { get; set; }
///
/// The url to the restore file.
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs b/backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs
index 75b369af6..233efaa32 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs
@@ -21,6 +21,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
/// Manages backups for apps.
///
[ApiExplorerSettings(GroupName = nameof(Backups))]
+ [ApiModelValidation(true)]
public class RestoreController : ApiController
{
private readonly IBackupService backupService;
diff --git a/backend/src/Squidex/Areas/IdentityServer/Config/LazyClientStore.cs b/backend/src/Squidex/Areas/IdentityServer/Config/LazyClientStore.cs
index 352d22c00..a887167d2 100644
--- a/backend/src/Squidex/Areas/IdentityServer/Config/LazyClientStore.cs
+++ b/backend/src/Squidex/Areas/IdentityServer/Config/LazyClientStore.cs
@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using IdentityServer4;
using IdentityServer4.Models;
@@ -107,10 +108,7 @@ namespace Squidex.Areas.IdentityServer.Config
Constants.RoleScope,
Constants.PermissionsScope
},
- Claims = new List
- {
- new ClientClaim(OpenIdClaims.Subject, user.Id)
- }
+ Claims = GetClaims(user)
};
}
@@ -237,5 +235,19 @@ namespace Squidex.Areas.IdentityServer.Config
};
}
}
+
+ private static List GetClaims(IUser user)
+ {
+ var claims = new List
+ {
+ new ClientClaim(OpenIdClaims.Subject, user.Id)
+ };
+
+ claims.AddRange(
+ user.Claims.Where(x => x.Type == SquidexClaimTypes.Permissions)
+ .Select(x => new ClientClaim(x.Type, x.Value)));
+
+ return claims;
+ }
}
}
diff --git a/backend/src/Squidex/Areas/IdentityServer/Controllers/Extensions.cs b/backend/src/Squidex/Areas/IdentityServer/Controllers/Extensions.cs
index b0bc1b89e..2b239e404 100644
--- a/backend/src/Squidex/Areas/IdentityServer/Controllers/Extensions.cs
+++ b/backend/src/Squidex/Areas/IdentityServer/Controllers/Extensions.cs
@@ -22,6 +22,11 @@ namespace Squidex.Areas.IdentityServer.Controllers
{
var externalLogin = await signInManager.GetExternalLoginInfoAsync(expectedXsrf);
+ if (externalLogin == null)
+ {
+ throw new InvalidOperationException("Request from external provider cannot be handled.");
+ }
+
var email = externalLogin.Principal.GetEmail();
if (string.IsNullOrWhiteSpace(email))