Skip to content

Commit

Permalink
release(1.7.0-RC2): merge release into main #323
Browse files Browse the repository at this point in the history
  • Loading branch information
Phil91 authored Nov 2, 2023
2 parents 11096f4 + c45575b commit 00f91aa
Show file tree
Hide file tree
Showing 48 changed files with 1,272 additions and 478 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

New features, fixed bugs, known defects and other noteworthy changes to each release of the Catena-X Portal Backend.

## 1.7.0-RC2

### Change
* Seeding Data
* updated technical user role description & user role names
* Others
* added email value validation for invitation, network registration and user invitation to enable the user input data validation for valid email

### Feature
n/a

### Technical Support
* Released extended error response message method (incl. error-type, error-code, a message-template and multiple parameters) and enabled the same for administration POST endpoints /userfile and registration GET endpoint /companyDetailsWithAddress

### Bugfix
* Adjusted the json property name for bpn within the BpdmLegalEntityOutputData
* Updated osp_welcome_email.html dynamic data field from idpAlias to companyName


## 1.7.0-RC1

### Change
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<Project>
<PropertyGroup>
<VersionPrefix>1.7.0</VersionPrefix>
<VersionSuffix>RC1</VersionSuffix>
<VersionSuffix>RC2</VersionSuffix>
</PropertyGroup>
</Project>
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,7 +20,9 @@
using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library;
using Org.Eclipse.TractusX.Portal.Backend.Framework.IO;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Linq;
using Org.Eclipse.TractusX.Portal.Backend.Keycloak.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
Expand All @@ -42,16 +43,18 @@ public class IdentityProviderBusinessLogic : IIdentityProviderBusinessLogic
private readonly IPortalRepositories _portalRepositories;
private readonly IProvisioningManager _provisioningManager;
private readonly IIdentityService _identityService;
private readonly IErrorMessageService _errorMessageService;
private readonly ILogger<IdentityProviderBusinessLogic> _logger;
private readonly IdentityProviderSettings _settings;

private static readonly Regex DisplayNameValidationExpression = new(@"^[a-zA-Z0-9\!\?\@\&\#\'\x22\(\)_\-\=\/\*\.\,\;\: ]+$", RegexOptions.None, TimeSpan.FromSeconds(1));

public IdentityProviderBusinessLogic(IPortalRepositories portalRepositories, IProvisioningManager provisioningManager, IIdentityService identityService, IOptions<IdentityProviderSettings> options, ILogger<IdentityProviderBusinessLogic> logger)
public IdentityProviderBusinessLogic(IPortalRepositories portalRepositories, IProvisioningManager provisioningManager, IIdentityService identityService, IErrorMessageService errorMessageService, IOptions<IdentityProviderSettings> options, ILogger<IdentityProviderBusinessLogic> logger)
{
_portalRepositories = portalRepositories;
_provisioningManager = provisioningManager;
_identityService = identityService;
_errorMessageService = errorMessageService;
_settings = options.Value;
_logger = logger;
}
Expand Down Expand Up @@ -653,9 +656,21 @@ private async ValueTask<IdentityProviderUpdateStats> UploadOwnCompanyUsersIdenti
var numErrors = errors.Count();
var numUnchanged = numLines - numProcessed - numErrors;

return new IdentityProviderUpdateStats(numProcessed, numUnchanged, numErrors, numLines, errors.Select(x => $"line: {x.Line}, message: {x.Error.Message}"));
return new IdentityProviderUpdateStats(
numProcessed,
numUnchanged,
numErrors,
numLines,
errors.Select(x => CreateUserUpdateError(x.Line, x.Error)));
}

private UserUpdateError CreateUserUpdateError(int line, Exception error) =>
error switch
{
DetailException detailException when detailException.HasDetails => new UserUpdateError(line, detailException.GetErrorMessage(_errorMessageService), detailException.GetErrorDetails(_errorMessageService)),
_ => new UserUpdateError(line, error.Message, Enumerable.Empty<ErrorDetails>())
};

private async IAsyncEnumerable<(bool, Exception?)> ProcessOwnCompanyUsersIdentityProviderLinkDataInternalAsync(
IAsyncEnumerable<(Guid CompanyUserId, UserProfile UserProfile, IEnumerable<IdentityProviderLink> IdentityProviderLinks)> userProfileLinkDatas,
IUserRepository userRepository,
Expand Down Expand Up @@ -927,11 +942,10 @@ private async IAsyncEnumerable<string> GetOwnCompanyUsersIdentityProviderDataLin
}
var identityProviderData = await _portalRepositories.GetInstance<IIdentityProviderRepository>().GetOwnCompanyIdentityProviderAliasDataUntracked(companyId, identityProviderIds).ToListAsync().ConfigureAwait(false);

