From 586ca00e66e849b684e00e90b6d613c39153c559 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Mon, 27 Jan 2025 19:58:43 +0100 Subject: [PATCH] Error map (#1185) * Extract mongo code to own assembly. * Error Map. --- .../Actions/Algolia/AlgoliaActionHandler.cs | 5 +-- .../Controllers/Error/ErrorController.cs | 41 +++++++++++++++++-- .../Config/Authentication/OidcHandler.cs | 5 +++ .../src/Squidex/Config/MyIdentityOptions.cs | 2 + backend/src/Squidex/appsettings.json | 1 + 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/backend/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaActionHandler.cs b/backend/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaActionHandler.cs index 7cd9c61113..0faa5e526b 100644 --- a/backend/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaActionHandler.cs +++ b/backend/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaActionHandler.cs @@ -83,7 +83,7 @@ public sealed class AlgoliaActionHandler(RuleEventFormatter formatter, IScriptEn { AppId = action.AppId, ApiKey = action.ApiKey, - Content = serializer.Serialize(content, true), + Content = delete ? null : serializer.Serialize(content, true), ContentId = contentId, IndexName = indexName }; @@ -100,7 +100,6 @@ protected override async Task ExecuteJobAsync(AlgoliaJob job, } var index = await clients.GetClientAsync((job.AppId, job.ApiKey, job.IndexName)); - try { if (job.Content != null) @@ -147,5 +146,5 @@ public sealed class AlgoliaJob public string IndexName { get; set; } - public string Content { get; set; } + public string? Content { get; set; } } diff --git a/backend/src/Squidex/Areas/IdentityServer/Controllers/Error/ErrorController.cs b/backend/src/Squidex/Areas/IdentityServer/Controllers/Error/ErrorController.cs index 0191faf0ff..f2585360b7 100644 --- a/backend/src/Squidex/Areas/IdentityServer/Controllers/Error/ErrorController.cs +++ b/backend/src/Squidex/Areas/IdentityServer/Controllers/Error/ErrorController.cs @@ -5,15 +5,20 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System.Text.RegularExpressions; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using Squidex.Config; using Squidex.Infrastructure; namespace Squidex.Areas.IdentityServer.Controllers.Error; -public sealed class ErrorController : IdentityServerController +public sealed class ErrorController(IOptions identityOptions) : IdentityServerController { + private readonly MyIdentityOptions identityOptions = identityOptions.Value; + [Route("error/")] public async Task Error(string? errorId = null) { @@ -32,14 +37,12 @@ public async Task Error(string? errorId = null) } var source = HttpContext.Features.Get(); - if (source == null) { return View("Error", vm); } var exception = source.Error; - while (exception?.InnerException != null) { exception = exception.InnerException; @@ -49,10 +52,42 @@ public async Task Error(string? errorId = null) { vm.ErrorMessage = exception?.Message; } + else if (TryGetMappedError(exception, out var mappedError)) + { + vm.ErrorMessage = mappedError; + } return View("Error", vm); } + private bool TryGetMappedError(Exception? exception, out string message) + { + message = null!; + + if (exception == null || identityOptions.OidcErrorMap == null || identityOptions.OidcErrorMap.Count == 0) + { + return false; + } + + foreach (var (pattern, value) in identityOptions.OidcErrorMap) + { + try + { + if (Regex.IsMatch(exception.Message, pattern)) + { + message = value; + return true; + } + } + catch + { + continue; + } + } + + return false; + } + private static bool IsTestEndpoint(IExceptionHandlerFeature source) { return source.Endpoint is RouteEndpoint route && route.RoutePattern.RawText == "identity-server/test"; diff --git a/backend/src/Squidex/Config/Authentication/OidcHandler.cs b/backend/src/Squidex/Config/Authentication/OidcHandler.cs index aa8ecfa5be..9d2461b34b 100644 --- a/backend/src/Squidex/Config/Authentication/OidcHandler.cs +++ b/backend/src/Squidex/Config/Authentication/OidcHandler.cs @@ -34,6 +34,11 @@ public override Task TokenValidated(TokenValidatedContext context) return base.TokenValidated(context); } + public override Task AuthenticationFailed(AuthenticationFailedContext context) + { + return base.AuthenticationFailed(context); + } + public override Task RedirectToIdentityProviderForSignOut(RedirectContext context) { if (!string.IsNullOrEmpty(options.OidcOnSignoutRedirectUrl)) diff --git a/backend/src/Squidex/Config/MyIdentityOptions.cs b/backend/src/Squidex/Config/MyIdentityOptions.cs index da1bc94b30..b2b36c6a62 100644 --- a/backend/src/Squidex/Config/MyIdentityOptions.cs +++ b/backend/src/Squidex/Config/MyIdentityOptions.cs @@ -55,6 +55,8 @@ public sealed class MyIdentityOptions public string OidcResponseType { get; set; } + public Dictionary? OidcErrorMap { get; set; } + public string? OidcOnSignoutRedirectUrl { get; set; } public string[] OidcScopes { get; set; } diff --git a/backend/src/Squidex/appsettings.json b/backend/src/Squidex/appsettings.json index e3002de923..536554b551 100644 --- a/backend/src/Squidex/appsettings.json +++ b/backend/src/Squidex/appsettings.json @@ -651,6 +651,7 @@ "oidcClient": "", "oidcSecret": "", "oidcPrompt": null, + "oidcErrorMap": null, "oidcMetadataAddress": "", "oidcScopes": [ "email"