From e2f9b53c63c15460fd61d7ece80d86dc1c0b1bf6 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 7 Mar 2021 18:50:19 +0100 Subject: [PATCH] Fix permissions for user client id and secret. --- backend/i18n/source/backend_en.json | 16 ++++---- backend/i18n/source/backend_it.json | 15 ++++---- backend/i18n/source/backend_nl.json | 17 +++++---- backend/src/Squidex.Shared/Texts.it.resx | 34 +++++++---------- backend/src/Squidex.Shared/Texts.nl.resx | 38 ++++++++----------- backend/src/Squidex.Shared/Texts.resx | 38 ++++++++----------- .../ApiModelValidationAttribute.cs | 10 ++++- .../Backups/Models/RestoreRequestDto.cs | 2 +- .../Controllers/Backups/RestoreController.cs | 1 + .../IdentityServer/Config/LazyClientStore.cs | 20 ++++++++-- .../IdentityServer/Controllers/Extensions.cs | 5 +++ 11 files changed, 103 insertions(+), 93 deletions(-) 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))