Skip to content

Commit

Permalink
feat(errorhandling)! enhance exceptions with details for errortype, e…
Browse files Browse the repository at this point in the history
…rrorcode and parameters (#315)

add new exceptions for errortype, errorcode and parameters
-------
Refs: CPLP-3090
Reviewed-By: Phil Schneider <[email protected]>
  • Loading branch information
ntruchsess authored Oct 31, 2023
1 parent 5d1b233 commit 897f8bc
Show file tree
Hide file tree
Showing 19 changed files with 441 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Administration.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
using Org.Eclipse.TractusX.Portal.Backend.Clearinghouse.Library.BusinessLogic;
using Org.Eclipse.TractusX.Portal.Backend.Clearinghouse.Library.Models;
Expand Down Expand Up @@ -82,7 +83,7 @@ private async Task<CompanyWithAddressData> GetCompanyWithAddressAsyncInternal(Gu
var companyWithAddress = await _portalRepositories.GetInstance<IApplicationRepository>().GetCompanyUserRoleWithAddressUntrackedAsync(applicationId).ConfigureAwait(false);
if (companyWithAddress == null)
{
throw new NotFoundException($"applicationId {applicationId} not found");
throw NotFoundException.Create(AdministrationRegistrationErrors.APPLICATION_NOT_FOUND, new ErrorParameter[] { new("applicationId", applicationId.ToString()) });
}
return new CompanyWithAddressData(
companyWithAddress.CompanyId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/********************************************************************************
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library;
using System.Collections.Immutable;

namespace Org.Eclipse.TractusX.Portal.Backend.Administration.ErrorHandling;

public class AdministrationRegistrationErrorMessageContainer : IErrorMessageContainer
{
private static readonly IReadOnlyDictionary<int, string> _messageContainer = new Dictionary<AdministrationRegistrationErrors, string> {
{ AdministrationRegistrationErrors.APPLICATION_NOT_FOUND, "application {applicationId} does not exist" }
}.ToImmutableDictionary(x => (int)x.Key, x => x.Value);

public Type Type { get => typeof(AdministrationRegistrationErrors); }
public IReadOnlyDictionary<int, string> MessageContainer { get => _messageContainer; }
}

public enum AdministrationRegistrationErrors
{
APPLICATION_NOT_FOUND
}
6 changes: 6 additions & 0 deletions src/administration/Administration.Service/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.Administration.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Web;
using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail;
using Org.Eclipse.TractusX.Portal.Backend.Notifications.Library;
Expand Down Expand Up @@ -78,5 +80,9 @@
.AddPartnerRegistration(builder.Configuration)
.AddNetworkRegistrationProcessHelper();

builder.Services
.AddSingleton<IErrorMessageService, ErrorMessageService>()
.AddSingleton<IErrorMessageContainer, AdministrationRegistrationErrorMessageContainer>();

builder.Services.AddProvisioningDBAccess(builder.Configuration);
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand All @@ -21,12 +20,19 @@
namespace Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;

[Serializable]
public class ConfigurationException : Exception
public class ConfigurationException : DetailException
{
public ConfigurationException() { }
public ConfigurationException() : base() { }
public ConfigurationException(string message) : base(message) { }
public ConfigurationException(string message, Exception inner) : base(message, inner) { }
protected ConfigurationException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }

protected ConfigurationException(Type errorType, int errorCode, IEnumerable<ErrorParameter>? parameters = null, Exception? inner = null) : base(errorType, errorCode, parameters, inner) { }

public static ConfigurationException Create<T>(T error, IEnumerable<ErrorParameter>? parameters = null, Exception? inner = null) where T : Enum =>
new(typeof(T), ValueOf(error), parameters, inner);
public static ConfigurationException Create<T>(T error, Exception inner) where T : Enum =>
new(typeof(T), ValueOf(error), null, inner);
}
14 changes: 10 additions & 4 deletions src/framework/Framework.ErrorHandling.Library/ConflictException.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand All @@ -21,12 +20,19 @@
namespace Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;

[Serializable]
public class ConflictException : Exception
public class ConflictException : DetailException
{
public ConflictException() { }
public ConflictException() : base() { }
public ConflictException(string message) : base(message) { }
public ConflictException(string message, System.Exception inner) : base(message, inner) { }
public ConflictException(string message, Exception inner) : base(message, inner) { }
protected ConflictException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }

protected ConflictException(Type errorType, int errorCode, IEnumerable<ErrorParameter>? parameters = null, Exception? inner = null) : base(errorType, errorCode, parameters, inner) { }

public static ConflictException Create<T>(T error, IEnumerable<ErrorParameter>? parameters = null, Exception? inner = null) where T : Enum =>
new(typeof(T), ValueOf(error), parameters, inner);
public static ConflictException Create<T>(T error, Exception inner) where T : Enum =>
new(typeof(T), ValueOf(error), null, inner);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand All @@ -22,18 +21,14 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;

/// <inheritdoc />
[Serializable]
public class ControllerArgumentException : Exception
public class ControllerArgumentException : DetailException
{
public ControllerArgumentException(string message) : base(message) { }
public ControllerArgumentException() : base() { }

public ControllerArgumentException(ArgumentException argumentException)
: this(argumentException.Message)
{
ParamName = argumentException.ParamName;
}
public ControllerArgumentException(string message) : base(message) { }

public ControllerArgumentException(string message, string paramName)
: base(String.Format("{0} (Parameter '{1}')", message, paramName))
: base(string.Format("{0} (Parameter '{1}')", message, paramName))
{
ParamName = paramName;
}
Expand All @@ -43,4 +38,18 @@ public ControllerArgumentException(string message, string paramName)
protected ControllerArgumentException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }

protected ControllerArgumentException(Type errorType, int errorCode, IEnumerable<ErrorParameter>? parameters = null, string? paramName = null, Exception? inner = null) : base(errorType, errorCode, parameters, inner)
{
ParamName = paramName;
}

public static ControllerArgumentException Create<T>(T error, IEnumerable<ErrorParameter>? parameters = null, string? paramName = null, Exception? inner = null) where T : Enum =>
new(typeof(T), ValueOf(error), parameters, paramName, inner);
public static ControllerArgumentException Create<T>(T error, Exception inner) where T : Enum =>
new(typeof(T), ValueOf(error), null, null, inner);
public static ControllerArgumentException Create<T>(T error, IEnumerable<ErrorParameter> parameters, Exception inner) where T : Enum =>
new(typeof(T), ValueOf(error), parameters, null, inner);
public static ControllerArgumentException Create<T>(T error, string paramName, Exception? inner = null) where T : Enum =>
new(typeof(T), ValueOf(error), null, paramName, inner);
}
80 changes: 80 additions & 0 deletions src/framework/Framework.ErrorHandling.Library/DetailException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/********************************************************************************
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library;
using System.Text.RegularExpressions;

namespace Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;

[Serializable]
public abstract class DetailException : Exception
{
private static readonly Regex _templateMatcherExpression = new Regex(@"\{(\w+)\}", RegexOptions.None, TimeSpan.FromSeconds(1)); // to replace any text surrounded by { and }
private enum NoDetailsErrorType
{
NONE = 0
}

protected DetailException() : base() { }
protected DetailException(string message) : base(message) { }
protected DetailException(string message, Exception inner) : base(message, inner) { }
protected DetailException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }

protected DetailException(
Type errorType, int errorCode, IEnumerable<ErrorParameter>? parameters, Exception? inner) : base(Enum.GetName(errorType, errorCode), inner)
{
ErrorType = errorType;
ErrorCode = errorCode;
Parameters = parameters ?? Enumerable.Empty<ErrorParameter>();
}

protected static int ValueOf<T>(T error) where T : Enum => (int)Convert.ChangeType(error, TypeCode.Int32);

public Type ErrorType { get; } = typeof(NoDetailsErrorType);
public int ErrorCode { get; } = (int)NoDetailsErrorType.NONE;
public IEnumerable<ErrorParameter> Parameters { get; } = Enumerable.Empty<ErrorParameter>();
public bool HasDetails { get => ErrorType != typeof(NoDetailsErrorType); }

public string GetErrorMessage(IErrorMessageService messageService) =>
_templateMatcherExpression.Replace(
messageService.GetMessage(ErrorType, ErrorCode),
m => Parameters.SingleOrDefault(x => x.Name == m.Groups[1].Value)?.Value ?? "null");

public IEnumerable<ErrorDetails> GetErrorDetails(IErrorMessageService messageService) =>
GetDetailExceptions().Select(x =>
new ErrorDetails(
x.Message,
x.ErrorType.Name,
messageService.GetMessage(x.ErrorType, x.ErrorCode),
x.Parameters));

private IEnumerable<DetailException> GetDetailExceptions()
{
yield return this;
var inner = InnerException;
while (inner is not null)
{
if (inner is DetailException detail && detail.ErrorType != typeof(NoDetailsErrorType))
yield return detail;
inner = inner.InnerException;
}
}
}
32 changes: 32 additions & 0 deletions src/framework/Framework.ErrorHandling.Library/ErrorDetails.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/********************************************************************************
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

namespace Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;

public record ErrorDetails(
string ErrorCode,
string Type,
string Message,
IEnumerable<ErrorParameter> Parameters
);

public record ErrorParameter(
string Name,
string Value
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
Expand All @@ -21,12 +20,19 @@
namespace Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;

[Serializable]
public class ForbiddenException : Exception
public class ForbiddenException : DetailException
{
public ForbiddenException() { }
public ForbiddenException() : base() { }
public ForbiddenException(string message) : base(message) { }
public ForbiddenException(string message, System.Exception inner) : base(message, inner) { }
public ForbiddenException(string message, Exception inner) : base(message, inner) { }
protected ForbiddenException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }

protected ForbiddenException(Type errorType, int errorCode, IEnumerable<ErrorParameter>? parameters = null, Exception? inner = null) : base(errorType, errorCode, parameters, inner) { }

public static ForbiddenException Create<T>(T error, IEnumerable<ErrorParameter>? parameters = null, Exception? inner = null) where T : Enum =>
new(typeof(T), ValueOf(error), parameters, inner);
public static ForbiddenException Create<T>(T error, Exception inner) where T : Enum =>
new(typeof(T), ValueOf(error), null, inner);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/********************************************************************************
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using System.Collections.Immutable;

namespace Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library;

public sealed class ErrorMessageService : IErrorMessageService
{
private readonly IReadOnlyDictionary<Type, IReadOnlyDictionary<int, string>> _messageContainers;

public ErrorMessageService(IEnumerable<IErrorMessageContainer> errorMessageContainers)
{
_messageContainers = errorMessageContainers.ToImmutableDictionary(x => x.Type, x => x.MessageContainer);
}

public string GetMessage(Type type, int code)
{
if (!_messageContainers.TryGetValue(type, out var container))
throw new ArgumentException($"unexpected type {type.Name}");

if (!container.TryGetValue(code, out var message))
throw new ArgumentException($"no message defined for {type.Name}.{Enum.GetName(type, code)}");

return message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/********************************************************************************
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

namespace Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library;

public record ErrorResponse(
string Type,
string Title,
int Status,
IDictionary<string, IEnumerable<string>> Errors,
string ErrorId,
IEnumerable<ErrorDetails>? Details
);
Loading

0 comments on commit 897f8bc

Please sign in to comment.