var invalidIds = identityProviderIds.Except(identityProviderData.Select(data => data.IdentityProviderId));
if (invalidIds.Any())
identityProviderIds.Except(identityProviderData.Select(data => data.IdentityProviderId)).IfAny(invalidIds =>
{
throw new ControllerArgumentException($"invalid identityProviders: [{String.Join(", ", invalidIds)}] for company {companyId}", nameof(identityProviderIds));
}
throw new ControllerArgumentException($"invalid identityProviders: [{string.Join(", ", invalidIds)}] for company {companyId}", nameof(identityProviderIds));
});

return identityProviderData;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@
using Org.Eclipse.TractusX.Portal.Backend.Processes.NetworkRegistration.Library;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;

public class NetworkBusinessLogic : INetworkBusinessLogic
{
private static readonly Regex Name = new(ValidationExpressions.Name, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private static readonly Regex Email = new(ValidationExpressions.Email, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private static readonly Regex BpnRegex = new(ValidationExpressions.Bpn, RegexOptions.Compiled, TimeSpan.FromSeconds(1));

private readonly IPortalRepositories _portalRepositories;
Expand Down Expand Up @@ -285,9 +285,9 @@ public Task RetriggerProcessStep(Guid externalId, ProcessStepTypeId processStepT

private static void ValidateUsers(UserDetailData user)
{
if (string.IsNullOrWhiteSpace(user.Email) || !Email.IsMatch(user.Email))
if (string.IsNullOrWhiteSpace(user.Email) || !new EmailAddressAttribute().IsValid(user.Email))
{
throw new ControllerArgumentException("User must have a valid email address");
throw new ControllerArgumentException($"Mail {user.Email} must not be empty and have valid format");
}

if (string.IsNullOrWhiteSpace(user.FirstName) || !Name.IsMatch(user.FirstName))
Expand Down
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
@@ -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,8 +20,9 @@
using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library;
using Org.Eclipse.TractusX.Portal.Backend.Framework.IO;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Web;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Linq;
using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
Expand All @@ -39,23 +39,27 @@ public class UserUploadBusinessLogic : IUserUploadBusinessLogic
private readonly IMailingService _mailingService;
private readonly UserSettings _settings;
private readonly IIdentityService _identityService;
private readonly IErrorMessageService _errorMessageService;

/// <summary>
/// Constructor.
/// </summary>
/// <param name="userProvisioningService">User Provisioning Service</param>
/// <param name="mailingService">Mailing Service</param>
/// <param name="identityService">Access to the identity Service</param>
/// <param name="errorMessageService">ErrorMessage Service</param>
/// <param name="settings">Settings</param>
public UserUploadBusinessLogic(
IUserProvisioningService userProvisioningService,
IMailingService mailingService,
IIdentityService identityService,
IErrorMessageService errorMessageService,
IOptions<UserSettings> settings)
{
_userProvisioningService = userProvisioningService;
_mailingService = mailingService;
_identityService = identityService;
_errorMessageService = errorMessageService;
_settings = settings.Value;
}

Expand Down Expand Up @@ -109,7 +113,11 @@ await GetUserRoleDatas(parsed.Roles, validRoleData, identity.CompanyId).Configur
.Select(x => (x.CompanyUserId != Guid.Empty, x.Error)),
cancellationToken).ConfigureAwait(false);

return new UserCreationStats(numCreated, errors.Count(), numLines, errors.Select(x => $"line: {x.Line}, message: {x.Error.Message}"));
return new UserCreationStats(
numCreated,
errors.Count(),
numLines,
errors.Select(error => CreateUserCreationError(error.Line, error.Error)));
}

private async IAsyncEnumerable<(Guid CompanyUserId, string UserName, string? Password, Exception? Error)> CreateOwnCompanyIdpUsersWithEmailAsync(string nameCreatedBy, CompanyNameIdpAliasData companyNameIdpAliasData, IAsyncEnumerable<UserCreationRoleDataIdpInfo> userCreationInfos, [EnumeratorCancellation] CancellationToken cancellationToken)
Expand Down Expand Up @@ -234,17 +242,27 @@ await GetUserRoleDatas(parsed.Roles, validRoleData, identity.CompanyId).Configur
.Select(x => (x.CompanyUserId != Guid.Empty, x.Error)),
cancellationToken).ConfigureAwait(false);

return new UserCreationStats(numCreated, errors.Count(), numLines, errors.Select(x => $"line: {x.Line}, message: {x.Error.Message}"));
return new UserCreationStats(
numCreated,
errors.Count(),
numLines,
errors.Select(error => CreateUserCreationError(error.Line, error.Error)));
}

private UserCreationError CreateUserCreationError(int line, Exception error) =>
error switch
{
DetailException detailException when detailException.HasDetails => new UserCreationError(line, detailException.GetErrorMessage(_errorMessageService), detailException.GetErrorDetails(_errorMessageService)),
_ => new UserCreationError(line, error.Message, Enumerable.Empty<ErrorDetails>())
};

private async ValueTask<IEnumerable<UserRoleData>> GetUserRoleDatas(IEnumerable<string> roles, List<UserRoleData> validRoleData, Guid companyId)
{
var unknownRoles = roles.Except(validRoleData.Select(r => r.UserRoleText));
if (unknownRoles.Any())
if (roles.Except(validRoleData.Select(r => r.UserRoleText)).IfAny(
unknownRoles => _userProvisioningService.GetOwnCompanyPortalRoleDatas(_settings.Portal.KeycloakClientID, unknownRoles, companyId),
out var roleDataTask))
{
var roleData = await _userProvisioningService.GetOwnCompanyPortalRoleDatas(_settings.Portal.KeycloakClientID, unknownRoles, companyId)
.ConfigureAwait(false);

var roleData = await roleDataTask!.ConfigureAwait(false);
if (roleData != null)
{
validRoleData.AddRange(roleData);
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
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public CompanyInvitationData(string? userName, string firstName, string lastName
public string lastName { get; set; }

[DefaultValue("string")]
[RegularExpression(ValidationExpressions.Email, ErrorMessage = "Invalid email", MatchTimeoutInMilliseconds = 500)]
[EmailAddress]
[JsonPropertyName("email")]
public string email { get; set; }

Expand Down
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 @@ -18,6 +17,9 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

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

namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;

public record IdentityProviderUpdateStats(int Updated, int Unchanged, int Error, int Total, IEnumerable<string> Errors);
public record IdentityProviderUpdateStats(int Updated, int Unchanged, int Error, int Total, IEnumerable<UserUpdateError> Errors);
public record UserUpdateError(int Line, string Message, IEnumerable<ErrorDetails> Details);
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class OwnCompanyUserEditableDetails
public string? LastName { get; set; }

[DefaultValue("string")]
[RegularExpression(ValidationExpressions.Email, ErrorMessage = "Invalid email", MatchTimeoutInMilliseconds = 500)]
[EmailAddress]
[JsonPropertyName("email")]
public string? Email { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public record UserCreationInfoIdp(
[property: JsonPropertyName("lastName")]
string LastName,

[RegularExpression(ValidationExpressions.Email, ErrorMessage = "Invalid email", MatchTimeoutInMilliseconds = 500)]
[EmailAddress]
[property: JsonPropertyName("email")]
string Email,

Expand Down
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 @@ -18,6 +17,9 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

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

namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;

public record UserCreationStats(int Created, int Error, int Total, IEnumerable<string> Errors);
public record UserCreationStats(int Created, int Error, int Total, IEnumerable<UserCreationError> Errors);
public record UserCreationError(int Line, string Message, IEnumerable<ErrorDetails> Details);
8 changes: 8 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 All @@ -29,6 +31,7 @@
using Org.Eclipse.TractusX.Portal.Backend.Processes.OfferSubscription.Library.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service;

var VERSION = "v2";
Expand Down Expand Up @@ -78,5 +81,10 @@
.AddPartnerRegistration(builder.Configuration)
.AddNetworkRegistrationProcessHelper();
builder.Services
.AddSingleton<IErrorMessageService, ErrorMessageService>()
.AddSingleton<IErrorMessageContainer, AdministrationRegistrationErrorMessageContainer>()
.AddSingleton<IErrorMessageContainer, ProvisioningServiceErrorMessageContainer>();
builder.Services.AddProvisioningDBAccess(builder.Configuration);
});
Loading

0 comments on commit 00f91aa

Please sign in to comment.