diff --git a/backend/i18n/frontend_en.json b/backend/i18n/frontend_en.json
index 774af780b..b3f7b0219 100644
--- a/backend/i18n/frontend_en.json
+++ b/backend/i18n/frontend_en.json
@@ -352,6 +352,7 @@
"contents.arrayNoFields": "Add a nested field first to add items.",
"contents.assetsUpload": "Drop files or click",
"contents.autotranslate": "Autotranslate from master language",
+ "contents.bulkFailed": "Failed to delete or update content. Please reload.",
"contents.changeStatusTo": "Change content item(s) to {action}",
"contents.changeStatusToImmediately": "Set to {action} immediately.",
"contents.changeStatusToLater": "Set to {action} at a later point date and time.",
@@ -370,7 +371,6 @@
"contents.currentStatusLabel": "Current Version",
"contents.deleteConfirmText": "Do you really want to delete the content?",
"contents.deleteConfirmTitle": "Delete content",
- "contents.deleteFailed": "Failed to delete content. Please reload.",
"contents.deleteManyConfirmText": "Do you really want to delete the selected content items?",
"contents.deleteReferrerConfirmText": "The content is referenced by another content item.\n\nDo you really want to delete this content?",
"contents.deleteReferrerConfirmTitle": "Delete content",
@@ -379,7 +379,6 @@
"contents.draftNew": "New Draft",
"contents.draftStatus": "New Version",
"contents.editPageTitle": "Edit Content",
- "contents.editTitle": "Edit Content",
"contents.invariantFieldDescription": "The '{fieldName}' field of the content item.",
"contents.languageModeAll": "All Languages",
"contents.languageModeSingle": "Single Language",
@@ -644,7 +643,6 @@
"rules.wizard.selectAction": "Select Action",
"rules.wizard.selectTrigger": "Select Trigger",
"rules.wizard.triggerHint": "The selection of the trigger type cannot be changed later.",
- "schema.fields.localConfirmText": "Lock field",
"schemas.addField": "Add Field",
"schemas.addFieldAndClose": "Create and close",
"schemas.addFieldAndCreate": "Create and add field",
@@ -883,17 +881,22 @@
"users.createPageTitle": "Create User",
"users.createTitle": "New User",
"users.createTooltip": "New User (CTRL + N)",
+ "users.deleteConfirmText": "Do you really want to delete this user?",
+ "users.deleteConfirmTitle": "Delete user",
+ "users.deleteFailed": "Failed to delete user. Please reload.",
"users.editPageTitle": "Edit User",
"users.editTitle": "Edit User",
"users.listPageTitle": "User Management",
"users.listTitle": "Users",
"users.loadFailed": "Failed to load users. Please reload.",
"users.loadUserFailed": "Failed to load user. Please reload.",
+ "users.lockFailed": "Failed to lock user. Please reload.",
"users.lockTooltip": "Lock User",
"users.passwordConfirmValidationMessage": "Passwords must be the same.",
"users.refreshTooltip": "Refresh Users (CTRL + SHIFT + R)",
"users.reloaded": "Users reloaded.",
"users.search": "Search for user",
+ "users.unlockFailed": "Failed to unlock user. Please reload.",
"users.unlockTooltip": "Unlock User",
"users.updateFailed": "Failed to update user. Please reload.",
"validation.between": "{field} must be between '{min}' and '{max}'.",
diff --git a/backend/i18n/frontend_it.json b/backend/i18n/frontend_it.json
index a22e9430b..3b9a5e4b2 100644
--- a/backend/i18n/frontend_it.json
+++ b/backend/i18n/frontend_it.json
@@ -352,6 +352,7 @@
"contents.arrayNoFields": "Aggiungi un primo campo annidato agli elementi.",
"contents.assetsUpload": "Trascina i file o clicca",
"contents.autotranslate": "Traduci in automatico dalla lingua principale",
+ "contents.bulkFailed": "Non è stato possibile eliminare il contenuto. Per favore ricarica.",
"contents.changeStatusTo": "Cambia l'elemeto(i) del contenuti in {action}",
"contents.changeStatusToImmediately": "Imposta {action} immediatamente.",
"contents.changeStatusToLater": "Imposta {action} ad una data e ora successiva.",
@@ -370,7 +371,6 @@
"contents.currentStatusLabel": "Versione corrente",
"contents.deleteConfirmText": "Sei sicuro di voler eliminare il contenuto?",
"contents.deleteConfirmTitle": "Elimina il contenuto",
- "contents.deleteFailed": "Non è stato possibile eliminare il contenuto. Per favore ricarica.",
"contents.deleteManyConfirmText": "Sei sicuro di voler eliminare gli elementi del contenuto selezionati?",
"contents.deleteReferrerConfirmText": "Il contenuto è collegato a un altro contenuto.\n\nSei sicuro di volerlo cancellare?",
"contents.deleteReferrerConfirmTitle": "Contenuto cancellato",
@@ -379,7 +379,6 @@
"contents.draftNew": "Nuova bozza",
"contents.draftStatus": "Nuova versione",
"contents.editPageTitle": "Modifica contenuto",
- "contents.editTitle": "Modifica il contenuto",
"contents.invariantFieldDescription": "Il campo '{fieldName}' del contenuto.",
"contents.languageModeAll": "Tutte le lingue",
"contents.languageModeSingle": "Una sola lingua",
@@ -644,7 +643,6 @@
"rules.wizard.selectAction": "Seleziona l'Azione",
"rules.wizard.selectTrigger": "Seleziona l'Attivazione",
"rules.wizard.triggerHint": "La selezione del tipo di attivazione non potrà essere modificata successivamente.",
- "schema.fields.localConfirmText": "Blocca il campo",
"schemas.addField": "Aggiungi un Campo",
"schemas.addFieldAndClose": "Crea e chiudi",
"schemas.addFieldAndCreate": "Crea e aggiungi il campo",
@@ -883,17 +881,22 @@
"users.createPageTitle": "Crea un utente",
"users.createTitle": "Nuovo utente",
"users.createTooltip": "Nuovo utente (CTRL + N)",
+ "users.deleteConfirmText": "Do you really want to delete this user?",
+ "users.deleteConfirmTitle": "Delete user",
+ "users.deleteFailed": "Failed to delete user. Please reload.",
"users.editPageTitle": "Modifica l'utente",
"users.editTitle": "Modifica l'utente",
"users.listPageTitle": "Gestione Utente",
"users.listTitle": "Utenti",
"users.loadFailed": "Non è stato possibile caricare gli utenti. Per favore ricarica.",
"users.loadUserFailed": "Non è stato possibile caricare l'utente. Per favore ricarica.",
+ "users.lockFailed": "Failed to lock user. Please reload.",
"users.lockTooltip": "Utente bloccato",
"users.passwordConfirmValidationMessage": "Le password devono essere uguali.",
"users.refreshTooltip": "Aggiorna gli Utenti (CTRL + SHIFT + R)",
"users.reloaded": "Utenti ricaricati.",
"users.search": "Cerca l'utente",
+ "users.unlockFailed": "Failed to unlock user. Please reload.",
"users.unlockTooltip": "Sblocca l'utente",
"users.updateFailed": "Non è stato possibile aggiornare l'utente. Per favore ricarica.",
"validation.between": "{field} deve essere tra '{min}' e '{max}'.",
diff --git a/backend/i18n/frontend_nl.json b/backend/i18n/frontend_nl.json
index dcdc9e828..b608d6b5d 100644
--- a/backend/i18n/frontend_nl.json
+++ b/backend/i18n/frontend_nl.json
@@ -352,6 +352,7 @@
"contents.arrayNoFields": "Voeg eerst een genest veld toe om items toe te voegen.",
"contents.assetsUpload": "Zet bestanden neer of klik",
"contents.autotranslate": "Automatisch vertalen vanuit de hoofdtaal",
+ "contents.bulkFailed": "Verwijderen van inhoud is mislukt. Laad opnieuw.",
"contents.changeStatusTo": "Verander inhoud item(s) in {action}",
"contents.changeStatusToImmediately": "Zet onmiddellijk op {action}.",
"contents.changeStatusToLater": "Zet op {action} op een latere datum en tijd.",
@@ -370,7 +371,6 @@
"contents.currentStatusLabel": "Huidige versie",
"contents.deleteConfirmText": "Wilt je de inhoud echt verwijderen?",
"contents.deleteConfirmTitle": "Inhoud verwijderen",
- "contents.deleteFailed": "Verwijderen van inhoud is mislukt. Laad opnieuw.",
"contents.deleteManyConfirmText": "Weet je zeker dat je de geselecteerde inhoudsitems wilt verwijderen?",
"contents.deleteReferrerConfirmText": "Er wordt naar de inhoud verwezen door een ander inhoudsitem. \n \n Wil je de inhoud echt verwijderen?",
"contents.deleteReferrerConfirmTitle": "Inhoud verwijderen",
@@ -379,7 +379,6 @@
"contents.draftNew": "Nieuw concept",
"contents.draftStatus": "Nieuwe versie",
"contents.editPageTitle": "Inhoud bewerken",
- "contents.editTitle": "Inhoud bewerken",
"contents.invariantFieldDescription": "Het veld '{fieldName}' van het inhoudsitem.",
"contents.languageModeAll": "Alle talen",
"contents.languageModeSingle": "Enkele taal",
@@ -644,7 +643,6 @@
"rules.wizard.selectAction": "Selecteer actie",
"rules.wizard.selectTrigger": "Selecteer Trigger",
"rules.wizard.triggerHint": "De selectie van het triggertype kan later niet worden gewijzigd.",
- "schema.fields.localConfirmText": "Lock field",
"schemas.addField": "Veld toevoegen",
"schemas.addFieldAndClose": "Maken en sluiten",
"schemas.addFieldAndCreate": "Maak en voeg veld toe",
@@ -883,17 +881,22 @@
"users.createPageTitle": "Gebruiker aanmaken",
"users.createTitle": "Nieuwe gebruiker",
"users.createTooltip": "Nieuwe gebruiker (CTRL + N)",
+ "users.deleteConfirmText": "Do you really want to delete this user?",
+ "users.deleteConfirmTitle": "Delete user",
+ "users.deleteFailed": "Failed to delete user. Please reload.",
"users.editPageTitle": "Gebruiker bewerken",
"users.editTitle": "Gebruiker bewerken",
"users.listPageTitle": "Gebruikersbeheer",
"users.listTitle": "Gebruikers",
"users.loadFailed": "Laden van gebruikers mislukt. Laad opnieuw.",
"users.loadUserFailed": "Kan gebruiker niet laden. Laad opnieuw.",
+ "users.lockFailed": "Failed to lock user. Please reload.",
"users.lockTooltip": "Gebruiker vergrendelen",
"users.passwordConfirmValidationMessage": "Wachtwoorden moeten hetzelfde zijn.",
"users.refreshTooltip": "Ververs gebruikers (CTRL + SHIFT + R)",
"users.reloaded": "Gebruikers herladen.",
"users.search": "Zoeken naar gebruiker",
+ "users.unlockFailed": "Failed to unlock user. Please reload.",
"users.unlockTooltip": "Gebruiker ontgrendelen",
"users.updateFailed": "Update gebruiker mislukt. Laad opnieuw.",
"validation.between": "{field} moet tussen '{min}' en '{max}' liggen.",
diff --git a/backend/i18n/source/backend_en.json b/backend/i18n/source/backend_en.json
index 2b43774e0..44c66589e 100644
--- a/backend/i18n/source/backend_en.json
+++ b/backend/i18n/source/backend_en.json
@@ -126,7 +126,6 @@
"contents.invalidGeolocation": "Invalid json type, expected latitude/longitude object.",
"contents.invalidGeolocationLatitude": "Latitude must be between -90 and 90.",
"contents.invalidGeolocationLongitude": "Longitude must be between -180 and 180.",
- "contents.invalidGeolocationMoreProperties": "Geolocation can only have latitude and longitude property.",
"contents.invalidNumber": "Invalid json type, expected number.",
"contents.invalidString": "Invalid json type, expected string.",
"contents.listReferences": "{count} Reference(s)",
@@ -282,6 +281,7 @@
"users.consent.piiHeadline": "Personal Information",
"users.consent.piiText": "I understand and agree that Squidex collects the following private information that are retrieved from external authentication providers such as Google, Microsoft or Github.
",
"users.consent.title": "Consent",
+ "users.deleteYourselfError": "You cannot delete yourself.",
"users.error.headline": "Operation failed",
"users.error.text": "We are really sorry that something went wrong.",
"users.error.title": "Error",
diff --git a/backend/i18n/source/backend_it.json b/backend/i18n/source/backend_it.json
index b1d10caeb..7c1b506b7 100644
--- a/backend/i18n/source/backend_it.json
+++ b/backend/i18n/source/backend_it.json
@@ -126,7 +126,6 @@
"contents.invalidGeolocation": "Errore nel json, atteso un object latitudine/longitudine.",
"contents.invalidGeolocationLatitude": "La latitudine deve essere tra -90 and 90.",
"contents.invalidGeolocationLongitude": "La longitude deve essere tra -180 and 180.",
- "contents.invalidGeolocationMoreProperties": "E' possibile impostare la geolocalizzazione solo impostando latitudine e longitudine.",
"contents.invalidNumber": "Errore nel json,, atteso un number.",
"contents.invalidString": "Errore nel json, atteso una string.",
"contents.listReferences": "{count} Collegamenti(s)",
diff --git a/backend/i18n/source/backend_nl.json b/backend/i18n/source/backend_nl.json
index 09103ae63..35ec0f2e0 100644
--- a/backend/i18n/source/backend_nl.json
+++ b/backend/i18n/source/backend_nl.json
@@ -126,7 +126,6 @@
"contents.invalidGeolocation": "Ongeldig json-type, verwacht object voor lengte- / breedtegraad.",
"contents.invalidGeolocationLatitude": "Breedtegraad moet tussen -90 en 90 zijn.",
"contents.invalidGeolocationLongitude": "Lengtegraad moet tussen -180 en 180 liggen.",
- "contents.invalidGeolocationMoreProperties": "Geolocatie kan alleen de eigenschap lengte- en breedtegraad hebben.",
"contents.invalidNumber": "Ongeldig json-type, verwacht aantal.",
"contents.invalidString": "Ongeldig json-type, verwachte string.",
"contents.listReferences": "{count} referentie (s)",
diff --git a/backend/i18n/source/frontend_en.json b/backend/i18n/source/frontend_en.json
index 774af780b..b3f7b0219 100644
--- a/backend/i18n/source/frontend_en.json
+++ b/backend/i18n/source/frontend_en.json
@@ -352,6 +352,7 @@
"contents.arrayNoFields": "Add a nested field first to add items.",
"contents.assetsUpload": "Drop files or click",
"contents.autotranslate": "Autotranslate from master language",
+ "contents.bulkFailed": "Failed to delete or update content. Please reload.",
"contents.changeStatusTo": "Change content item(s) to {action}",
"contents.changeStatusToImmediately": "Set to {action} immediately.",
"contents.changeStatusToLater": "Set to {action} at a later point date and time.",
@@ -370,7 +371,6 @@
"contents.currentStatusLabel": "Current Version",
"contents.deleteConfirmText": "Do you really want to delete the content?",
"contents.deleteConfirmTitle": "Delete content",
- "contents.deleteFailed": "Failed to delete content. Please reload.",
"contents.deleteManyConfirmText": "Do you really want to delete the selected content items?",
"contents.deleteReferrerConfirmText": "The content is referenced by another content item.\n\nDo you really want to delete this content?",
"contents.deleteReferrerConfirmTitle": "Delete content",
@@ -379,7 +379,6 @@
"contents.draftNew": "New Draft",
"contents.draftStatus": "New Version",
"contents.editPageTitle": "Edit Content",
- "contents.editTitle": "Edit Content",
"contents.invariantFieldDescription": "The '{fieldName}' field of the content item.",
"contents.languageModeAll": "All Languages",
"contents.languageModeSingle": "Single Language",
@@ -644,7 +643,6 @@
"rules.wizard.selectAction": "Select Action",
"rules.wizard.selectTrigger": "Select Trigger",
"rules.wizard.triggerHint": "The selection of the trigger type cannot be changed later.",
- "schema.fields.localConfirmText": "Lock field",
"schemas.addField": "Add Field",
"schemas.addFieldAndClose": "Create and close",
"schemas.addFieldAndCreate": "Create and add field",
@@ -883,17 +881,22 @@
"users.createPageTitle": "Create User",
"users.createTitle": "New User",
"users.createTooltip": "New User (CTRL + N)",
+ "users.deleteConfirmText": "Do you really want to delete this user?",
+ "users.deleteConfirmTitle": "Delete user",
+ "users.deleteFailed": "Failed to delete user. Please reload.",
"users.editPageTitle": "Edit User",
"users.editTitle": "Edit User",
"users.listPageTitle": "User Management",
"users.listTitle": "Users",
"users.loadFailed": "Failed to load users. Please reload.",
"users.loadUserFailed": "Failed to load user. Please reload.",
+ "users.lockFailed": "Failed to lock user. Please reload.",
"users.lockTooltip": "Lock User",
"users.passwordConfirmValidationMessage": "Passwords must be the same.",
"users.refreshTooltip": "Refresh Users (CTRL + SHIFT + R)",
"users.reloaded": "Users reloaded.",
"users.search": "Search for user",
+ "users.unlockFailed": "Failed to unlock user. Please reload.",
"users.unlockTooltip": "Unlock User",
"users.updateFailed": "Failed to update user. Please reload.",
"validation.between": "{field} must be between '{min}' and '{max}'.",
diff --git a/backend/i18n/source/frontend_it.json b/backend/i18n/source/frontend_it.json
index fbc295343..450344dfc 100644
--- a/backend/i18n/source/frontend_it.json
+++ b/backend/i18n/source/frontend_it.json
@@ -347,6 +347,7 @@
"contents.arrayNoFields": "Aggiungi un primo campo annidato agli elementi.",
"contents.assetsUpload": "Trascina i file o clicca",
"contents.autotranslate": "Traduci in automatico dalla lingua principale",
+ "contents.bulkFailed": "Non è stato possibile eliminare il contenuto. Per favore ricarica.",
"contents.changeStatusTo": "Cambia l'elemeto(i) del contenuti in {action}",
"contents.changeStatusToImmediately": "Imposta {action} immediatamente.",
"contents.changeStatusToLater": "Imposta {action} ad una data e ora successiva.",
@@ -362,7 +363,6 @@
"contents.currentStatusLabel": "Versione corrente",
"contents.deleteConfirmText": "Sei sicuro di voler eliminare il contenuto?",
"contents.deleteConfirmTitle": "Elimina il contenuto",
- "contents.deleteFailed": "Non è stato possibile eliminare il contenuto. Per favore ricarica.",
"contents.deleteManyConfirmText": "Sei sicuro di voler eliminare gli elementi del contenuto selezionati?",
"contents.deleteReferrerConfirmText": "Il contenuto è collegato a un altro contenuto.\n\nSei sicuro di volerlo cancellare?",
"contents.deleteReferrerConfirmTitle": "Contenuto cancellato",
@@ -371,7 +371,6 @@
"contents.draftNew": "Nuova bozza",
"contents.draftStatus": "Nuova versione",
"contents.editPageTitle": "Modifica contenuto",
- "contents.editTitle": "Modifica il contenuto",
"contents.invariantFieldDescription": "Il campo '{fieldName}' del contenuto.",
"contents.languageModeAll": "Tutte le lingue",
"contents.languageModeSingle": "Una sola lingua",
@@ -626,7 +625,6 @@
"rules.wizard.selectAction": "Seleziona l'Azione",
"rules.wizard.selectTrigger": "Seleziona l'Attivazione",
"rules.wizard.triggerHint": "La selezione del tipo di attivazione non potrà essere modificata successivamente.",
- "schema.fields.localConfirmText": "Blocca il campo",
"schemas.addField": "Aggiungi un Campo",
"schemas.addFieldAndClose": "Crea e chiudi",
"schemas.addFieldAndCreate": "Crea e aggiungi il campo",
diff --git a/backend/i18n/source/frontend_nl.json b/backend/i18n/source/frontend_nl.json
index 5ab379cad..6ba22de24 100644
--- a/backend/i18n/source/frontend_nl.json
+++ b/backend/i18n/source/frontend_nl.json
@@ -340,6 +340,7 @@
"contents.arrayNoFields": "Voeg eerst een genest veld toe om items toe te voegen.",
"contents.assetsUpload": "Zet bestanden neer of klik",
"contents.autotranslate": "Automatisch vertalen vanuit de hoofdtaal",
+ "contents.bulkFailed": "Verwijderen van inhoud is mislukt. Laad opnieuw.",
"contents.changeStatusTo": "Verander inhoud item(s) in {action}",
"contents.changeStatusToImmediately": "Zet onmiddellijk op {action}.",
"contents.changeStatusToLater": "Zet op {action} op een latere datum en tijd.",
@@ -355,7 +356,6 @@
"contents.currentStatusLabel": "Huidige versie",
"contents.deleteConfirmText": "Wilt je de inhoud echt verwijderen?",
"contents.deleteConfirmTitle": "Inhoud verwijderen",
- "contents.deleteFailed": "Verwijderen van inhoud is mislukt. Laad opnieuw.",
"contents.deleteManyConfirmText": "Weet je zeker dat je de geselecteerde inhoudsitems wilt verwijderen?",
"contents.deleteReferrerConfirmText": "Er wordt naar de inhoud verwezen door een ander inhoudsitem. \n \n Wil je de inhoud echt verwijderen?",
"contents.deleteReferrerConfirmTitle": "Inhoud verwijderen",
@@ -364,7 +364,6 @@
"contents.draftNew": "Nieuw concept",
"contents.draftStatus": "Nieuwe versie",
"contents.editPageTitle": "Inhoud bewerken",
- "contents.editTitle": "Inhoud bewerken",
"contents.invariantFieldDescription": "Het veld '{fieldName}' van het inhoudsitem.",
"contents.languageModeAll": "Alle talen",
"contents.languageModeSingle": "Enkele taal",
diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/PredefinedPatternsFormatter.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/PredefinedPatternsFormatter.cs
index 4f472a1cf..62a739c3a 100644
--- a/backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/PredefinedPatternsFormatter.cs
+++ b/backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/PredefinedPatternsFormatter.cs
@@ -10,7 +10,7 @@ using System.Collections.Generic;
using System.Globalization;
using Squidex.Domain.Apps.Core.Rules.EnrichedEvents;
using Squidex.Infrastructure;
-using Squidex.Shared.Users;
+using Squidex.Shared.Identity;
using Squidex.Text;
namespace Squidex.Domain.Apps.Core.HandleRules
@@ -161,7 +161,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules
{
if (@event is EnrichedUserEventBase userEvent)
{
- return userEvent.User?.DisplayName();
+ return userEvent.User?.Claims.DisplayName();
}
return null;
@@ -191,7 +191,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules
{
if (@event is EnrichedCommentEvent commentEvent)
{
- return commentEvent.MentionedUser.DisplayName();
+ return commentEvent.MentionedUser.Claims.DisplayName();
}
return null;
diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs
index a0725cbe5..aca73b166 100644
--- a/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs
+++ b/backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintUser.cs
@@ -26,7 +26,7 @@ namespace Squidex.Domain.Apps.Core.Scripting
var isClient = !string.IsNullOrWhiteSpace(clientId);
- return CreateUser(engine, user.Id, isClient, user.Email, user.DisplayName(), user.Claims);
+ return CreateUser(engine, user.Id, isClient, user.Email, user.Claims.DisplayName(), user.Claims);
}
public static ObjectWrapper Create(Engine engine, ClaimsPrincipal principal)
diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/Templates/Extensions/UserFluidExtension.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/Templates/Extensions/UserFluidExtension.cs
index f74b05589..a246dcff2 100644
--- a/backend/src/Squidex.Domain.Apps.Core.Operations/Templates/Extensions/UserFluidExtension.cs
+++ b/backend/src/Squidex.Domain.Apps.Core.Operations/Templates/Extensions/UserFluidExtension.cs
@@ -9,6 +9,7 @@ using System;
using System.Linq;
using Fluid;
using Fluid.Values;
+using Squidex.Shared.Identity;
using Squidex.Shared.Users;
namespace Squidex.Domain.Apps.Core.Templates.Extensions
@@ -26,7 +27,7 @@ namespace Squidex.Domain.Apps.Core.Templates.Extensions
case "email":
return new StringValue(user.Email);
case "name":
- return new StringValue(user.DisplayName());
+ return new StringValue(user.Claims.DisplayName());
default:
{
var claim = user.Claims.FirstOrDefault(x => string.Equals(name, x.Type, StringComparison.OrdinalIgnoreCase));
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/GeoQueryTransformer.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/GeoQueryTransformer.cs
index 741d87d8b..5b98ddeb8 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/GeoQueryTransformer.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/GeoQueryTransformer.cs
@@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
-using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Contents.Text;
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Context.cs b/backend/src/Squidex.Domain.Apps.Entities/Context.cs
index 335250bff..e35874636 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Context.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Context.cs
@@ -36,7 +36,7 @@ namespace Squidex.Domain.Apps.Entities
User = user;
- Permissions = User.Permissions();
+ Permissions = User.Claims.Permissions();
IsFrontendClient = User.IsInClient(DefaultClients.Frontend);
}
diff --git a/backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs b/backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs
index 55652f5b6..84b82eddd 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/History/NotifoService.cs
@@ -25,7 +25,7 @@ using Squidex.Shared.Users;
namespace Squidex.Domain.Apps.Entities.History
{
- public class NotifoService : IUserEventHandler
+ public class NotifoService : IUserEvents
{
private static readonly Duration MaxAge = Duration.FromHours(12);
private readonly NotifoOptions options;
@@ -93,7 +93,7 @@ namespace Squidex.Domain.Apps.Entities.History
var userRequest = new UpsertUserDto
{
Id = user.Id,
- FullName = user.DisplayName(),
+ FullName = user.Claims.DisplayName(),
PreferredLanguage = "en",
PreferredTimezone = null,
Settings = settings,
diff --git a/backend/src/Squidex.Domain.Apps.Entities/Notifications/NotificationEmailSender.cs b/backend/src/Squidex.Domain.Apps.Entities/Notifications/NotificationEmailSender.cs
index bf22c8b94..4a43b9c8b 100644
--- a/backend/src/Squidex.Domain.Apps.Entities/Notifications/NotificationEmailSender.cs
+++ b/backend/src/Squidex.Domain.Apps.Entities/Notifications/NotificationEmailSender.cs
@@ -12,6 +12,7 @@ using Squidex.Domain.Apps.Core;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Email;
using Squidex.Log;
+using Squidex.Shared.Identity;
using Squidex.Shared.Users;
namespace Squidex.Domain.Apps.Entities.Notifications
@@ -86,7 +87,7 @@ namespace Squidex.Domain.Apps.Entities.Notifications
var vars = new TemplatesVars { Assigner = assigner, AppName = appName };
- if (user.HasConsent())
+ if (user.Claims.HasConsent())
{
return SendEmailAsync("ExistingUser",
texts.ExistingUserSubject,
@@ -152,13 +153,13 @@ namespace Squidex.Domain.Apps.Entities.Notifications
if (vars.Assigner != null)
{
text = text.Replace("$ASSIGNER_EMAIL", vars.Assigner.Email);
- text = text.Replace("$ASSIGNER_NAME", vars.Assigner.DisplayName());
+ text = text.Replace("$ASSIGNER_NAME", vars.Assigner.Claims.DisplayName());
}
if (vars.User != null)
{
text = text.Replace("$USER_EMAIL", vars.User.Email);
- text = text.Replace("$USER_NAME", vars.User.DisplayName());
+ text = text.Replace("$USER_NAME", vars.User.Claims.DisplayName());
}
if (vars.ApiCallsLimit != null)
diff --git a/backend/src/Squidex.Domain.Users/DefaultUserResolver.cs b/backend/src/Squidex.Domain.Users/DefaultUserResolver.cs
index abacbaa8e..fcfb27540 100644
--- a/backend/src/Squidex.Domain.Users/DefaultUserResolver.cs
+++ b/backend/src/Squidex.Domain.Users/DefaultUserResolver.cs
@@ -10,7 +10,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Squidex.Infrastructure;
using Squidex.Shared.Users;
@@ -34,35 +33,26 @@ namespace Squidex.Domain.Users
{
Guard.NotNullOrEmpty(email, nameof(email));
- var created = false;
-
using (var scope = serviceProvider.CreateScope())
{
- var userFactory = scope.ServiceProvider.GetRequiredService();
- var userManager = scope.ServiceProvider.GetRequiredService>();
+ var userService = scope.ServiceProvider.GetRequiredService();
try
{
- var user = userFactory.Create(email);
-
- var result = await userManager.CreateAsync(user);
-
- if (result.Succeeded)
+ var user = await userService.CreateAsync(email, new UserValues
{
- created = true;
+ Invited = invited
+ });
- var values = new UserValues { DisplayName = email, Invited = invited };
-
- await userManager.UpdateAsync(user, values);
- }
+ return (user, true);
}
catch
{
}
- var found = await userManager.FindByEmailWithClaimsAsync(email);
+ var found = await FindByIdOrEmailAsync(email);
- return (found, created);
+ return (found, false);
}
}
@@ -74,7 +64,7 @@ namespace Squidex.Domain.Users
using (var scope = serviceProvider.CreateScope())
{
- var userManager = scope.ServiceProvider.GetRequiredService>();
+ var userService = scope.ServiceProvider.GetRequiredService();
var values = new UserValues
{
@@ -84,7 +74,7 @@ namespace Squidex.Domain.Users
}
};
- await userManager.UpdateAsync(id, values);
+ await userService.UpdateAsync(id, values);
}
}
@@ -94,9 +84,9 @@ namespace Squidex.Domain.Users
using (var scope = serviceProvider.CreateScope())
{
- var userManager = scope.ServiceProvider.GetRequiredService>();
+ var userService = scope.ServiceProvider.GetRequiredService();
- return await userManager.FindByIdWithClaimsAsync(id);
+ return await userService.FindByIdAsync(id);
}
}
@@ -106,16 +96,15 @@ namespace Squidex.Domain.Users
using (var scope = serviceProvider.CreateScope())
{
- var userFactory = scope.ServiceProvider.GetRequiredService();
- var userManager = scope.ServiceProvider.GetRequiredService>();
+ var userService = scope.ServiceProvider.GetRequiredService();
- if (userFactory.IsId(idOrEmail))
+ if (idOrEmail.Contains("@"))
{
- return await userManager.FindByIdWithClaimsAsync(idOrEmail);
+ return await userService.FindByEmailAsync(idOrEmail);
}
else
{
- return await userManager.FindByEmailWithClaimsAsync(idOrEmail);
+ return await userService.FindByIdAsync(idOrEmail);
}
}
}
@@ -124,11 +113,11 @@ namespace Squidex.Domain.Users
{
using (var scope = serviceProvider.CreateScope())
{
- var userManager = scope.ServiceProvider.GetRequiredService>();
+ var userService = scope.ServiceProvider.GetRequiredService();
- var result = await userManager.QueryByEmailAsync(null);
+ var result = await userService.QueryAsync(take: int.MaxValue);
- return result.OfType().ToList();
+ return result.ToList();
}
}
@@ -138,11 +127,11 @@ namespace Squidex.Domain.Users
using (var scope = serviceProvider.CreateScope())
{
- var userManager = scope.ServiceProvider.GetRequiredService>();
+ var userService = scope.ServiceProvider.GetRequiredService();
- var result = await userManager.QueryByEmailAsync(email);
+ var result = await userService.QueryAsync(email);
- return result.OfType().ToList();
+ return result.ToList();
}
}
@@ -152,12 +141,9 @@ namespace Squidex.Domain.Users
using (var scope = serviceProvider.CreateScope())
{
- var userManager = scope.ServiceProvider.GetRequiredService>();
- var userFactory = scope.ServiceProvider.GetRequiredService();
-
- ids = ids.Where(x => userFactory.IsId(x)).ToArray();
+ var userService = scope.ServiceProvider.GetRequiredService();
- var result = await userManager.QueryByIdsAync(ids);
+ var result = await userService.QueryAsync(ids);
return result.OfType().ToDictionary(x => x.Id);
}
diff --git a/backend/src/Squidex.Domain.Users/DefaultUserService.cs b/backend/src/Squidex.Domain.Users/DefaultUserService.cs
new file mode 100644
index 000000000..15cb93954
--- /dev/null
+++ b/backend/src/Squidex.Domain.Users/DefaultUserService.cs
@@ -0,0 +1,408 @@
+// ==========================================================================
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex UG (haftungsbeschraenkt)
+// All rights reserved. Licensed under the MIT license.
+// ==========================================================================
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Identity;
+using Squidex.Infrastructure;
+using Squidex.Infrastructure.Security;
+using Squidex.Log;
+using Squidex.Shared;
+using Squidex.Shared.Identity;
+using Squidex.Shared.Users;
+
+namespace Squidex.Domain.Users
+{
+ public sealed class DefaultUserService : IUserService
+ {
+ private readonly UserManager userManager;
+ private readonly IUserFactory userFactory;
+ private readonly IEnumerable userEvents;
+ private readonly ISemanticLog log;
+
+ public DefaultUserService(UserManager userManager, IUserFactory userFactory,
+ IEnumerable userEvents, ISemanticLog log)
+ {
+ Guard.NotNull(userManager, nameof(userManager));
+ Guard.NotNull(userFactory, nameof(userFactory));
+ Guard.NotNull(userEvents, nameof(userEvents));
+ Guard.NotNull(log, nameof(log));
+
+ this.userManager = userManager;
+ this.userFactory = userFactory;
+ this.userEvents = userEvents;
+
+ this.log = log;
+ }
+
+ public async Task IsEmptyAsync()
+ {
+ var result = await QueryAsync(null, 0, 0);
+
+ return result.Total == 0;
+ }
+
+ public string GetUserId(ClaimsPrincipal user)
+ {
+ Guard.NotNull(user, nameof(user));
+
+ return userManager.GetUserId(user);
+ }
+
+ public async Task> QueryAsync(IEnumerable ids)
+ {
+ Guard.NotNull(ids, nameof(ids));
+
+ ids = ids.Where(userFactory.IsId);
+
+ if (!ids.Any())
+ {
+ return ResultList.CreateFrom(0);
+ }
+
+ var users = userManager.Users.Where(x => ids.Contains(x.Id)).ToList();
+
+ var resolved = await ResolveAsync(users);
+
+ return ResultList.Create(users.Count, resolved);
+ }
+
+ public async Task> QueryAsync(string? query, int take, int skip)
+ {
+ IQueryable QueryUsers(string? email = null)
+ {
+ var result = userManager.Users;
+
+ if (!string.IsNullOrWhiteSpace(email))
+ {
+ var normalizedEmail = userManager.NormalizeEmail(email);
+
+ result = result.Where(x => x.NormalizedEmail.Contains(normalizedEmail));
+ }
+
+ return result;
+ }
+
+ var userItems = QueryUsers(query).Take(take).Skip(skip).ToList();
+ var userTotal = QueryUsers(query).LongCount();
+
+ var resolved = await ResolveAsync(userItems);
+
+ return ResultList.Create(userTotal, resolved);
+ }
+
+ public Task> GetLoginsAsync(IUser user)
+ {
+ Guard.NotNull(user, nameof(user));
+
+ return userManager.GetLoginsAsync((IdentityUser)user.Identity);
+ }
+
+ public Task HasPasswordAsync(IUser user)
+ {
+ Guard.NotNull(user, nameof(user));
+
+ return userManager.HasPasswordAsync((IdentityUser)user.Identity);
+ }
+
+ public async Task FindByLoginAsync(string provider, string key)
+ {
+ Guard.NotNullOrEmpty(provider, nameof(provider));
+
+ var user = await userManager.FindByLoginAsync(provider, key);
+
+ return await ResolveOptionalAsync(user);
+ }
+
+ public async Task FindByEmailAsync(string email)
+ {
+ Guard.NotNullOrEmpty(email, nameof(email));
+
+ var user = await userManager.FindByEmailAsync(email);
+
+ return await ResolveOptionalAsync(user);
+ }
+
+ public async Task GetAsync(ClaimsPrincipal principal)
+ {
+ Guard.NotNull(principal, nameof(principal));
+
+ var user = await userManager.GetUserAsync(principal);
+
+ return await ResolveOptionalAsync(user);
+ }
+
+ public async Task FindByIdAsync(string id)
+ {
+ if (!userFactory.IsId(id))
+ {
+ return null;
+ }
+
+ var user = await userManager.FindByIdAsync(id);
+
+ return await ResolveOptionalAsync(user);
+ }
+
+ public async Task CreateAsync(string email, UserValues? values = null, bool lockAutomatically = false)
+ {
+ Guard.NotNullOrEmpty(email, nameof(email));
+
+ var isFirst = !userManager.Users.Any();
+
+ var user = userFactory.Create(email);
+
+ try
+ {
+ await userManager.CreateAsync(user).Throw(log);
+
+ values ??= new UserValues();
+
+ if (string.IsNullOrWhiteSpace(values.DisplayName))
+ {
+ values.DisplayName = email;
+ }
+
+ if (isFirst)
+ {
+ var permissions = values.Permissions?.ToIds().ToList() ?? new List();
+
+ permissions.Add(Permissions.Admin);
+
+ values.Permissions = new PermissionSet(permissions);
+ }
+
+ await userManager.SyncClaims(user, values).Throw(log);
+
+ if (!string.IsNullOrWhiteSpace(values.Password))
+ {
+ await userManager.AddPasswordAsync(user, values.Password).Throw(log);
+ }
+
+ if (!isFirst && lockAutomatically)
+ {
+ await userManager.SetLockoutEndDateAsync(user, LockoutDate()).Throw(log);
+ }
+ }
+ catch (Exception)
+ {
+ try
+ {
+ if (userFactory.IsId(user.Id))
+ {
+ await userManager.DeleteAsync(user);
+ }
+ }
+ catch (Exception ex2)
+ {
+ log.LogError(ex2, w => w
+ .WriteProperty("action", "CleanupUser")
+ .WriteProperty("status", "Failed"));
+ }
+
+ throw;
+ }
+
+ var resolved = await ResolveAsync(user);
+
+ foreach (var @events in userEvents)
+ {
+ @events.OnUserRegistered(resolved);
+ }
+
+ if (HasConsentGiven(values, null!))
+ {
+ foreach (var @events in userEvents)
+ {
+ @events.OnConsentGiven(resolved);
+ }
+ }
+
+ return resolved;
+ }
+
+ public Task SetPasswordAsync(string id, string password, string? oldPassword)
+ {
+ Guard.NotNullOrEmpty(id, nameof(id));
+
+ return ForUserAsync(id, async user =>
+ {
+ if (await userManager.HasPasswordAsync(user))
+ {
+ await userManager.ChangePasswordAsync(user, oldPassword!, password).Throw(log);
+ }
+ else
+ {
+ await userManager.AddPasswordAsync(user, password).Throw(log);
+ }
+ });
+ }
+
+ public async Task UpdateAsync(string id, UserValues values)
+ {
+ Guard.NotNullOrEmpty(id, nameof(id));
+ Guard.NotNull(values, nameof(values));
+
+ var user = await GetUserAsync(id);
+
+ var oldUser = await ResolveAsync(user);
+
+ if (!string.IsNullOrWhiteSpace(values.Email) && values.Email != user.Email)
+ {
+ await userManager.SetEmailAsync(user, values.Email).Throw(log);
+ await userManager.SetUserNameAsync(user, values.Email).Throw(log);
+ }
+
+ await userManager.SyncClaims(user, values).Throw(log);
+
+ if (!string.IsNullOrWhiteSpace(values.Password))
+ {
+ if (await userManager.HasPasswordAsync(user))
+ {
+ await userManager.RemovePasswordAsync(user).Throw(log);
+ }
+
+ await userManager.AddPasswordAsync(user, values.Password).Throw(log);
+ }
+
+ var resolved = await ResolveAsync(user);
+
+ foreach (var @events in userEvents)
+ {
+ @events.OnUserUpdated(resolved);
+ }
+
+ if (HasConsentGiven(values, oldUser))
+ {
+ foreach (var @events in userEvents)
+ {
+ @events.OnConsentGiven(resolved);
+ }
+ }
+
+ return resolved;
+ }
+
+ public Task LockAsync(string id)
+ {
+ Guard.NotNullOrEmpty(id, nameof(id));
+
+ return ForUserAsync(id, user => userManager.SetLockoutEndDateAsync(user, LockoutDate()).Throw(log));
+ }
+
+ public Task UnlockAsync(string id)
+ {
+ Guard.NotNullOrEmpty(id, nameof(id));
+
+ return ForUserAsync(id, user => userManager.SetLockoutEndDateAsync(user, null).Throw(log));
+ }
+
+ public Task AddLoginAsync(string id, ExternalLoginInfo externalLogin)
+ {
+ Guard.NotNullOrEmpty(id, nameof(id));
+
+ return ForUserAsync(id, user => userManager.AddLoginAsync(user, externalLogin).Throw(log));
+ }
+
+ public Task RemoveLoginAsync(string id, string loginProvider, string providerKey)
+ {
+ Guard.NotNullOrEmpty(id, nameof(id));
+
+ return ForUserAsync(id, user => userManager.RemoveLoginAsync(user, loginProvider, providerKey).Throw(log));
+ }
+
+ public async Task DeleteAsync(string id)
+ {
+ Guard.NotNullOrEmpty(id, nameof(id));
+
+ var user = await GetUserAsync(id);
+
+ var resolved = await ResolveAsync(user);
+
+ await userManager.DeleteAsync(user).Throw(log);
+
+ foreach (var @events in userEvents)
+ {
+ @events.OnUserDeleted(resolved);
+ }
+ }
+
+ private async Task ForUserAsync(string id, Func action)
+ {
+ var user = await GetUserAsync(id);
+
+ await action(user);
+
+ return await ResolveAsync(user);
+ }
+
+ private async Task GetUserAsync(string id)
+ {
+ if (!userFactory.IsId(id))
+ {
+ throw new DomainObjectNotFoundException(id);
+ }
+
+ var user = await userManager.FindByIdAsync(id);
+
+ if (user == null)
+ {
+ throw new DomainObjectNotFoundException(id);
+ }
+
+ return user;
+ }
+
+ private Task ResolveAsync(IEnumerable users)
+ {
+ return Task.WhenAll(users.Select(async user =>
+ {
+ return await ResolveAsync(user);
+ }));
+ }
+
+ private async Task ResolveAsync(IdentityUser user)
+ {
+ var claims = await userManager.GetClaimsAsync(user);
+
+ if (!claims.Any(x => string.Equals(x.Type, SquidexClaimTypes.DisplayName, StringComparison.OrdinalIgnoreCase)))
+ {
+ claims.Add(new Claim(SquidexClaimTypes.DisplayName, user.Email));
+ }
+
+ return new UserWithClaims(user, claims.ToList());
+ }
+
+ private async Task ResolveOptionalAsync(IdentityUser? user)
+ {
+ if (user == null)
+ {
+ return null;
+ }
+
+ return await ResolveAsync(user);
+ }
+
+ private static bool HasConsentGiven(UserValues values, IUser? oldUser)
+ {
+ if (values.Consent == true && oldUser?.Claims.HasConsent() != true)
+ {
+ return true;
+ }
+
+ return values.ConsentForEmails == true && oldUser?.Claims.HasConsentForEmails() != true;
+ }
+
+ private static DateTimeOffset LockoutDate()
+ {
+ return DateTimeOffset.UtcNow.AddYears(100);
+ }
+ }
+}
diff --git a/backend/src/Squidex.Domain.Users/IUserEventHandler.cs b/backend/src/Squidex.Domain.Users/IUserEventHandler.cs
deleted file mode 100644
index 0bf9f8a48..000000000
--- a/backend/src/Squidex.Domain.Users/IUserEventHandler.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// ==========================================================================
-// Squidex Headless CMS
-// ==========================================================================
-// Copyright (c) Squidex UG (haftungsbeschraenkt)
-// All rights reserved. Licensed under the MIT license.
-// ==========================================================================
-
-using Squidex.Shared.Users;
-
-namespace Squidex.Domain.Users
-{
- public interface IUserEventHandler
- {
- void OnUserRegistered(IUser user)
- {
- }
-
- void OnUserUpdated(IUser user)
- {
- }
-
- void OnConsentGiven(IUser user)
- {
- }
- }
-}
diff --git a/backend/src/Squidex.Domain.Users/IUserEvents.cs b/backend/src/Squidex.Domain.Users/IUserEvents.cs
index 8383b7770..26f51ea75 100644
--- a/backend/src/Squidex.Domain.Users/IUserEvents.cs
+++ b/backend/src/Squidex.Domain.Users/IUserEvents.cs
@@ -11,10 +11,20 @@ namespace Squidex.Domain.Users
{
public interface IUserEvents
{
- void OnUserRegistered(IUser user);
+ void OnUserRegistered(IUser user)
+ {
+ }
- void OnUserUpdated(IUser user);
+ void OnUserUpdated(IUser user)
+ {
+ }
- void OnConsentGiven(IUser user);
+ void OnUserDeleted(IUser user)
+ {
+ }
+
+ void OnConsentGiven(IUser user)
+ {
+ }
}
}
diff --git a/backend/src/Squidex.Domain.Users/IUserService.cs b/backend/src/Squidex.Domain.Users/IUserService.cs
new file mode 100644
index 000000000..d70dc8cc8
--- /dev/null
+++ b/backend/src/Squidex.Domain.Users/IUserService.cs
@@ -0,0 +1,55 @@
+// ==========================================================================
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex UG (haftungsbeschraenkt)
+// All rights reserved. Licensed under the MIT license.
+// ==========================================================================
+
+using System.Collections.Generic;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Identity;
+using Squidex.Infrastructure;
+using Squidex.Shared.Users;
+
+namespace Squidex.Domain.Users
+{
+ public interface IUserService
+ {
+ Task> QueryAsync(IEnumerable ids);
+
+ Task> QueryAsync(string? query = null, int take = 10, int skip = 0);
+
+ string GetUserId(ClaimsPrincipal user);
+
+ Task> GetLoginsAsync(IUser user);
+
+ Task HasPasswordAsync(IUser user);
+
+ Task IsEmptyAsync();
+
+ Task CreateAsync(string email, UserValues? values = null, bool lockAutomatically = false);
+
+ Task GetAsync(ClaimsPrincipal principal);
+
+ Task FindByEmailAsync(string email);
+
+ Task FindByIdAsync(string id);
+
+ Task FindByLoginAsync(string provider, string key);
+
+ Task SetPasswordAsync(string id, string password, string? oldPassword = null);
+
+ Task AddLoginAsync(string id, ExternalLoginInfo externalLogin);
+
+ Task RemoveLoginAsync(string id, string loginProvider, string providerKey);
+
+ Task LockAsync(string id);
+
+ Task UnlockAsync(string id);
+
+ Task UpdateAsync(string id, UserValues values);
+
+ Task DeleteAsync(string id);
+ }
+}
diff --git a/backend/src/Squidex.Domain.Users/UserEvents.cs b/backend/src/Squidex.Domain.Users/UserEvents.cs
deleted file mode 100644
index 4bf14785a..000000000
--- a/backend/src/Squidex.Domain.Users/UserEvents.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-// ==========================================================================
-// Squidex Headless CMS
-// ==========================================================================
-// Copyright (c) Squidex UG (haftungsbeschränkt)
-// All rights reserved. Licensed under the MIT license.
-// ==========================================================================
-
-using System.Collections.Generic;
-using Squidex.Infrastructure;
-using Squidex.Shared.Users;
-
-namespace Squidex.Domain.Users
-{
- public sealed class UserEvents : IUserEvents
- {
- private readonly IEnumerable userEventHandlers;
-
- public UserEvents(IEnumerable userEventHandlers)
- {
- Guard.NotNull(userEventHandlers, nameof(userEventHandlers));
-
- this.userEventHandlers = userEventHandlers;
- }
-
- public void OnUserRegistered(IUser user)
- {
- foreach (var handler in userEventHandlers)
- {
- handler.OnUserRegistered(user);
- }
- }
-
- public void OnUserUpdated(IUser user)
- {
- foreach (var handler in userEventHandlers)
- {
- handler.OnUserUpdated(user);
- }
- }
-
- public void OnConsentGiven(IUser user)
- {
- foreach (var handler in userEventHandlers)
- {
- handler.OnConsentGiven(user);
- }
- }
- }
-}
diff --git a/backend/src/Squidex.Domain.Users/UserManagerExtensions.cs b/backend/src/Squidex.Domain.Users/UserManagerExtensions.cs
index c4f39e65e..d30be87c5 100644
--- a/backend/src/Squidex.Domain.Users/UserManagerExtensions.cs
+++ b/backend/src/Squidex.Domain.Users/UserManagerExtensions.cs
@@ -9,263 +9,158 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
+using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
-using Squidex.Infrastructure;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
+using Squidex.Log;
+using Squidex.Shared.Identity;
namespace Squidex.Domain.Users
{
- public static class UserManagerExtensions
+ internal static class UserManagerExtensions
{
- public static async Task GetUserWithClaimsAsync(this UserManager userManager, ClaimsPrincipal principal)
+ public static async Task Throw(this Task task, ISemanticLog log)
{
- if (principal == null)
- {
- return null;
- }
+ var result = await task;
- var user = await userManager.FindByIdWithClaimsAsync(userManager.GetUserId(principal));
-
- return user;
- }
-
- public static async Task ResolveUserAsync(this UserManager userManager, IdentityUser user)
- {
- if (user == null)
+ static string Localize(IdentityError error)
{
- return null;
+ if (!string.IsNullOrWhiteSpace(error.Code))
+ {
+ return T.Get($"dotnet_identity_{error.Code}", error.Description);
+ }
+ else
+ {
+ return error.Description;
+ }
}
- var claims = await userManager.GetClaimsAsync(user);
-
- return new UserWithClaims(user, claims);
- }
-
- public static async Task FindByIdWithClaimsAsync(this UserManager userManager, string id)
- {
- if (id == null)
+ if (!result.Succeeded)
{
- return null;
- }
+ var errorMessageBuilder = new StringBuilder();
- var user = await userManager.FindByIdAsync(id);
-
- return await userManager.ResolveUserAsync(user);
- }
-
- public static async Task FindByEmailWithClaimsAsync(this UserManager userManager, string email)
- {
- if (email == null)
- {
- return null;
- }
+ foreach (var error in result.Errors)
+ {
+ errorMessageBuilder.Append(error.Code);
+ errorMessageBuilder.Append(": ");
+ errorMessageBuilder.AppendLine(error.Description);
+ }
- var user = await userManager.FindByEmailAsync(email);
+ var errorMessage = errorMessageBuilder.ToString();
- return await userManager.ResolveUserAsync(user);
- }
+ log.LogError(errorMessage, (ctx, w) => w
+ .WriteProperty("action", "IdentityOperation")
+ .WriteProperty("status", "Failed")
+ .WriteProperty("message", ctx));
- public static async Task FindByLoginWithClaimsAsync(this UserManager userManager, string loginProvider, string providerKey)
- {
- if (loginProvider == null || providerKey == null)
- {
- return null;
+ throw new ValidationException(result.Errors.Select(x => new ValidationError(Localize(x))).ToList());
}
-
- var user = await userManager.FindByLoginAsync(loginProvider, providerKey);
-
- return await userManager.ResolveUserAsync(user);
- }
-
- public static Task CountByEmailAsync(this UserManager userManager, string? email = null)
- {
- var count = QueryUsers(userManager, email).LongCount();
-
- return Task.FromResult(count);
- }
-
- public static async Task> QueryByIdsAync(this UserManager userManager, string[] ids)
- {
- var users = userManager.Users.Where(x => ids.Contains(x.Id)).ToList();
-
- var result = await userManager.ResolveUsersAsync(users);
-
- return result.ToList();
}
- public static async Task> QueryByEmailAsync(this UserManager userManager, string? email = null, int take = 10, int skip = 0)
+ public static async Task SyncClaims(this UserManager userManager, IdentityUser user, UserValues values)
{
- var users = QueryUsers(userManager, email).Skip(skip).Take(take).ToList();
+ var current = await userManager.GetClaimsAsync(user);
- var result = await userManager.ResolveUsersAsync(users);
+ var claimsToRemove = new List();
+ var claimsToAdd = new List();
- return result.ToList();
- }
-
- public static Task ResolveUsersAsync(this UserManager userManager, IEnumerable users)
- {
- return Task.WhenAll(users.Select(async user =>
+ void RemoveClaims(Func predicate)
{
- return (await userManager.ResolveUserAsync(user))!;
- }));
- }
-
- public static IQueryable QueryUsers(UserManager userManager, string? email = null)
- {
- var result = userManager.Users;
+ claimsToAdd.RemoveAll(x => predicate(x));
+ claimsToRemove.AddRange(current.Where(predicate));
+ }
- if (!string.IsNullOrWhiteSpace(email))
+ void AddClaim(string type, string value)
{
- var normalizedEmail = userManager.NormalizeEmail(email);
-
- result = result.Where(x => x.NormalizedEmail.Contains(normalizedEmail));
+ claimsToAdd.Add(new Claim(type, value));
}
- return result;
- }
-
- public static async Task CreateAsync(this UserManager userManager, IUserFactory factory, UserValues values)
- {
- var user = factory.Create(values.Email);
-
- try
+ void SyncString(string type, string? value)
{
- await DoChecked(() => userManager.CreateAsync(user));
- await DoChecked(() => values.SyncClaims(userManager, user));
-
- if (!string.IsNullOrWhiteSpace(values.Password))
+ if (value != null)
{
- await DoChecked(() => userManager.AddPasswordAsync(user, values.Password));
- }
- }
- catch
- {
- await userManager.DeleteAsync(user);
+ RemoveClaims(x => x.Type == type);
- throw;
+ if (!string.IsNullOrWhiteSpace(value))
+ {
+ AddClaim(type, value);
+ }
+ }
}
- return (await userManager.ResolveUserAsync(user))!;
- }
-
- public static async Task UpdateAsync(this UserManager userManager, string id, UserValues values)
- {
- var user = await userManager.FindByIdAsync(id);
-
- if (user == null)
+ void SyncBoolean(string type, bool? value)
{
- throw new DomainObjectNotFoundException(id);
+ if (value != null)
+ {
+ RemoveClaims(x => x.Type == type);
+
+ if (value == true)
+ {
+ AddClaim(type, value.ToString()!);
+ }
+ }
}
- await UpdateAsync(userManager, user, values);
+ SyncString(SquidexClaimTypes.ClientSecret, values.ClientSecret);
+ SyncString(SquidexClaimTypes.DisplayName, values.DisplayName);
+ SyncString(SquidexClaimTypes.PictureUrl, values.PictureUrl);
- return (await userManager.ResolveUserAsync(user))!;
- }
+ SyncBoolean(SquidexClaimTypes.Hidden, values.Hidden);
+ SyncBoolean(SquidexClaimTypes.Invited, values.Invited);
+ SyncBoolean(SquidexClaimTypes.Consent, values.Consent);
+ SyncBoolean(SquidexClaimTypes.ConsentForEmails, values.ConsentForEmails);
- public static Task GenerateClientSecretAsync(this UserManager userManager, IdentityUser user)
- {
- var update = new UserValues
+ if (values.Permissions != null)
{
- ClientSecret = RandomHash.New()
- };
+ RemoveClaims(x => x.Type == SquidexClaimTypes.Permissions);
- return update.SyncClaims(userManager, user);
- }
+ foreach (var permission in values.Permissions)
+ {
+ AddClaim(SquidexClaimTypes.Permissions, permission.Id);
+ }
+ }
- public static async Task UpdateSafeAsync(this UserManager userManager, IdentityUser user, UserValues values)
- {
- try
+ if (values.Properties != null)
{
- await userManager.UpdateAsync(user, values);
+ RemoveClaims(x => x.Type.StartsWith(SquidexClaimTypes.CustomPrefix, StringComparison.OrdinalIgnoreCase));
- return IdentityResult.Success;
- }
- catch (ValidationException ex)
- {
- return IdentityResult.Failed(ex.Errors.Select(x => new IdentityError { Description = x.Message }).ToArray());
+ foreach (var (name, value) in values.Properties)
+ {
+ AddClaim($"{SquidexClaimTypes.CustomPrefix}:{name}", value);
+ }
}
- }
- public static async Task UpdateAsync(this UserManager userManager, IdentityUser user, UserValues values)
- {
- Guard.NotNull(user, nameof(user));
- Guard.NotNull(values, nameof(values));
-
- if (!string.IsNullOrWhiteSpace(values.Email) && values.Email != user.Email)
+ if (values.CustomClaims != null)
{
- await DoChecked(() => userManager.SetEmailAsync(user, values.Email));
- await DoChecked(() => userManager.SetUserNameAsync(user, values.Email));
- }
-
- await DoChecked(() => values.SyncClaims(userManager, user));
+ foreach (var group in values.CustomClaims.GroupBy(x => x.Type))
+ {
+ RemoveClaims(x => x.Type == group.Key);
- if (!string.IsNullOrWhiteSpace(values.Password))
- {
- await DoChecked(() => userManager.RemovePasswordAsync(user));
- await DoChecked(() => userManager.AddPasswordAsync(user, values.Password));
+ foreach (var claim in group)
+ {
+ AddClaim(claim.Type, claim.Value);
+ }
+ }
}
- }
-
- public static async Task LockAsync(this UserManager userManager, string id)
- {
- var user = await userManager.FindByIdAsync(id);
- if (user == null)
+ if (claimsToRemove.Count > 0)
{
- throw new DomainObjectNotFoundException(id);
- }
-
- await DoChecked(() => userManager.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.AddYears(100)));
-
- return (await userManager.ResolveUserAsync(user))!;
- }
+ var result = await userManager.RemoveClaimsAsync(user, claimsToRemove);
- public static async Task UnlockAsync(this UserManager userManager, string id)
- {
- var user = await userManager.FindByIdAsync(id);
-
- if (user == null)
- {
- throw new DomainObjectNotFoundException(id);
+ if (!result.Succeeded)
+ {
+ return result;
+ }
}
- await DoChecked(() => userManager.SetLockoutEndDateAsync(user, null));
-
- return (await userManager.ResolveUserAsync(user))!;
- }
-
- private static async Task DoChecked(Func> action)
- {
- var result = await action();
-
- if (!result.Succeeded)
+ if (claimsToAdd.Count > 0)
{
- throw new ValidationException(result.Errors.Select(x => new ValidationError(x.Localize())).ToList());
+ return await userManager.AddClaimsAsync(user, claimsToAdd);
}
- }
- public static Task SyncClaims(this UserManager userManager, IdentityUser user, UserValues values)
- {
- return values.SyncClaims(userManager, user);
- }
-
- public static string Localize(this IdentityResult result)
- {
- return string.Join(". ", result.Errors.Select(x => x.Localize()));
- }
-
- public static string Localize(this IdentityError error)
- {
- if (!string.IsNullOrWhiteSpace(error.Code))
- {
- return T.Get($"dotnet_identity_{error.Code}", error.Description);
- }
- else
- {
- return error.Description;
- }
+ return IdentityResult.Success;
}
}
}
diff --git a/backend/src/Squidex.Domain.Users/UserValues.cs b/backend/src/Squidex.Domain.Users/UserValues.cs
index f1bd1a763..5726d02d8 100644
--- a/backend/src/Squidex.Domain.Users/UserValues.cs
+++ b/backend/src/Squidex.Domain.Users/UserValues.cs
@@ -5,14 +5,9 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
-using System;
using System.Collections.Generic;
-using System.Linq;
using System.Security.Claims;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Identity;
using Squidex.Infrastructure.Security;
-using Squidex.Shared.Identity;
namespace Squidex.Domain.Users
{
@@ -41,109 +36,5 @@ namespace Squidex.Domain.Users
public List? CustomClaims { get; set; }
public List<(string Name, string Value)>? Properties { get; set; }
-
- internal async Task SyncClaims(UserManager userManager, IdentityUser user)
- {
- var current = await userManager.GetClaimsAsync(user);
-
- var claimsToRemove = new List();
- var claimsToAdd = new List();
-
- void RemoveClaims(Func predicate)
- {
- claimsToAdd.RemoveAll(x => predicate(x));
- claimsToRemove.AddRange(current.Where(predicate));
- }
-
- void AddClaim(string type, string value)
- {
- claimsToAdd.Add(new Claim(type, value));
- }
-
- void SyncString(string type, string? value)
- {
- if (value != null)
- {
- RemoveClaims(x => x.Type == type);
-
- if (!string.IsNullOrWhiteSpace(value))
- {
- AddClaim(type, value);
- }
- }
- }
-
- void SyncBoolean(string type, bool? value)
- {
- if (value != null)
- {
- RemoveClaims(x => x.Type == type);
-
- if (value == true)
- {
- AddClaim(type, value.ToString()!);
- }
- }
- }
-
- SyncString(SquidexClaimTypes.ClientSecret, ClientSecret);
- SyncString(SquidexClaimTypes.DisplayName, DisplayName);
- SyncString(SquidexClaimTypes.PictureUrl, PictureUrl);
-
- SyncBoolean(SquidexClaimTypes.Hidden, Hidden);
- SyncBoolean(SquidexClaimTypes.Invited, Invited);
- SyncBoolean(SquidexClaimTypes.Consent, Consent);
- SyncBoolean(SquidexClaimTypes.ConsentForEmails, ConsentForEmails);
-
- if (Permissions != null)
- {
- RemoveClaims(x => x.Type == SquidexClaimTypes.Permissions);
-
- foreach (var permission in Permissions)
- {
- AddClaim(SquidexClaimTypes.Permissions, permission.Id);
- }
- }
-
- if (Properties != null)
- {
- RemoveClaims(x => x.Type.StartsWith(SquidexClaimTypes.CustomPrefix, StringComparison.OrdinalIgnoreCase));
-
- foreach (var (name, value) in Properties)
- {
- AddClaim($"{SquidexClaimTypes.CustomPrefix}:{name}", value);
- }
- }
-
- if (CustomClaims != null)
- {
- foreach (var group in CustomClaims.GroupBy(x => x.Type))
- {
- RemoveClaims(x => x.Type == group.Key);
-
- foreach (var claim in group)
- {
- AddClaim(claim.Type, claim.Value);
- }
- }
- }
-
- if (claimsToRemove.Count > 0)
- {
- var result = await userManager.RemoveClaimsAsync(user, claimsToRemove);
-
- if (!result.Succeeded)
- {
- return result;
- }
- }
-
- if (claimsToAdd.Count > 0)
- {
- return await userManager.AddClaimsAsync(user, claimsToAdd);
- }
-
- return IdentityResult.Success;
- }
}
}
diff --git a/backend/src/Squidex.Domain.Users/UserWithClaims.cs b/backend/src/Squidex.Domain.Users/UserWithClaims.cs
index 541c42cd1..b376b1c11 100644
--- a/backend/src/Squidex.Domain.Users/UserWithClaims.cs
+++ b/backend/src/Squidex.Domain.Users/UserWithClaims.cs
@@ -7,20 +7,16 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Security.Claims;
using Microsoft.AspNetCore.Identity;
-using Squidex.Infrastructure;
using Squidex.Shared.Users;
namespace Squidex.Domain.Users
{
- public sealed class UserWithClaims : IUser
+ internal sealed class UserWithClaims : IUser
{
public IdentityUser Identity { get; }
- public List Claims { get; }
-
public string Id
{
get { return Identity.Id; }
@@ -36,19 +32,15 @@ namespace Squidex.Domain.Users
get { return Identity.LockoutEnd > DateTime.UtcNow; }
}
- IReadOnlyList IUser.Claims
- {
- get { return Claims; }
- }
+ public IReadOnlyList Claims { get; }
- public UserWithClaims(IdentityUser user, IEnumerable claims)
- {
- Guard.NotNull(user, nameof(user));
- Guard.NotNull(claims, nameof(claims));
+ object IUser.Identity => Identity;
+ public UserWithClaims(IdentityUser user, IReadOnlyList claims)
+ {
Identity = user;
- Claims = claims.ToList();
+ Claims = claims;
}
}
}
diff --git a/backend/src/Squidex.Infrastructure/Validation/LocalizedCompareAttribute.cs b/backend/src/Squidex.Infrastructure/Validation/LocalizedCompareAttribute.cs
index 766b11e31..13e3fdfde 100644
--- a/backend/src/Squidex.Infrastructure/Validation/LocalizedCompareAttribute.cs
+++ b/backend/src/Squidex.Infrastructure/Validation/LocalizedCompareAttribute.cs
@@ -24,7 +24,7 @@ namespace Squidex.Infrastructure.Validation
var other = T.Get($"common.{OtherProperty.ToCamelCase()}", OtherProperty);
- return T.Get("annotations_Compare", base.FormatErrorMessage(name), new { property, other });
+ return T.Get("annotations_Compare", base.FormatErrorMessage(name), new { name = property, other });
}
}
}
diff --git a/backend/src/Squidex.Infrastructure/Validation/LocalizedEmailAddressAttribute.cs b/backend/src/Squidex.Infrastructure/Validation/LocalizedEmailAddressAttribute.cs
index 5c6e37e0b..15bc81a59 100644
--- a/backend/src/Squidex.Infrastructure/Validation/LocalizedEmailAddressAttribute.cs
+++ b/backend/src/Squidex.Infrastructure/Validation/LocalizedEmailAddressAttribute.cs
@@ -24,7 +24,7 @@ namespace Squidex.Infrastructure.Validation
{
var property = T.Get($"common.{name.ToCamelCase()}", name);
- return T.Get("annotations_EmailAddress", base.FormatErrorMessage(name), new { property });
+ return T.Get("annotations_EmailAddress", base.FormatErrorMessage(name), new { name = property });
}
}
}
diff --git a/backend/src/Squidex.Infrastructure/Validation/LocalizedRangeAttribute.cs b/backend/src/Squidex.Infrastructure/Validation/LocalizedRangeAttribute.cs
index ca3e41fd6..5e3b7a483 100644
--- a/backend/src/Squidex.Infrastructure/Validation/LocalizedRangeAttribute.cs
+++ b/backend/src/Squidex.Infrastructure/Validation/LocalizedRangeAttribute.cs
@@ -32,7 +32,7 @@ namespace Squidex.Infrastructure.Validation
var min = Minimum;
var max = Maximum;
- return T.Get("annotations_Range", base.FormatErrorMessage(name), new { property, min, max });
+ return T.Get("annotations_Range", base.FormatErrorMessage(name), new { name = property, min, max });
}
}
}
diff --git a/backend/src/Squidex.Infrastructure/Validation/LocalizedRegularExpressionAttribute.cs b/backend/src/Squidex.Infrastructure/Validation/LocalizedRegularExpressionAttribute.cs
index 174ef3ced..cef55b31c 100644
--- a/backend/src/Squidex.Infrastructure/Validation/LocalizedRegularExpressionAttribute.cs
+++ b/backend/src/Squidex.Infrastructure/Validation/LocalizedRegularExpressionAttribute.cs
@@ -24,7 +24,7 @@ namespace Squidex.Infrastructure.Validation
{
var property = T.Get($"common.{name.ToCamelCase()}", name);
- return T.Get("annotations_RegularExpression", base.FormatErrorMessage(name), new { property });
+ return T.Get("annotations_RegularExpression", base.FormatErrorMessage(name), new { name = property });
}
}
}
diff --git a/backend/src/Squidex.Infrastructure/Validation/LocalizedRequiredAttribute.cs b/backend/src/Squidex.Infrastructure/Validation/LocalizedRequiredAttribute.cs
index 50b0c334b..5fa2d84da 100644
--- a/backend/src/Squidex.Infrastructure/Validation/LocalizedRequiredAttribute.cs
+++ b/backend/src/Squidex.Infrastructure/Validation/LocalizedRequiredAttribute.cs
@@ -19,7 +19,7 @@ namespace Squidex.Infrastructure.Validation
{
var property = T.Get($"common.{name.ToCamelCase()}", name);
- return T.Get("annotations_Required", base.FormatErrorMessage(name), new { property });
+ return T.Get("annotations_Required", base.FormatErrorMessage(name), new { name = property });
}
}
}
diff --git a/backend/src/Squidex.Infrastructure/Validation/LocalizedStringLengthAttribute.cs b/backend/src/Squidex.Infrastructure/Validation/LocalizedStringLengthAttribute.cs
index 951cf1c3a..f610dda35 100644
--- a/backend/src/Squidex.Infrastructure/Validation/LocalizedStringLengthAttribute.cs
+++ b/backend/src/Squidex.Infrastructure/Validation/LocalizedStringLengthAttribute.cs
@@ -25,7 +25,7 @@ namespace Squidex.Infrastructure.Validation
var min = MinimumLength;
var max = MaximumLength;
- var args = new { property, min, max };
+ var args = new { name = property, min, max };
if (min > 0)
{
diff --git a/backend/src/Squidex.Shared/Identity/ClaimsPrincipalExtensions.cs b/backend/src/Squidex.Shared/Identity/ClaimsPrincipalExtensions.cs
deleted file mode 100644
index d4f8ee4d8..000000000
--- a/backend/src/Squidex.Shared/Identity/ClaimsPrincipalExtensions.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// ==========================================================================
-// Squidex Headless CMS
-// ==========================================================================
-// Copyright (c) Squidex UG (haftungsbeschraenkt)
-// All rights reserved. Licensed under the MIT license.
-// ==========================================================================
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Claims;
-using Squidex.Infrastructure.Security;
-
-namespace Squidex.Shared.Identity
-{
- public static class ClaimsPrincipalExtensions
- {
- public static void SetDisplayName(this ClaimsIdentity identity, string displayName)
- {
- identity.AddClaim(new Claim(SquidexClaimTypes.DisplayName, displayName));
- }
-
- public static void SetPictureUrl(this ClaimsIdentity identity, string pictureUrl)
- {
- identity.AddClaim(new Claim(SquidexClaimTypes.PictureUrl, pictureUrl));
- }
-
- public static PermissionSet Permissions(this ClaimsPrincipal principal)
- {
- return new PermissionSet(principal.Claims
- .Where(x =>
- (x.Type == SquidexClaimTypes.Permissions ||
- x.Type == SquidexClaimTypes.PermissionsClient) &&
- !string.IsNullOrWhiteSpace(x.Value))
- .Select(x => new Permission(x.Value)));
- }
-
- public static IEnumerable GetSquidexClaims(this ClaimsPrincipal principal)
- {
- return principal.Claims
- .Where(x =>
- (x.Type.StartsWith(SquidexClaimTypes.Prefix, StringComparison.Ordinal) ||
- x.Type.StartsWith(SquidexClaimTypes.PrefixClient, StringComparison.Ordinal)) &&
- !string.IsNullOrWhiteSpace(x.Value));
- }
- }
-}
diff --git a/backend/src/Squidex.Shared/Identity/SquidexClaimTypes.cs b/backend/src/Squidex.Shared/Identity/SquidexClaimTypes.cs
index c2594c52e..38d4ea32a 100644
--- a/backend/src/Squidex.Shared/Identity/SquidexClaimTypes.cs
+++ b/backend/src/Squidex.Shared/Identity/SquidexClaimTypes.cs
@@ -9,31 +9,25 @@ namespace Squidex.Shared.Identity
{
public static class SquidexClaimTypes
{
- public static readonly string DisplayName = "urn:squidex:name";
-
- public static readonly string PictureUrl = "urn:squidex:picture";
-
- public static readonly string NotifoKey = "urn:squidex:notifo";
+ public static readonly string ClientSecret = "urn:squidex:clientSecret";
public static readonly string Consent = "urn:squidex:consent";
public static readonly string ConsentForEmails = "urn:squidex:consent:emails";
+ public static readonly string CustomPrefix = "urn:squidex:custom";
+
+ public static readonly string DisplayName = "urn:squidex:name";
+
public static readonly string Hidden = "urn:squidex:hidden";
public static readonly string Invited = "urn:squidex:invited";
- public static readonly string CustomPrefix = "urn:squidex:custom";
+ public static readonly string NotifoKey = "urn:squidex:notifo";
public static readonly string Permissions = "urn:squidex:permissions";
- public static readonly string PermissionsClient = "client_urn:squidex:permissions";
-
- public static readonly string ClientSecret = "urn:squidex:clientSecret";
-
- public static readonly string Prefix = "urn:squidex:";
-
- public static readonly string PrefixClient = "client_urn:squidex:";
+ public static readonly string PictureUrl = "urn:squidex:picture";
public static readonly string PictureUrlStore = "store";
}
diff --git a/backend/src/Squidex.Shared/Identity/SquidexClaimsExtensions.cs b/backend/src/Squidex.Shared/Identity/SquidexClaimsExtensions.cs
new file mode 100644
index 000000000..c2dbbd48e
--- /dev/null
+++ b/backend/src/Squidex.Shared/Identity/SquidexClaimsExtensions.cs
@@ -0,0 +1,159 @@
+// ==========================================================================
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex UG (haftungsbeschränkt)
+// All rights reserved. Licensed under the MIT license.
+// ==========================================================================
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using Squidex.Infrastructure.Security;
+
+namespace Squidex.Shared.Identity
+{
+ public static class SquidexClaimsExtensions
+ {
+ private const string ClientPrefix = "client_";
+
+ public static PermissionSet Permissions(this IEnumerable user)
+ {
+ return new PermissionSet(user.GetClaims(SquidexClaimTypes.Permissions).Select(x => new Permission(x.Value)));
+ }
+
+ public static bool IsHidden(this IEnumerable user)
+ {
+ return user.HasClaimValue(SquidexClaimTypes.Hidden, "true");
+ }
+
+ public static bool HasConsent(this IEnumerable user)
+ {
+ return user.HasClaimValue(SquidexClaimTypes.Consent, "true");
+ }
+
+ public static bool HasConsentForEmails(this IEnumerable user)
+ {
+ return user.HasClaimValue(SquidexClaimTypes.ConsentForEmails, "true");
+ }
+
+ public static bool HasDisplayName(this IEnumerable user)
+ {
+ return user.HasClaim(SquidexClaimTypes.DisplayName);
+ }
+
+ public static bool HasPictureUrl(this IEnumerable user)
+ {
+ return user.HasClaim(SquidexClaimTypes.PictureUrl);
+ }
+
+ public static bool IsPictureUrlStored(this IEnumerable user)
+ {
+ return user.HasClaimValue(SquidexClaimTypes.PictureUrl, SquidexClaimTypes.PictureUrlStore);
+ }
+
+ public static string? ClientSecret(this IEnumerable user)
+ {
+ return user.GetClaimValue(SquidexClaimTypes.ClientSecret);
+ }
+
+ public static string? PictureUrl(this IEnumerable user)
+ {
+ return user.GetClaimValue(SquidexClaimTypes.PictureUrl);
+ }
+
+ public static string? DisplayName(this IEnumerable user)
+ {
+ return user.GetClaimValue(SquidexClaimTypes.DisplayName);
+ }
+
+ public static bool HasClaim(this IEnumerable user, string type)
+ {
+ return user.GetClaims(type).Any();
+ }
+
+ public static bool HasClaimValue(this IEnumerable user, string type, string value)
+ {
+ return user.GetClaims(type).Any(x => string.Equals(x.Value, value, StringComparison.OrdinalIgnoreCase));
+ }
+
+ public static IEnumerable GetSquidexClaims(this IEnumerable user)
+ {
+ const string prefix = "urn:squidex:";
+
+ foreach (var claim in user)
+ {
+ var type = GetType(claim);
+
+ if (type.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
+ {
+ yield return claim;
+ }
+ }
+ }
+
+ public static IEnumerable<(string Name, string Value)> GetCustomProperties(this IEnumerable user)
+ {
+ foreach (var claim in user)
+ {
+ var type = GetType(claim);
+
+ if (type.StartsWith(SquidexClaimTypes.CustomPrefix, StringComparison.OrdinalIgnoreCase))
+ {
+ var name = type[(SquidexClaimTypes.CustomPrefix.Length + 1)..].ToString();
+
+ yield return (name, claim.Value);
+ }
+ }
+ }
+
+ public static string? PictureNormalizedUrl(this IEnumerable user)
+ {
+ var url = user.FirstOrDefault(x => x.Type == SquidexClaimTypes.PictureUrl)?.Value;
+
+ if (!string.IsNullOrWhiteSpace(url) && Uri.IsWellFormedUriString(url, UriKind.Absolute) && url.Contains("gravatar"))
+ {
+ if (url.Contains("?"))
+ {
+ url += "&d=404";
+ }
+ else
+ {
+ url += "?d=404";
+ }
+ }
+
+ return url;
+ }
+
+ private static string? GetClaimValue(this IEnumerable user, string type)
+ {
+ return user.GetClaims(type).FirstOrDefault()?.Value;
+ }
+
+ private static IEnumerable GetClaims(this IEnumerable user, string request)
+ {
+ foreach (var claim in user)
+ {
+ var type = GetType(claim);
+
+ if (type.Equals(request, StringComparison.OrdinalIgnoreCase))
+ {
+ yield return claim;
+ }
+ }
+ }
+
+ private static ReadOnlySpan GetType(Claim claim)
+ {
+ var type = claim.Type.AsSpan();
+
+ if (type.StartsWith(ClientPrefix, StringComparison.OrdinalIgnoreCase))
+ {
+ type = type[ClientPrefix.Length..];
+ }
+
+ return type;
+ }
+ }
+}
diff --git a/backend/src/Squidex.Shared/Texts.it.resx b/backend/src/Squidex.Shared/Texts.it.resx
index e93b41b0e..f51d4b34e 100644
--- a/backend/src/Squidex.Shared/Texts.it.resx
+++ b/backend/src/Squidex.Shared/Texts.it.resx
@@ -463,9 +463,6 @@
La longitude deve essere tra -180 and 180.
-
- E' possibile impostare la geolocalizzazione solo impostando latitudine e longitudine.
-
Errore nel json,, atteso un number.
@@ -931,6 +928,9 @@
Acconsento
+
+ You cannot delete yourself.
+
Operazione non riuscita
diff --git a/backend/src/Squidex.Shared/Texts.nl.resx b/backend/src/Squidex.Shared/Texts.nl.resx
index d1b2c183b..edee5068b 100644
--- a/backend/src/Squidex.Shared/Texts.nl.resx
+++ b/backend/src/Squidex.Shared/Texts.nl.resx
@@ -463,9 +463,6 @@
Lengtegraad moet tussen -180 en 180 liggen.
-
- Geolocatie kan alleen de eigenschap lengte- en breedtegraad hebben.
-
Ongeldig json-type, verwacht aantal.
@@ -931,6 +928,9 @@
Toestemming
+
+ You cannot delete yourself.
+
Bewerking mislukt
diff --git a/backend/src/Squidex.Shared/Texts.resx b/backend/src/Squidex.Shared/Texts.resx
index 65dc55e89..9507a3795 100644
--- a/backend/src/Squidex.Shared/Texts.resx
+++ b/backend/src/Squidex.Shared/Texts.resx
@@ -463,9 +463,6 @@
Longitude must be between -180 and 180.
-
- Geolocation can only have latitude and longitude property.
-
Invalid json type, expected number.
@@ -931,6 +928,9 @@
Consent
+
+ You cannot delete yourself.
+
Operation failed
diff --git a/backend/src/Squidex.Shared/Users/ClientUser.cs b/backend/src/Squidex.Shared/Users/ClientUser.cs
index 88f840eff..52419312e 100644
--- a/backend/src/Squidex.Shared/Users/ClientUser.cs
+++ b/backend/src/Squidex.Shared/Users/ClientUser.cs
@@ -18,19 +18,6 @@ namespace Squidex.Shared.Users
private readonly RefToken token;
private readonly List claims;
- public ClientUser(RefToken token)
- {
- Guard.NotNull(token, nameof(token));
-
- this.token = token;
-
- claims = new List
- {
- new Claim(OpenIdClaims.ClientId, token.Identifier),
- new Claim(SquidexClaimTypes.DisplayName, token.ToString())
- };
- }
-
public string Id
{
get { return token.Identifier; }
@@ -50,5 +37,20 @@ namespace Squidex.Shared.Users
{
get { return claims; }
}
+
+ public object Identity => throw new System.NotImplementedException();
+
+ public ClientUser(RefToken token)
+ {
+ Guard.NotNull(token, nameof(token));
+
+ this.token = token;
+
+ claims = new List
+ {
+ new Claim(OpenIdClaims.ClientId, token.Identifier),
+ new Claim(SquidexClaimTypes.DisplayName, token.ToString())
+ };
+ }
}
}
diff --git a/backend/src/Squidex.Shared/Users/IUser.cs b/backend/src/Squidex.Shared/Users/IUser.cs
index 2c0534095..8e9253fb5 100644
--- a/backend/src/Squidex.Shared/Users/IUser.cs
+++ b/backend/src/Squidex.Shared/Users/IUser.cs
@@ -12,11 +12,13 @@ namespace Squidex.Shared.Users
{
public interface IUser
{
+ bool IsLocked { get; }
+
string Id { get; }
string Email { get; }
- bool IsLocked { get; }
+ object Identity { get; }
IReadOnlyList Claims { get; }
}
diff --git a/backend/src/Squidex.Shared/Users/UserExtensions.cs b/backend/src/Squidex.Shared/Users/UserExtensions.cs
deleted file mode 100644
index 89f9e7dbe..000000000
--- a/backend/src/Squidex.Shared/Users/UserExtensions.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-// ==========================================================================
-// Squidex Headless CMS
-// ==========================================================================
-// Copyright (c) Squidex UG (haftungsbeschränkt)
-// All rights reserved. Licensed under the MIT license.
-// ==========================================================================
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Squidex.Infrastructure.Security;
-using Squidex.Shared.Identity;
-
-namespace Squidex.Shared.Users
-{
- public static class UserExtensions
- {
- public static PermissionSet Permissions(this IUser user)
- {
- return new PermissionSet(user.GetClaimValues(SquidexClaimTypes.Permissions).Select(x => new Permission(x)));
- }
-
- public static bool IsInvited(this IUser user)
- {
- return user.HasClaimValue(SquidexClaimTypes.Invited, "true");
- }
-
- public static bool IsHidden(this IUser user)
- {
- return user.HasClaimValue(SquidexClaimTypes.Hidden, "true");
- }
-
- public static bool HasConsent(this IUser user)
- {
- return user.HasClaimValue(SquidexClaimTypes.Consent, "true");
- }
-
- public static bool HasConsentForEmails(this IUser user)
- {
- return user.HasClaimValue(SquidexClaimTypes.ConsentForEmails, "true");
- }
-
- public static bool HasDisplayName(this IUser user)
- {
- return user.HasClaim(SquidexClaimTypes.DisplayName);
- }
-
- public static bool HasPictureUrl(this IUser user)
- {
- return user.HasClaim(SquidexClaimTypes.PictureUrl);
- }
-
- public static bool IsPictureUrlStored(this IUser user)
- {
- return user.HasClaimValue(SquidexClaimTypes.PictureUrl, SquidexClaimTypes.PictureUrlStore);
- }
-
- public static string? ClientSecret(this IUser user)
- {
- return user.GetClaimValue(SquidexClaimTypes.ClientSecret);
- }
-
- public static string? PictureUrl(this IUser user)
- {
- return user.GetClaimValue(SquidexClaimTypes.PictureUrl);
- }
-
- public static string? DisplayName(this IUser user)
- {
- return user.GetClaimValue(SquidexClaimTypes.DisplayName);
- }
-
- public static string? GetClaimValue(this IUser user, string type)
- {
- return user.Claims.FirstOrDefault(x => string.Equals(x.Type, type, StringComparison.OrdinalIgnoreCase))?.Value;
- }
-
- public static string[] GetClaimValues(this IUser user, string type)
- {
- return user.Claims.Where(x => string.Equals(x.Type, type, StringComparison.OrdinalIgnoreCase))
- .Select(x => x.Value).ToArray();
- }
-
- public static List<(string Name, string Value)> GetCustomProperties(this IUser user)
- {
- return user.Claims.Where(x => x.Type.StartsWith(SquidexClaimTypes.CustomPrefix, StringComparison.OrdinalIgnoreCase))
- .Select(x => (x.Type[(SquidexClaimTypes.CustomPrefix.Length + 1)..], x.Value)).ToList();
- }
-
- public static bool HasClaim(this IUser user, string type)
- {
- return user.Claims.Any(x => string.Equals(x.Type, type, StringComparison.OrdinalIgnoreCase));
- }
-
- public static bool HasClaimValue(this IUser user, string type, string value)
- {
- return user.Claims.Any(x =>
- string.Equals(x.Type, type, StringComparison.OrdinalIgnoreCase) &&
- string.Equals(x.Value, value, StringComparison.OrdinalIgnoreCase));
- }
-
- public static string? PictureNormalizedUrl(this IUser user)
- {
- var url = user.Claims.FirstOrDefault(x => x.Type == SquidexClaimTypes.PictureUrl)?.Value;
-
- if (!string.IsNullOrWhiteSpace(url) && Uri.IsWellFormedUriString(url, UriKind.Absolute) && url.Contains("gravatar"))
- {
- if (url.Contains("?"))
- {
- url += "&d=404";
- }
- else
- {
- url += "?d=404";
- }
- }
-
- return url;
- }
- }
-}
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs
index 24ec24e27..c4dee1df7 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppClientsController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Apps.Models;
@@ -41,7 +42,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/{app}/clients/")]
- [ProducesResponseType(typeof(ClientsDto), 200)]
+ [ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppClientsRead)]
[ApiCosts(0)]
public IActionResult GetClients(string app)
@@ -100,7 +101,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpPut]
[Route("apps/{app}/clients/{id}/")]
- [ProducesResponseType(typeof(ClientsDto), 200)]
+ [ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppClientsUpdate)]
[ApiCosts(1)]
public async Task PutClient(string app, string id, [FromBody] UpdateClientDto request)
@@ -126,7 +127,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpDelete]
[Route("apps/{app}/clients/{id}/")]
- [ProducesResponseType(typeof(ClientsDto), 200)]
+ [ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppClientsDelete)]
[ApiCosts(1)]
public async Task DeleteClient(string app, string id)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs
index 4e5ad1c62..cf78feb99 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppContributorsController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Apps.Models;
@@ -50,7 +51,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/{app}/contributors/")]
- [ProducesResponseType(typeof(ContributorsDto), 200)]
+ [ProducesResponseType(typeof(ContributorsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContributorsRead)]
[ApiCosts(0)]
public IActionResult GetContributors(string app)
@@ -99,7 +100,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpDelete]
[Route("apps/{app}/contributors/me/")]
- [ProducesResponseType(typeof(ContributorsDto), 200)]
+ [ProducesResponseType(typeof(ContributorsDto), StatusCodes.Status200OK)]
[ApiPermission]
[ApiCosts(1)]
public async Task DeleteMyself(string app)
@@ -122,7 +123,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpDelete]
[Route("apps/{app}/contributors/{id}/")]
- [ProducesResponseType(typeof(ContributorsDto), 200)]
+ [ProducesResponseType(typeof(ContributorsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContributorsRevoke)]
[ApiCosts(1)]
public async Task DeleteContributor(string app, string id)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs
index 8f07b66bf..1acc33bce 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppLanguagesController.cs
@@ -7,6 +7,7 @@
using System;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Apps.Models;
@@ -40,7 +41,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/{app}/languages/")]
- [ProducesResponseType(typeof(AppLanguagesDto), 200)]
+ [ProducesResponseType(typeof(AppLanguagesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppLanguagesRead)]
[ApiCosts(0)]
public IActionResult GetLanguages(string app)
@@ -92,7 +93,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpPut]
[Route("apps/{app}/languages/{language}/")]
- [ProducesResponseType(typeof(AppLanguagesDto), 200)]
+ [ProducesResponseType(typeof(AppLanguagesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppLanguagesUpdate)]
[ApiCosts(1)]
public async Task PutLanguage(string app, string language, [FromBody] UpdateLanguageDto request)
@@ -116,7 +117,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpDelete]
[Route("apps/{app}/languages/{language}/")]
- [ProducesResponseType(typeof(AppLanguagesDto), 200)]
+ [ProducesResponseType(typeof(AppLanguagesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppLanguagesDelete)]
[ApiCosts(1)]
public async Task DeleteLanguage(string app, string language)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs
index 3f0f76f95..d39075d11 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppPatternsController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Apps.Models;
@@ -42,7 +43,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/{app}/patterns/")]
- [ProducesResponseType(typeof(PatternsDto), 200)]
+ [ProducesResponseType(typeof(PatternsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppPatternsRead)]
[ApiCosts(0)]
public IActionResult GetPatterns(string app)
@@ -94,7 +95,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpPut]
[Route("apps/{app}/patterns/{id}/")]
- [ProducesResponseType(typeof(PatternsDto), 200)]
+ [ProducesResponseType(typeof(PatternsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppPatternsUpdate)]
[ApiCosts(1)]
public async Task PutPattern(string app, DomainId id, [FromBody] UpdatePatternDto request)
@@ -120,7 +121,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpDelete]
[Route("apps/{app}/patterns/{id}/")]
- [ProducesResponseType(typeof(PatternsDto), 200)]
+ [ProducesResponseType(typeof(PatternsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppPatternsDelete)]
[ApiCosts(1)]
public async Task DeletePattern(string app, DomainId id)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs
index b8d018d09..a0ddc72fa 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppRolesController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Apps.Models;
@@ -42,7 +43,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/{app}/roles/")]
- [ProducesResponseType(typeof(RolesDto), 200)]
+ [ProducesResponseType(typeof(RolesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRolesRead)]
[ApiCosts(0)]
public IActionResult GetRoles(string app)
@@ -67,7 +68,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/{app}/roles/permissions")]
- [ProducesResponseType(typeof(string[]), 200)]
+ [ProducesResponseType(typeof(string[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRolesRead)]
[ApiCosts(0)]
public IActionResult GetPermissions(string app)
@@ -119,7 +120,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpPut]
[Route("apps/{app}/roles/{roleName}/")]
- [ProducesResponseType(typeof(RolesDto), 200)]
+ [ProducesResponseType(typeof(RolesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRolesUpdate)]
[ApiCosts(1)]
public async Task PutRole(string app, string roleName, [FromBody] UpdateRoleDto request)
@@ -143,7 +144,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpDelete]
[Route("apps/{app}/roles/{roleName}/")]
- [ProducesResponseType(typeof(RolesDto), 200)]
+ [ProducesResponseType(typeof(RolesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRolesDelete)]
[ApiCosts(1)]
public async Task DeleteRole(string app, string roleName)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs
index 8645038e2..abd9f8c8f 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppWorkflowsController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Apps.Models;
@@ -43,7 +44,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/{app}/workflows/")]
- [ProducesResponseType(typeof(WorkflowsDto), 200)]
+ [ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppWorkflowsRead)]
[ApiCosts(0)]
public IActionResult GetWorkflows(string app)
@@ -70,7 +71,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpPost]
[Route("apps/{app}/workflows/")]
- [ProducesResponseType(typeof(WorkflowsDto), 200)]
+ [ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppWorkflowsUpdate)]
[ApiCosts(1)]
public async Task PostWorkflow(string app, [FromBody] AddWorkflowDto request)
@@ -95,7 +96,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpPut]
[Route("apps/{app}/workflows/{id}")]
- [ProducesResponseType(typeof(WorkflowsDto), 200)]
+ [ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppWorkflowsUpdate)]
[ApiCosts(1)]
public async Task PutWorkflow(string app, DomainId id, [FromBody] UpdateWorkflowDto request)
@@ -118,7 +119,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpDelete]
[Route("apps/{app}/workflows/{id}")]
- [ProducesResponseType(typeof(WorkflowsDto), 200)]
+ [ProducesResponseType(typeof(WorkflowsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppWorkflowsUpdate)]
[ApiCosts(1)]
public async Task DeleteWorkflow(string app, DomainId id)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs
index 2b04ceb89..65437462f 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs
@@ -70,7 +70,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/")]
- [ProducesResponseType(typeof(AppDto[]), 200)]
+ [ProducesResponseType(typeof(AppDto[]), StatusCodes.Status200OK)]
[ApiPermission]
[ApiCosts(0)]
public async Task GetApps()
@@ -102,7 +102,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/{app}")]
- [ProducesResponseType(typeof(AppDto), 200)]
+ [ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)]
[ApiPermission]
[ApiCosts(0)]
public IActionResult GetApp(string app)
@@ -158,7 +158,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpPut]
[Route("apps/{app}/")]
- [ProducesResponseType(typeof(AppDto), 200)]
+ [ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUpdate)]
[ApiCosts(0)]
public async Task UpdateApp(string app, [FromBody] UpdateAppDto request)
@@ -180,7 +180,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpPost]
[Route("apps/{app}/image")]
- [ProducesResponseType(typeof(AppDto), 200)]
+ [ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUpdateImage)]
[ApiCosts(0)]
public async Task UploadImage(string app, IFormFile file)
@@ -200,7 +200,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpGet]
[Route("apps/{app}/image")]
- [ProducesResponseType(typeof(FileResult), 200)]
+ [ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK)]
[AllowAnonymous]
[ApiCosts(0)]
public IActionResult GetImage(string app)
@@ -271,7 +271,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
///
[HttpDelete]
[Route("apps/{app}/image")]
- [ProducesResponseType(typeof(AppDto), 200)]
+ [ProducesResponseType(typeof(AppDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUpdateImage)]
[ApiCosts(0)]
public async Task DeleteImage(string app)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs
index 594953d95..bb1667286 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs
@@ -8,6 +8,7 @@
using System.Collections.Generic;
using Squidex.Infrastructure.Translations;
using Squidex.Infrastructure.Validation;
+using Squidex.Shared.Identity;
using Squidex.Shared.Users;
using Squidex.Web;
@@ -49,7 +50,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
{
if (users.TryGetValue(ContributorId, out var user))
{
- ContributorName = user.DisplayName()!;
+ ContributorName = user.Claims.DisplayName()!;
ContributorEmail = user.Email;
}
else
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
index 5f51dd0bc..b89a34082 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
@@ -10,6 +10,7 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Assets.Models;
@@ -67,7 +68,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpGet]
[Route("assets/{app}/{idOrSlug}/{*more}")]
- [ProducesResponseType(typeof(FileResult), 200)]
+ [ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK)]
[ApiPermission]
[ApiCosts(0.5)]
[AllowAnonymous]
@@ -94,7 +95,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpGet]
[Route("assets/{id}/")]
- [ProducesResponseType(typeof(FileResult), 200)]
+ [ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK)]
[ApiPermission]
[ApiCosts(0.5)]
[AllowAnonymous]
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs
index c59190e78..595798419 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Assets.Models;
@@ -47,7 +48,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpGet]
[Route("apps/{app}/assets/folders", Order = -1)]
- [ProducesResponseType(typeof(AssetsDto), 200)]
+ [ProducesResponseType(typeof(AssetsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)]
[ApiCosts(1)]
public async Task GetAssetFolders(string app, [FromQuery] DomainId parentId)
@@ -106,7 +107,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpPut]
[Route("apps/{app}/assets/folders/{id}/", Order = -1)]
- [ProducesResponseType(typeof(AssetDto), 200)]
+ [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)]
[ApiCosts(1)]
@@ -132,7 +133,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpPut]
[Route("apps/{app}/assets/folders/{id}/parent", Order = -1)]
- [ProducesResponseType(typeof(AssetDto), 200)]
+ [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)]
[ApiCosts(1)]
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs
index c2907f4d0..f19b63a2b 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs
@@ -64,7 +64,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpGet]
[Route("apps/{app}/assets/tags")]
- [ProducesResponseType(typeof(Dictionary), 200)]
+ [ProducesResponseType(typeof(Dictionary), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)]
[ApiCosts(1)]
public async Task GetTags(string app)
@@ -92,7 +92,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpGet]
[Route("apps/{app}/assets/")]
- [ProducesResponseType(typeof(AssetsDto), 200)]
+ [ProducesResponseType(typeof(AssetsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)]
[ApiCosts(1)]
public async Task GetAssets(string app, [FromQuery] DomainId? parentId, [FromQuery] string? ids = null, [FromQuery] string? q = null)
@@ -121,7 +121,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpPost]
[Route("apps/{app}/assets/query")]
- [ProducesResponseType(typeof(AssetsDto), 200)]
+ [ProducesResponseType(typeof(AssetsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)]
[ApiCosts(1)]
public async Task GetAssetsPost(string app, [FromBody] QueryDto query)
@@ -147,7 +147,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpGet]
[Route("apps/{app}/assets/{id}/")]
- [ProducesResponseType(typeof(AssetDto), 200)]
+ [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsRead)]
[ApiCosts(1)]
public async Task GetAsset(string app, DomainId id)
@@ -223,7 +223,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpPut]
[Route("apps/{app}/assets/{id}/content/")]
- [ProducesResponseType(typeof(AssetDto), 200)]
+ [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpload)]
[ApiCosts(1)]
public async Task PutAssetContent(string app, DomainId id, IFormFile file)
@@ -250,7 +250,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpPut]
[Route("apps/{app}/assets/{id}/")]
- [ProducesResponseType(typeof(AssetDto), 200)]
+ [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)]
[ApiCosts(1)]
@@ -276,7 +276,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
///
[HttpPut]
[Route("apps/{app}/assets/{id}/parent")]
- [ProducesResponseType(typeof(AssetDto), 200)]
+ [ProducesResponseType(typeof(AssetDto), StatusCodes.Status200OK)]
[AssetRequestSizeLimit]
[ApiPermissionOrAnonymous(Permissions.AppAssetsUpdate)]
[ApiCosts(1)]
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Backups/BackupContentController.cs b/backend/src/Squidex/Areas/Api/Controllers/Backups/BackupContentController.cs
index c0868e44f..30c50716d 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Backups/BackupContentController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Backups/BackupContentController.cs
@@ -7,6 +7,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Domain.Apps.Entities.Backup;
using Squidex.Infrastructure;
@@ -45,7 +46,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
[HttpGet]
[Route("apps/{app}/backups/{id}")]
[ResponseCache(Duration = 3600 * 24 * 30)]
- [ProducesResponseType(typeof(FileResult), 200)]
+ [ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK)]
[ApiCosts(0)]
[AllowAnonymous]
public async Task GetBackupContent(string app, DomainId id)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs
index 10941e581..c217b3054 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Backups/BackupsController.cs
@@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.Backups.Models;
using Squidex.Domain.Apps.Entities.Backup;
@@ -43,7 +44,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
///
[HttpGet]
[Route("apps/{app}/backups/")]
- [ProducesResponseType(typeof(BackupJobsDto), 200)]
+ [ProducesResponseType(typeof(BackupJobsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppBackupsRead)]
[ApiCosts(0)]
public async Task GetBackups(string app)
@@ -66,7 +67,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
///
[HttpPost]
[Route("apps/{app}/backups/")]
- [ProducesResponseType(typeof(List), 200)]
+ [ProducesResponseType(typeof(List), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppBackupsCreate)]
[ApiCosts(0)]
public IActionResult PostBackup(string app)
@@ -87,7 +88,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
///
[HttpDelete]
[Route("apps/{app}/backups/{id}")]
- [ProducesResponseType(typeof(List), 200)]
+ [ProducesResponseType(typeof(List), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppBackupsDelete)]
[ApiCosts(0)]
public async Task DeleteBackup(string app, DomainId id)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs b/backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs
index 5f71b3125..75b369af6 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.Backups.Models;
using Squidex.Domain.Apps.Entities.Backup;
@@ -38,7 +39,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
///
[HttpGet]
[Route("apps/restore/")]
- [ProducesResponseType(typeof(RestoreJobDto), 200)]
+ [ProducesResponseType(typeof(RestoreJobDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminRestore)]
public async Task GetRestoreJob()
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Comments/CommentsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Comments/CommentsController.cs
index 0c1945ab2..f3f71616b 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Comments/CommentsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Comments/CommentsController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Comments.Models;
@@ -47,7 +48,7 @@ namespace Squidex.Areas.Api.Controllers.Comments
///
[HttpGet]
[Route("apps/{app}/comments/{commentsId}")]
- [ProducesResponseType(typeof(CommentsDto), 200)]
+ [ProducesResponseType(typeof(CommentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppCommentsRead)]
[ApiCosts(0)]
public async Task GetComments(string app, DomainId commentsId, [FromQuery] long version = EtagVersion.Any)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Comments/Notifications/UserNotificationsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Comments/Notifications/UserNotificationsController.cs
index 455a4ecc7..6244c397b 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Comments/Notifications/UserNotificationsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Comments/Notifications/UserNotificationsController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Comments.Models;
@@ -47,7 +48,7 @@ namespace Squidex.Areas.Api.Controllers.Comments.Notifications
///
[HttpGet]
[Route("users/{userId}/notifications")]
- [ProducesResponseType(typeof(CommentsDto), 200)]
+ [ProducesResponseType(typeof(CommentsDto), StatusCodes.Status200OK)]
[ApiPermission]
public async Task GetNotifications(DomainId userId, [FromQuery] long version = EtagVersion.Any)
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
index 75f200616..451ab462a 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
@@ -7,6 +7,7 @@
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.Contents.Models;
using Squidex.Domain.Apps.Core.Contents;
@@ -149,7 +150,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpGet]
[Route("content/{app}/")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous]
[ApiCosts(1)]
public async Task GetAllContents(string app, [FromQuery] string ids)
@@ -178,7 +179,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpPost]
[Route("content/{app}/")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous]
[ApiCosts(1)]
public async Task GetAllContentsPost(string app, [FromBody] ContentsIdsQueryDto query)
@@ -209,7 +210,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpGet]
[Route("content/{app}/{name}/")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous]
[ApiCosts(1)]
public async Task GetContents(string app, string name, [FromQuery] string? ids = null, [FromQuery] string? q = null)
@@ -241,7 +242,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpPost]
[Route("content/{app}/{name}/query")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous]
[ApiCosts(1)]
public async Task GetContentsPost(string app, string name, [FromBody] QueryDto query)
@@ -273,7 +274,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpGet]
[Route("content/{app}/{name}/{id}/")]
- [ProducesResponseType(typeof(ContentDto), 200)]
+ [ProducesResponseType(typeof(ContentDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous]
[ApiCosts(1)]
public async Task GetContent(string app, string name, DomainId id)
@@ -333,7 +334,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpGet]
[Route("content/{app}/{name}/{id}/references")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous]
[ApiCosts(1)]
public async Task GetReferences(string app, string name, DomainId id, [FromQuery] string? q = null)
@@ -364,7 +365,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpGet]
[Route("content/{app}/{name}/{id}/referencing")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous]
[ApiCosts(1)]
public async Task GetReferencing(string app, string name, DomainId id, [FromQuery] string? q = null)
@@ -462,7 +463,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpPost]
[Route("content/{app}/{name}/import")]
- [ProducesResponseType(typeof(BulkResultDto[]), 200)]
+ [ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsCreate)]
[ApiCosts(5)]
public async Task PostContents(string app, string name, [FromBody] ImportContentsDto request)
@@ -493,7 +494,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpPost]
[Route("content/{app}/{name}/bulk")]
- [ProducesResponseType(typeof(BulkResultDto[]), 200)]
+ [ProducesResponseType(typeof(BulkResultDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContents)]
[ApiCosts(5)]
public async Task BulkContents(string app, string name, [FromBody] BulkUpdateDto request)
@@ -526,7 +527,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpPost]
[Route("content/{app}/{name}/{id}/")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsUpsert)]
[ApiCosts(1)]
public async Task PostContent(string app, string name, DomainId id, [FromBody] NamedContentData request, [FromQuery] bool publish = false)
@@ -555,7 +556,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpPut]
[Route("content/{app}/{name}/{id}/")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsUpdate)]
[ApiCosts(1)]
public async Task PutContent(string app, string name, DomainId id, [FromBody] NamedContentData request)
@@ -584,7 +585,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpPatch]
[Route("content/{app}/{name}/{id}/")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsUpdate)]
[ApiCosts(1)]
public async Task PatchContent(string app, string name, DomainId id, [FromBody] NamedContentData request)
@@ -613,7 +614,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpPut]
[Route("content/{app}/{name}/{id}/status/")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsUpdate)]
[ApiCosts(1)]
public async Task PutContentStatus(string app, string name, DomainId id, ChangeStatusDto request)
@@ -640,7 +641,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpPost]
[Route("content/{app}/{name}/{id}/draft/")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsVersionCreate)]
[ApiCosts(1)]
public async Task CreateDraft(string app, string name, DomainId id)
@@ -667,7 +668,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
///
[HttpDelete]
[Route("content/{app}/{name}/{id}/draft/")]
- [ProducesResponseType(typeof(ContentsDto), 200)]
+ [ProducesResponseType(typeof(ContentsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppContentsDelete)]
[ApiCosts(1)]
public async Task DeleteVersion(string app, string name, DomainId id)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs b/backend/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs
index c276af340..622ee0dff 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Orleans;
using Squidex.Areas.Api.Controllers.EventConsumers.Models;
@@ -29,7 +30,7 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers
[HttpGet]
[Route("event-consumers/")]
- [ProducesResponseType(typeof(EventConsumersDto), 200)]
+ [ProducesResponseType(typeof(EventConsumersDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminEventsRead)]
public async Task GetEventConsumers()
{
@@ -42,7 +43,7 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers
[HttpPut]
[Route("event-consumers/{consumerName}/start/")]
- [ProducesResponseType(typeof(EventConsumerDto), 200)]
+ [ProducesResponseType(typeof(EventConsumerDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminEventsManage)]
public async Task StartEventConsumer(string consumerName)
{
@@ -55,7 +56,7 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers
[HttpPut]
[Route("event-consumers/{consumerName}/stop/")]
- [ProducesResponseType(typeof(EventConsumerDto), 200)]
+ [ProducesResponseType(typeof(EventConsumerDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminEventsManage)]
public async Task StopEventConsumer(string consumerName)
{
@@ -68,7 +69,7 @@ namespace Squidex.Areas.Api.Controllers.EventConsumers
[HttpPut]
[Route("event-consumers/{consumerName}/reset/")]
- [ProducesResponseType(typeof(EventConsumerDto), 200)]
+ [ProducesResponseType(typeof(EventConsumerDto), StatusCodes.Status200OK)]
[ApiPermission(Permissions.AdminEventsManage)]
public async Task ResetEventConsumer(string consumerName)
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs b/backend/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs
index 9f7b3e16a..820200c79 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/History/HistoryController.cs
@@ -7,6 +7,7 @@
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.History.Models;
using Squidex.Domain.Apps.Entities.History;
@@ -41,7 +42,7 @@ namespace Squidex.Areas.Api.Controllers.History
///
[HttpGet]
[Route("apps/{app}/history/")]
- [ProducesResponseType(typeof(HistoryEventDto), 200)]
+ [ProducesResponseType(typeof(HistoryEventDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppHistory)]
[ApiCosts(0.1)]
public async Task GetHistory(string app, string channel)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs b/backend/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs
index 5c9a74e67..9a023ed72 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Languages/LanguagesController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Linq;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Infrastructure;
@@ -36,7 +37,7 @@ namespace Squidex.Areas.Api.Controllers.Languages
///
[HttpGet]
[Route("languages/")]
- [ProducesResponseType(typeof(LanguageDto[]), 200)]
+ [ProducesResponseType(typeof(LanguageDto[]), StatusCodes.Status200OK)]
[ApiPermission]
public IActionResult GetLanguages()
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/News/NewsController.cs b/backend/src/Squidex/Areas/Api/Controllers/News/NewsController.cs
index 50e28fbfd..be965fc2e 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/News/NewsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/News/NewsController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.News.Models;
using Squidex.Areas.Api.Controllers.News.Service;
@@ -37,7 +38,7 @@ namespace Squidex.Areas.Api.Controllers.News
///
[HttpGet]
[Route("news/features/")]
- [ProducesResponseType(typeof(FeaturesDto), 200)]
+ [ProducesResponseType(typeof(FeaturesDto), StatusCodes.Status200OK)]
[ApiPermission]
public async Task GetNews([FromQuery] int version = 0)
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Ping/PingController.cs b/backend/src/Squidex/Areas/Api/Controllers/Ping/PingController.cs
index 1e1881131..9165f7b93 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Ping/PingController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Ping/PingController.cs
@@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Infrastructure.Commands;
using Squidex.Shared;
@@ -33,7 +34,7 @@ namespace Squidex.Areas.Api.Controllers.Ping
/// 200 => Infos returned.
///
[HttpGet]
- [ProducesResponseType(typeof(ExposedValues), 200)]
+ [ProducesResponseType(typeof(ExposedValues), StatusCodes.Status200OK)]
[Route("info/")]
public IActionResult GetInfo()
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs b/backend/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs
index 0b81d48e5..39e502087 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Plans/AppPlansController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Plans.Models;
@@ -44,7 +45,7 @@ namespace Squidex.Areas.Api.Controllers.Plans
///
[HttpGet]
[Route("apps/{app}/plans/")]
- [ProducesResponseType(typeof(AppPlansDto), 200)]
+ [ProducesResponseType(typeof(AppPlansDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppPlansRead)]
[ApiCosts(0)]
public IActionResult GetPlans(string app)
@@ -73,7 +74,7 @@ namespace Squidex.Areas.Api.Controllers.Plans
///
[HttpPut]
[Route("apps/{app}/plan/")]
- [ProducesResponseType(typeof(PlanChangedDto), 200)]
+ [ProducesResponseType(typeof(PlanChangedDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppPlansChange)]
[ApiCosts(0)]
public async Task PutPlan(string app, [FromBody] ChangePlanDto request)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs b/backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs
index be4b445fe..0138d4aca 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs
@@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using NodaTime;
@@ -56,7 +57,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
///
[HttpGet]
[Route("rules/actions/")]
- [ProducesResponseType(typeof(Dictionary), 200)]
+ [ProducesResponseType(typeof(Dictionary), StatusCodes.Status200OK)]
[ApiPermission]
[ApiCosts(0)]
public IActionResult GetActions()
@@ -83,7 +84,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
///
[HttpGet]
[Route("apps/{app}/rules/")]
- [ProducesResponseType(typeof(RulesDto), 200)]
+ [ProducesResponseType(typeof(RulesDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesRead)]
[ApiCosts(1)]
public async Task GetRules(string app)
@@ -131,7 +132,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
///
[HttpDelete]
[Route("apps/{app}/rules/run")]
- [ProducesResponseType(204)]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiCosts(1)]
public async Task DeleteRuleRun(string app)
@@ -154,7 +155,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
///
[HttpPut]
[Route("apps/{app}/rules/{id}/")]
- [ProducesResponseType(typeof(RuleDto), 200)]
+ [ProducesResponseType(typeof(RuleDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesUpdate)]
[ApiCosts(1)]
public async Task PutRule(string app, DomainId id, [FromBody] UpdateRuleDto request)
@@ -177,7 +178,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
///
[HttpPut]
[Route("apps/{app}/rules/{id}/enable/")]
- [ProducesResponseType(typeof(RuleDto), 200)]
+ [ProducesResponseType(typeof(RuleDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesDisable)]
[ApiCosts(1)]
public async Task EnableRule(string app, DomainId id)
@@ -200,7 +201,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
///
[HttpPut]
[Route("apps/{app}/rules/{id}/disable/")]
- [ProducesResponseType(typeof(RuleDto), 200)]
+ [ProducesResponseType(typeof(RuleDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesDisable)]
[ApiCosts(1)]
public async Task DisableRule(string app, DomainId id)
@@ -245,7 +246,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
///
[HttpPut]
[Route("apps/{app}/rules/{id}/run")]
- [ProducesResponseType(204)]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
[ApiPermissionOrAnonymous(Permissions.AppRulesEvents)]
[ApiCosts(1)]
public async Task PutRuleRun(string app, DomainId id, [FromQuery] bool fromSnapshots = false)
@@ -288,7 +289,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
///
[HttpGet]
[Route("apps/{app}/rules/events/")]
- [ProducesResponseType(typeof(RuleEventsDto), 200)]
+ [ProducesResponseType(typeof(RuleEventsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppRulesRead)]
[ApiCosts(0)]
public async Task GetEvents(string app, [FromQuery] DomainId? ruleId = null, [FromQuery] int skip = 0, [FromQuery] int take = 20)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs
index e199ba5e1..33cceda86 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemaFieldsController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.Schemas.Models;
using Squidex.Domain.Apps.Entities.Schemas;
@@ -93,7 +94,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/ui/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutSchemaUIFields(string app, string name, [FromBody] ConfigureUIFieldsDto request)
@@ -118,7 +119,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/ordering/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutSchemaFieldOrdering(string app, string name, [FromBody] ReorderFieldsDto request)
@@ -144,7 +145,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/ordering/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutNestedFieldOrdering(string app, string name, long parentId, [FromBody] ReorderFieldsDto request)
@@ -170,7 +171,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{id:long}/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutField(string app, string name, long id, [FromBody] UpdateFieldDto request)
@@ -197,7 +198,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutNestedField(string app, string name, long parentId, long id, [FromBody] UpdateFieldDto request)
@@ -225,7 +226,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{id:long}/lock/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task LockField(string app, string name, long id)
@@ -254,7 +255,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/lock/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task LockNestedField(string app, string name, long parentId, long id)
@@ -282,7 +283,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{id:long}/hide/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task HideField(string app, string name, long id)
@@ -311,7 +312,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/hide/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task HideNestedField(string app, string name, long parentId, long id)
@@ -339,7 +340,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{id:long}/show/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task ShowField(string app, string name, long id)
@@ -368,7 +369,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/show/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task ShowNestedField(string app, string name, long parentId, long id)
@@ -396,7 +397,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{id:long}/enable/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task EnableField(string app, string name, long id)
@@ -425,7 +426,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/enable/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task EnableNestedField(string app, string name, long parentId, long id)
@@ -453,7 +454,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{id:long}/disable/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task DisableField(string app, string name, long id)
@@ -482,7 +483,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/disable/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task DisableNestedField(string app, string name, long parentId, long id)
@@ -507,7 +508,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpDelete]
[Route("apps/{app}/schemas/{name}/fields/{id:long}/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task DeleteField(string app, string name, long id)
@@ -533,7 +534,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpDelete]
[Route("apps/{app}/schemas/{name}/fields/{parentId:long}/nested/{id:long}/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task DeleteNestedField(string app, string name, long parentId, long id)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs b/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs
index 52437870f..375506fbd 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs
@@ -7,6 +7,7 @@
using System;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Api.Controllers.Schemas.Models;
@@ -44,7 +45,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpGet]
[Route("apps/{app}/schemas/")]
- [ProducesResponseType(typeof(SchemasDto), 200)]
+ [ProducesResponseType(typeof(SchemasDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasRead)]
[ApiCosts(0)]
public async Task GetSchemas(string app)
@@ -72,7 +73,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpGet]
[Route("apps/{app}/schemas/{name}/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasRead)]
[ApiCosts(0)]
public async Task GetSchema(string app, string name)
@@ -142,7 +143,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutSchema(string app, string name, [FromBody] UpdateSchemaDto request)
@@ -167,7 +168,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/sync")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutSchemaSync(string app, string name, [FromBody] SynchronizeSchemaDto request)
@@ -192,7 +193,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/category")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutCategory(string app, string name, [FromBody] ChangeCategoryDto request)
@@ -217,7 +218,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/preview-urls")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutPreviewUrls(string app, string name, [FromBody] ConfigurePreviewUrlsDto request)
@@ -242,7 +243,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/scripts/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasScripts)]
[ApiCosts(1)]
public async Task PutScripts(string app, string name, [FromBody] SchemaScriptsDto request)
@@ -267,7 +268,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/rules/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasUpdate)]
[ApiCosts(1)]
public async Task PutRules(string app, string name, [FromBody] ConfigureFieldRulesDto request)
@@ -290,7 +291,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/publish/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasPublish)]
[ApiCosts(1)]
public async Task PublishSchema(string app, string name)
@@ -313,7 +314,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
///
[HttpPut]
[Route("apps/{app}/schemas/{name}/unpublish/")]
- [ProducesResponseType(typeof(SchemaDetailsDto), 200)]
+ [ProducesResponseType(typeof(SchemaDetailsDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSchemasPublish)]
[ApiCosts(1)]
public async Task UnpublishSchema(string app, string name)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Search/SearchController.cs b/backend/src/Squidex/Areas/Api/Controllers/Search/SearchController.cs
index ac9230937..10d41b551 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Search/SearchController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Search/SearchController.cs
@@ -7,6 +7,7 @@
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.Search.Models;
using Squidex.Domain.Apps.Entities.Search;
@@ -41,7 +42,7 @@ namespace Squidex.Areas.Api.Controllers.Search
///
[HttpGet]
[Route("apps/{app}/search/")]
- [ProducesResponseType(typeof(SearchResultDto[]), 200)]
+ [ProducesResponseType(typeof(SearchResultDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppSearch)]
[ApiCosts(0)]
public async Task GetSearchResults(string app, [FromQuery] string? query = null)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs b/backend/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs
index 5a6e51163..98c2f9352 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs
@@ -9,6 +9,7 @@ using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.DataProtection;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.Statistics.Models;
using Squidex.Domain.Apps.Entities.Apps;
@@ -66,7 +67,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics
///
[HttpGet]
[Route("apps/{app}/usages/log/")]
- [ProducesResponseType(typeof(LogDownloadDto), 200)]
+ [ProducesResponseType(typeof(LogDownloadDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUsage)]
[ApiCosts(0)]
public IActionResult GetLog(string app)
@@ -93,7 +94,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics
///
[HttpGet]
[Route("apps/{app}/usages/calls/{fromDate}/{toDate}/")]
- [ProducesResponseType(typeof(CallsUsageDtoDto), 200)]
+ [ProducesResponseType(typeof(CallsUsageDtoDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUsage)]
[ApiCosts(0)]
public async Task GetUsages(string app, DateTime fromDate, DateTime toDate)
@@ -122,7 +123,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics
///
[HttpGet]
[Route("apps/{app}/usages/storage/today/")]
- [ProducesResponseType(typeof(CurrentStorageDto), 200)]
+ [ProducesResponseType(typeof(CurrentStorageDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUsage)]
[ApiCosts(0)]
public async Task GetCurrentStorageSize(string app)
@@ -149,7 +150,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics
///
[HttpGet]
[Route("apps/{app}/usages/storage/{fromDate}/{toDate}/")]
- [ProducesResponseType(typeof(StorageUsagePerDateDto[]), 200)]
+ [ProducesResponseType(typeof(StorageUsagePerDateDto[]), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppUsage)]
[ApiCosts(0)]
public async Task GetStorageSizes(string app, DateTime fromDate, DateTime toDate)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs b/backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs
index ea9b74897..539982cea 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Translations/TranslationsController.cs
@@ -6,6 +6,7 @@
// ==========================================================================
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Squidex.Areas.Api.Controllers.Translations.Models;
using Squidex.Infrastructure.Commands;
@@ -39,7 +40,7 @@ namespace Squidex.Areas.Api.Controllers.Translations
///
[HttpPost]
[Route("apps/{app}/translations/")]
- [ProducesResponseType(typeof(TranslationDto), 200)]
+ [ProducesResponseType(typeof(TranslationDto), StatusCodes.Status200OK)]
[ApiPermissionOrAnonymous(Permissions.AppTranslate)]
[ApiCosts(0)]
public async Task PostTranslation(string app, [FromBody] TranslateDto request)
diff --git a/backend/src/Squidex/Areas/Api/Controllers/UI/UIController.cs b/backend/src/Squidex/Areas/Api/Controllers/UI/UIController.cs
index 8a4b825e3..ba161ad2c 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/UI/UIController.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/UI/UIController.cs
@@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Squidex.Areas.Api.Controllers.UI.Models;
@@ -42,7 +43,7 @@ namespace Squidex.Areas.Api.Controllers.UI
///
[HttpGet]
[Route("ui/settings/")]
- [ProducesResponseType(typeof(UISettingsDto), 200)]
+ [ProducesResponseType(typeof(UISettingsDto), StatusCodes.Status200OK)]
[ApiPermission]
public IActionResult GetSettings()
{
@@ -64,7 +65,7 @@ namespace Squidex.Areas.Api.Controllers.UI
///
[HttpGet]
[Route("apps/{app}/ui/settings/")]
- [ProducesResponseType(typeof(Dictionary), 200)]
+ [ProducesResponseType(typeof(Dictionary), StatusCodes.Status200OK)]
[ApiPermission]
public async Task GetSettings(string app)
{
@@ -83,7 +84,7 @@ namespace Squidex.Areas.Api.Controllers.UI
///
[HttpGet]
[Route("apps/{app}/ui/settings/me")]
- [ProducesResponseType(typeof(Dictionary), 200)]
+ [ProducesResponseType(typeof(Dictionary), StatusCodes.Status200OK)]
[ApiPermission]
public async Task GetUserSettings(string app)
{
diff --git a/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs b/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs
index 6c51fe683..a80e143f5 100644
--- a/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs
+++ b/backend/src/Squidex/Areas/Api/Controllers/Users/Models/UserDto.cs
@@ -8,6 +8,7 @@
using System.Collections.Generic;
using Squidex.Infrastructure.Reflection;
using Squidex.Infrastructure.Validation;
+using Squidex.Shared.Identity;
using Squidex.Shared.Users;
using Squidex.Web;
@@ -47,8 +48,8 @@ namespace Squidex.Areas.Api.Controllers.Users.Models
public static UserDto FromUser(IUser user, Resources resources)
{
- var userPermssions = user.Permissions().ToIds();
- var userName = user.DisplayName()!;
+ var userPermssions = user.Claims.Permissions().ToIds();
+ var userName = user.Claims.DisplayName()!;
var result = SimpleMapper.Map(user, new UserDto { DisplayName = userName, Permissions = userPermssions });
@@ -79,6 +80,8 @@ namespace Squidex.Areas.Api.Controllers.Users.Models
{
AddPutLink("unlock", resources.Url