diff --git a/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs
index fc8a9b769f..0cf42b585b 100644
--- a/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs
@@ -45,7 +45,6 @@ public class CompanyDataBusinessLogic(
{
private static readonly Regex BpnsRegex = new(ValidationExpressions.Bpns, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private static readonly Regex EcmRegex = new(ValidationExpressions.ExternalCertificateNumber, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
- private static readonly Regex Company = new(ValidationExpressions.Company, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private readonly IIdentityData _identityData = identityService.IdentityData;
private readonly CompanyDataSettings _settings = options.Value;
@@ -267,9 +266,9 @@ public async Task CreateCompanyCertificate(CompanyCertificateCreationData data,
throw new ControllerArgumentException("ValidTill date should be greater than current date");
}
- if (data.Issuer != null && !Company.IsMatch(data.Issuer!))
+ if (data.Issuer != null && !data.Issuer.IsValidCompanyName())
{
- throw new ControllerArgumentException("Issuer length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the company name");
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", nameof(data.Issuer))]);
}
var documentContentType = data.Document.ContentType.ParseMediaTypeId();
diff --git a/src/administration/Administration.Service/BusinessLogic/InvitationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/InvitationBusinessLogic.cs
index 289b5ef6a6..49bb0bca7d 100644
--- a/src/administration/Administration.Service/BusinessLogic/InvitationBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/InvitationBusinessLogic.cs
@@ -24,13 +24,11 @@
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
using Org.Eclipse.TractusX.Portal.Backend.Processes.Library;
-using System.Text.RegularExpressions;
namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;
public class InvitationBusinessLogic : IInvitationBusinessLogic
{
- private static readonly Regex Company = new(ValidationExpressions.Company, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private readonly IPortalRepositories _portalRepositories;
///
@@ -50,14 +48,9 @@ public Task ExecuteInvitation(CompanyInvitationData invitationData)
throw new ControllerArgumentException("email must not be empty", "email");
}
- if (string.IsNullOrWhiteSpace(invitationData.OrganisationName))
+ if (invitationData.OrganisationName == null || !invitationData.OrganisationName.IsValidCompanyName())
{
- throw new ControllerArgumentException("organisationName must not be empty", "organisationName");
- }
-
- if (!string.IsNullOrEmpty(invitationData.OrganisationName) && !Company.IsMatch(invitationData.OrganisationName))
- {
- throw new ControllerArgumentException("OrganisationName length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the Organisation name", "organisationName");
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", nameof(invitationData.OrganisationName))]);
}
return ExecuteInvitationInternalAsync(invitationData);
diff --git a/src/administration/Administration.Service/BusinessLogic/NetworkBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/NetworkBusinessLogic.cs
index 91cbe4a288..7550d8803d 100644
--- a/src/administration/Administration.Service/BusinessLogic/NetworkBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/NetworkBusinessLogic.cs
@@ -47,16 +47,14 @@ public class NetworkBusinessLogic(
{
private static readonly Regex Name = new(ValidationExpressions.Name, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private static readonly Regex ExternalId = new("^[A-Za-z0-9\\-+_/,.]{6,36}$", RegexOptions.Compiled, TimeSpan.FromSeconds(1));
- private static readonly Regex Company = new(ValidationExpressions.Company, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
-
private readonly IIdentityData _identityData = identityService.IdentityData;
private readonly PartnerRegistrationSettings _settings = options.Value;
public async Task HandlePartnerRegistration(PartnerRegistrationData data)
{
- if (!string.IsNullOrEmpty(data.Name) && !Company.IsMatch(data.Name))
+ if (!data.Name.IsValidCompanyName())
{
- throw new ControllerArgumentException("OrganisationName length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the Organisation name", "organisationName");
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", "OrganisationName")]);
}
var ownerCompanyId = _identityData.CompanyId;
diff --git a/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs
index df02c3c6b0..9b1b59e811 100644
--- a/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs
@@ -63,7 +63,6 @@ public sealed class RegistrationBusinessLogic(
: IRegistrationBusinessLogic
{
private static readonly Regex BpnRegex = new(ValidationExpressions.Bpn, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
- private static readonly Regex Company = new(ValidationExpressions.Company, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private readonly IIdentityData _identityData = identityService.IdentityData;
private readonly RegistrationSettings _settings = configuration.Value;
@@ -85,9 +84,9 @@ private async Task GetCompanyWithAddressAsyncInternal(Gu
{
throw NotFoundException.Create(AdministrationRegistrationErrors.APPLICATION_NOT_FOUND, [new("applicationId", applicationId.ToString())]);
}
- if (!string.IsNullOrEmpty(companyWithAddress.Name) && !Company.IsMatch(companyWithAddress.Name))
+ if (!companyWithAddress.Name.IsValidCompanyName())
{
- throw new ControllerArgumentException("OrganisationName length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the Organisation name", "organisationName");
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", "OrganisationName")]);
}
return new CompanyWithAddressData(
@@ -124,9 +123,9 @@ private async Task GetCompanyWithAddressAsyncInternal(Gu
public Task> GetCompanyApplicationDetailsAsync(int page, int size, CompanyApplicationStatusFilter? companyApplicationStatusFilter, string? companyName)
{
- if (!string.IsNullOrEmpty(companyName) && !Company.IsMatch(companyName))
+ if (companyName != null && !companyName.IsValidCompanyName())
{
- throw new ControllerArgumentException("CompanyName length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the company name", nameof(companyName));
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", "CompanyName")]);
}
var applications = portalRepositories.GetInstance()
.GetCompanyApplicationsFilteredQuery(
@@ -164,9 +163,9 @@ private async Task GetCompanyWithAddressAsyncInternal(Gu
public Task> GetOspCompanyDetailsAsync(int page, int size, CompanyApplicationStatusFilter? companyApplicationStatusFilter, string? companyName)
{
- if (!string.IsNullOrEmpty(companyName) && !Company.IsMatch(companyName))
+ if (companyName != null && !companyName.IsValidCompanyName())
{
- throw new ControllerArgumentException("CompanyName length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the company name", nameof(companyName));
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", "CompanyName")]);
}
var applications = portalRepositories.GetInstance()
.GetExternalCompanyApplicationsFilteredQuery(_identityData.CompanyId,
@@ -199,9 +198,9 @@ private async Task GetCompanyWithAddressAsyncInternal(Gu
}
public Task> GetAllCompanyApplicationsDetailsAsync(int page, int size, string? companyName)
{
- if (!string.IsNullOrEmpty(companyName) && !Company.IsMatch(companyName))
+ if (companyName != null && !companyName.IsValidCompanyName())
{
- throw new ControllerArgumentException("CompanyName length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the company name", nameof(companyName));
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", "CompanyName")]);
}
var applications = portalRepositories.GetInstance().GetAllCompanyApplicationsDetailsQuery(companyName);
diff --git a/src/administration/Administration.Service/Program.cs b/src/administration/Administration.Service/Program.cs
index a6868d2408..3f366431c3 100644
--- a/src/administration/Administration.Service/Program.cs
+++ b/src/administration/Administration.Service/Program.cs
@@ -21,6 +21,7 @@
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Service;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.Portal.Backend.IssuerComponent.Library.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Notifications.Library;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
@@ -94,7 +95,8 @@ await WebAppHelper
.AddSingleton()
.AddSingleton()
.AddSingleton()
- .AddSingleton();
+ .AddSingleton()
+ .AddSingleton();
builder.Services.AddProvisioningDBAccess(builder.Configuration);
}).ConfigureAwait(ConfigureAwaitOptions.None);
diff --git a/src/framework/Framework.Async/Directory.Build.props b/src/framework/Framework.Async/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.Async/Directory.Build.props
+++ b/src/framework/Framework.Async/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.Cors/Directory.Build.props b/src/framework/Framework.Cors/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.Cors/Directory.Build.props
+++ b/src/framework/Framework.Cors/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.DBAccess/Directory.Build.props b/src/framework/Framework.DBAccess/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.DBAccess/Directory.Build.props
+++ b/src/framework/Framework.DBAccess/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.DateTimeProvider/Directory.Build.props b/src/framework/Framework.DateTimeProvider/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.DateTimeProvider/Directory.Build.props
+++ b/src/framework/Framework.DateTimeProvider/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.DependencyInjection/Directory.Build.props b/src/framework/Framework.DependencyInjection/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.DependencyInjection/Directory.Build.props
+++ b/src/framework/Framework.DependencyInjection/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.ErrorHandling.Controller/Directory.Build.props b/src/framework/Framework.ErrorHandling.Controller/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.ErrorHandling.Controller/Directory.Build.props
+++ b/src/framework/Framework.ErrorHandling.Controller/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.ErrorHandling.Web/Directory.Build.props b/src/framework/Framework.ErrorHandling.Web/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.ErrorHandling.Web/Directory.Build.props
+++ b/src/framework/Framework.ErrorHandling.Web/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.ErrorHandling/Directory.Build.props b/src/framework/Framework.ErrorHandling/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.ErrorHandling/Directory.Build.props
+++ b/src/framework/Framework.ErrorHandling/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.HttpClientExtensions/Directory.Build.props b/src/framework/Framework.HttpClientExtensions/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.HttpClientExtensions/Directory.Build.props
+++ b/src/framework/Framework.HttpClientExtensions/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.IO/Directory.Build.props b/src/framework/Framework.IO/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.IO/Directory.Build.props
+++ b/src/framework/Framework.IO/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.Linq/Directory.Build.props b/src/framework/Framework.Linq/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.Linq/Directory.Build.props
+++ b/src/framework/Framework.Linq/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.Logging/Directory.Build.props b/src/framework/Framework.Logging/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.Logging/Directory.Build.props
+++ b/src/framework/Framework.Logging/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.Models/Directory.Build.props b/src/framework/Framework.Models/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.Models/Directory.Build.props
+++ b/src/framework/Framework.Models/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.Models/ValidationExpressionErrorMessages.cs b/src/framework/Framework.Models/ValidationExpressionErrorMessages.cs
new file mode 100644
index 0000000000..e06fe4fb98
--- /dev/null
+++ b/src/framework/Framework.Models/ValidationExpressionErrorMessages.cs
@@ -0,0 +1,40 @@
+/********************************************************************************
+ * Copyright (c) 2024 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.Service;
+using System.Collections.Immutable;
+
+namespace Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
+
+// This class contains error messages for validation expressions
+public class ValidationExpressionErrorMessageContainer : IErrorMessageContainer
+{
+ private static readonly IReadOnlyDictionary _messageContainer = new Dictionary {
+ { ValidationExpressionErrors.INCORRECT_COMPANY_NAME, "{name}: length must be between 1 and 160 characters and not start or end with a white space" },
+
+ }.ToImmutableDictionary(x => (int)x.Key, x => x.Value);
+
+ public Type Type { get => typeof(ValidationExpressionErrors); }
+ public IReadOnlyDictionary MessageContainer { get => _messageContainer; }
+}
+
+public enum ValidationExpressionErrors
+{
+ INCORRECT_COMPANY_NAME
+}
diff --git a/src/framework/Framework.Models/ValidationExpressions.cs b/src/framework/Framework.Models/ValidationExpressions.cs
index 5755887180..c4d265d744 100644
--- a/src/framework/Framework.Models/ValidationExpressions.cs
+++ b/src/framework/Framework.Models/ValidationExpressions.cs
@@ -24,6 +24,6 @@ public static class ValidationExpressions
public const string Name = @"^.+$";
public const string Bpn = @"^(BPNL|bpnl)[\w|\d]{12}$";
public const string Bpns = @"^(BPNS|bpns)[\w|\d]{12}$";
- public const string Company = @"^\d*?[A-Za-zÀ-ÿ]\d?([A-Za-z0-9À-ÿ-_+=.,:;!?'\x22@()]\s?){2,40}$";
+ public const string Company = @"^(?!.*\s$)([\wÀ-ÿ£$€¥¢@%*+\-/\\,.:;=<>!?&^#'\x22()[\]]\s?){1,160}$";
public const string ExternalCertificateNumber = @"^[a-zA-Z0-9]{0,36}$";
}
diff --git a/src/framework/Framework.Models/ValidationExpressionsValidator.cs b/src/framework/Framework.Models/ValidationExpressionsValidator.cs
new file mode 100644
index 0000000000..1e62a06aec
--- /dev/null
+++ b/src/framework/Framework.Models/ValidationExpressionsValidator.cs
@@ -0,0 +1,31 @@
+/********************************************************************************
+ * Copyright (c) 2024 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.Text.RegularExpressions;
+
+namespace Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
+
+public static class ValidationExpressionsValidator
+{
+ private static readonly Regex CompanyRegex = new(ValidationExpressions.Company, RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture, TimeSpan.FromSeconds(1));
+ public static bool IsValidCompanyName(this string companyName)
+ {
+ return CompanyRegex.IsMatch(companyName);
+ }
+}
diff --git a/src/framework/Framework.Seeding/Directory.Build.props b/src/framework/Framework.Seeding/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.Seeding/Directory.Build.props
+++ b/src/framework/Framework.Seeding/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.Swagger/Directory.Build.props b/src/framework/Framework.Swagger/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.Swagger/Directory.Build.props
+++ b/src/framework/Framework.Swagger/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.Token/Directory.Build.props b/src/framework/Framework.Token/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.Token/Directory.Build.props
+++ b/src/framework/Framework.Token/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/framework/Framework.Web/Directory.Build.props b/src/framework/Framework.Web/Directory.Build.props
index f53f08f151..416bf1cdf9 100644
--- a/src/framework/Framework.Web/Directory.Build.props
+++ b/src/framework/Framework.Web/Directory.Build.props
@@ -19,7 +19,7 @@
- 2.5.0
+ 2.6.0
diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs
index 2e5914d16f..b61d226008 100644
--- a/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs
+++ b/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs
@@ -31,7 +31,6 @@
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities;
-using System.Text.RegularExpressions;
namespace Org.Eclipse.TractusX.Portal.Backend.Apps.Service.BusinessLogic;
@@ -40,7 +39,6 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Apps.Service.BusinessLogic;
///
public class AppReleaseBusinessLogic : IAppReleaseBusinessLogic
{
- private static readonly Regex Company = new(ValidationExpressions.Company, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private readonly IPortalRepositories _portalRepositories;
private readonly AppsSettings _settings;
private readonly IOfferService _offerService;
@@ -189,9 +187,9 @@ public Task AddAppAsync(AppRequestModel appRequestModel)
throw new ControllerArgumentException("Use Case Ids must not be null or empty", nameof(appRequestModel.UseCaseIds));
}
- if (!string.IsNullOrEmpty(appRequestModel.Provider) && !Company.IsMatch(appRequestModel.Provider))
+ if (appRequestModel.Provider != null && !appRequestModel.Provider.IsValidCompanyName())
{
- throw new ControllerArgumentException("Provider length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the Organisation name", nameof(appRequestModel.Provider));
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", nameof(appRequestModel.Provider))]);
}
return CreateAppAsync(appRequestModel);
@@ -269,9 +267,9 @@ public async Task UpdateAppReleaseAsync(Guid appId, AppRequestModel appRequestMo
throw new ForbiddenException($"Company {companyId} is not the app provider.");
}
- if (!string.IsNullOrEmpty(appRequestModel.Provider) && !Company.IsMatch(appRequestModel.Provider))
+ if (appRequestModel.Provider != null && !appRequestModel.Provider.IsValidCompanyName())
{
- throw new ControllerArgumentException("Provider length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the Organisation name", nameof(appRequestModel.Provider));
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", nameof(appRequestModel.Provider))]);
}
if (appRequestModel.SalesManagerId.HasValue)
diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs
index b33d9ccea0..4bbe253efc 100644
--- a/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs
+++ b/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs
@@ -30,7 +30,6 @@
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities;
-using System.Text.RegularExpressions;
namespace Org.Eclipse.TractusX.Portal.Backend.Apps.Service.BusinessLogic;
@@ -39,7 +38,6 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Apps.Service.BusinessLogic;
///
public class AppsBusinessLogic : IAppsBusinessLogic
{
- private static readonly Regex Company = new(ValidationExpressions.Company, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private readonly IPortalRepositories _portalRepositories;
private readonly IOfferSubscriptionService _offerSubscriptionService;
private readonly AppsSettings _settings;
@@ -158,9 +156,9 @@ public async Task AddFavouriteAppForUserAsync(Guid appId)
///
public async Task> GetCompanyProvidedAppSubscriptionStatusesForUserAsync(int page, int size, SubscriptionStatusSorting? sorting, OfferSubscriptionStatusId? statusId, Guid? offerId, string? companyName = null)
{
- if (!string.IsNullOrWhiteSpace(companyName) && !Company.IsMatch(companyName))
+ if (companyName != null && !companyName.IsValidCompanyName())
{
- throw new ControllerArgumentException("CompanyName length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the company name");
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", "CompanyName")]);
}
async Task?> GetCompanyProvidedAppSubscriptionStatusData(int skip, int take)
diff --git a/src/marketplace/Apps.Service/Program.cs b/src/marketplace/Apps.Service/Program.cs
index 1ba4cf95e1..a2be778650 100644
--- a/src/marketplace/Apps.Service/Program.cs
+++ b/src/marketplace/Apps.Service/Program.cs
@@ -19,6 +19,8 @@
using Org.Eclipse.TractusX.Portal.Backend.Apps.Service.BusinessLogic;
using Org.Eclipse.TractusX.Portal.Backend.Dim.Library.DependencyInjection;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Service;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.Portal.Backend.Notifications.Library;
using Org.Eclipse.TractusX.Portal.Backend.Offers.Library.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Service;
@@ -48,6 +50,8 @@ await WebAppHelper
.AddTransient()
.AddTransient()
.AddTransient()
+ .AddSingleton()
+ .AddSingleton()
.AddTechnicalUserProfile()
.ConfigureAppsSettings(builder.Configuration.GetSection("AppMarketPlace"))
.AddOfferDocumentServices();
diff --git a/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs b/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs
index c3f87b85e0..366cc59eea 100644
--- a/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs
+++ b/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs
@@ -29,7 +29,6 @@
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities;
using Org.Eclipse.TractusX.Portal.Backend.Services.Service.ViewModels;
-using System.Text.RegularExpressions;
namespace Org.Eclipse.TractusX.Portal.Backend.Services.Service.BusinessLogic;
@@ -38,7 +37,6 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Services.Service.BusinessLogic;
///
public class ServiceBusinessLogic : IServiceBusinessLogic
{
- private static readonly Regex Company = new(ValidationExpressions.Company, RegexOptions.Compiled, TimeSpan.FromSeconds(1));
private readonly IPortalRepositories _portalRepositories;
private readonly IOfferService _offerService;
private readonly IOfferSubscriptionService _offerSubscriptionService;
@@ -135,9 +133,9 @@ public Task AutoSetupServiceAsync(OfferAutoSetupData
///
public async Task> GetCompanyProvidedServiceSubscriptionStatusesForUserAsync(int page, int size, SubscriptionStatusSorting? sorting, OfferSubscriptionStatusId? statusId, Guid? offerId, string? companyName = null)
{
- if (!string.IsNullOrEmpty(companyName) && !Company.IsMatch(companyName))
+ if (companyName != null && !companyName.IsValidCompanyName())
{
- throw new ControllerArgumentException("CompanyName length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the company name");
+ throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", "CompanyName")]);
}
async Task?> GetCompanyProvidedAppSubscriptionStatusData(int skip, int take)
{
diff --git a/src/marketplace/Services.Service/Program.cs b/src/marketplace/Services.Service/Program.cs
index 43ca334e85..3ed8f2ef65 100644
--- a/src/marketplace/Services.Service/Program.cs
+++ b/src/marketplace/Services.Service/Program.cs
@@ -18,6 +18,8 @@
********************************************************************************/
using Org.Eclipse.TractusX.Portal.Backend.Dim.Library.DependencyInjection;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Service;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.Portal.Backend.Notifications.Library;
using Org.Eclipse.TractusX.Portal.Backend.Offers.Library.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Web.DependencyInjection;
@@ -48,6 +50,8 @@ await WebAppHelper
.AddServiceBusinessLogic(builder.Configuration)
.AddTransient()
.AddTransient()
+ .AddSingleton()
+ .AddSingleton()
.AddTechnicalUserProfile()
.AddOfferDocumentServices();
diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs
index f4e7fb44cb..4a88b22a2a 100644
--- a/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs
+++ b/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs
@@ -885,7 +885,7 @@ public async Task CheckCompanyCertificateType_WithInvalidCall_ThrowsControllerFo
var file = FormFileHelper.GetFormFile("test content", "test.pdf", MediaTypeId.PDF.MapToMediaType());
var externalCertificateNumber = "2345678";
var sites = new[] { "BPNS00000003CRHK" };
- var data = new CompanyCertificateCreationData(CompanyCertificateTypeId.IATF, file, externalCertificateNumber, sites, _now.AddMicroseconds(-1), _now.AddMicroseconds(1), "+ACC");
+ var data = new CompanyCertificateCreationData(CompanyCertificateTypeId.IATF, file, externalCertificateNumber, sites, _now.AddMicroseconds(-1), _now.AddMicroseconds(1), " +ACC");
A.CallTo(() => _companyCertificateRepository.CheckCompanyCertificateType(CompanyCertificateTypeId.IATF))
.Returns(false);
@@ -895,7 +895,7 @@ public async Task CheckCompanyCertificateType_WithInvalidCall_ThrowsControllerFo
// Assert
var ex = await Assert.ThrowsAsync(Act);
- ex.Message.Should().Be($"Issuer length must be 3-40 characters and *+=#%\\s not used as one of the first three characters in the company name");
+ ex.Message.Should().Be(ValidationExpressionErrors.INCORRECT_COMPANY_NAME.ToString());
}
#endregion
diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/InvitationBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/InvitationBusinessLogicTests.cs
index d36048f7d1..43c3c8d195 100644
--- a/tests/administration/Administration.Service.Tests/BusinessLogic/InvitationBusinessLogicTests.cs
+++ b/tests/administration/Administration.Service.Tests/BusinessLogic/InvitationBusinessLogicTests.cs
@@ -20,6 +20,7 @@
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
@@ -71,23 +72,6 @@ public async Task ExecuteInvitation_WithoutEmail_ThrowsControllerArgumentExcepti
ex.ParamName.Should().Be("email");
}
- [Fact]
- public async Task ExecuteInvitation_WithoutOrganisationName_ThrowsControllerArgumentException()
- {
- var invitationData = _fixture.Build()
- .With(x => x.OrganisationName, (string?)null)
- .WithNamePattern(x => x.FirstName)
- .WithNamePattern(x => x.LastName)
- .WithEmailPattern(x => x.Email)
- .Create();
-
- async Task Act() => await _sut.ExecuteInvitation(invitationData);
-
- var ex = await Assert.ThrowsAsync(Act);
- ex.Message.Should().Be("organisationName must not be empty (Parameter 'organisationName')");
- ex.ParamName.Should().Be("organisationName");
- }
-
[Fact]
public async Task ExecuteInvitation_WithValidData_CreatesExpected()
{
@@ -112,6 +96,48 @@ public async Task ExecuteInvitation_WithValidData_CreatesExpected()
invitations.Should().ContainSingle().And.Satisfy(x => x.ProcessId == processes.Single().Id && x.UserName == "testUserName");
}
+ [Theory]
+ [InlineData("ValidOrganisationName123")]
+ [InlineData("Organisation Name")]
+ [InlineData("Organisation$Name")]
+ [InlineData("Organisation\\Name")]
+ [InlineData("Organisation/Name")]
+ [InlineData("Organisation")]
+ [InlineData("Organisation Name!")]
+ [InlineData("7-ELEVEN INTERNATIONAL LLC")]
+ [InlineData("C")]
+ [InlineData("+SEN Inc.")]
+ [InlineData("Double \"Quote\" Company S.A.")]
+ [InlineData("Special Characters ^&%#@*/_-\\")]
+ [InlineData("German: ÄÖÜß")]
+ [InlineData("Icelandic: ÆÐÞ")]
+ public async Task ExecuteInvitation_WithValidOrganisationName_DoesNotThrowException(string validName)
+ {
+ var invitationData = _fixture.Build()
+ .With(x => x.OrganisationName, validName)
+ .Create();
+
+ Func Act = async () => await _sut.ExecuteInvitation(invitationData);
+
+ await Act.Should().NotThrowAsync();
+ }
+
+ [Theory]
+ [InlineData(null)] // null value
+ [InlineData("Organisation Name ")] // Ends with whitespace
+ [InlineData("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWX")] // Exceeds 160 characters
+ public async Task ExecuteInvitation_WithInvalidOrganisationName_ThrowsControllerArgumentException(string? invalidName)
+ {
+ var invitationData = _fixture.Build()
+ .With(x => x.OrganisationName, invalidName)
+ .Create();
+
+ async Task Act() => await _sut.ExecuteInvitation(invitationData);
+
+ var ex = await Assert.ThrowsAsync(Act);
+ ex.Message.Should().Be(ValidationExpressionErrors.INCORRECT_COMPANY_NAME.ToString());
+ }
+
#endregion
#region RetriggerCreateCentralIdp
diff --git a/tests/framework/Framework.Models.Tests/ValidationExpressionsTests.cs b/tests/framework/Framework.Models.Tests/ValidationExpressionsTests.cs
new file mode 100644
index 0000000000..2e8f9f0d50
--- /dev/null
+++ b/tests/framework/Framework.Models.Tests/ValidationExpressionsTests.cs
@@ -0,0 +1,65 @@
+
+/********************************************************************************
+ * Copyright (c) 2024 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.Text.RegularExpressions;
+
+namespace Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Tests;
+
+public class ValidationExpressionsTests
+{
+ [Theory]
+ [InlineData("ValidCompanyName123", true)] // Valid company name
+ [InlineData("Company Name", true)] // Valid with space
+ [InlineData("Company$Name", true)] // Valid with special character
+ [InlineData("Company\\Name", true)] // Valid with backslash
+ [InlineData("Company/Name", true)] // Valid with forward slash
+ [InlineData("Company", true)] // Valid with angle brackets
+ [InlineData("Company Name!", true)] // Valid with exclamation mark
+ [InlineData("Company@Name", true)] // Valid with @ symbol
+ [InlineData("C", true)] // Minimum valid length
+ [InlineData("7-ELEVEN INTERNATIONAL LLC", true)]
+ [InlineData("Recht 24/7 Schröder Rechtsanwaltsgesellschaft mbH", true)]
+ [InlineData("Currency £$€¥¢", true)]
+ [InlineData("Brackets []()", true)]
+ [InlineData("Punctuation !?,.;:", true)]
+ [InlineData("Double \"Quote\" Company S.A.", true)]
+ [InlineData("Single 'Quote' Company LLC", true)]
+ [InlineData("Special Characters ^&%#@*/_-\\", true)]
+ [InlineData("German: ÄÖÜß", true)]
+ [InlineData("+SEN Inc.", true)] // leading special character
+ [InlineData("Danish: ÆØÅ", true)]
+ [InlineData("Bayerische Motoren Werke Aktiengesellschaft ", false)] // Ends with whitespace
+ [InlineData(" Bayerische Motoren Werke Aktiengesellschaft", false)] // starts with whitespace
+ [InlineData("Bayerische Motoren Werke Aktiengesellschaft", false)] // double whitespace
+ [InlineData(@"123456789012345678901234567890
+ 123456789012345678901234567890
+ 123456789012345678901234567890
+ 123456789012345678901234567890
+ 123456789012345678901234567890
+ 12345678901234567890", false)] // Exceeds 160 characters
+ [InlineData("", false)] // Empty string
+ [InlineData(" ", false)] // Single space
+ [InlineData(" ", false)] // Multiple spaces
+ public void TestCompanyNameRegex(string companyName, bool expectedResult)
+ {
+ var result = companyName.IsValidCompanyName();
+ Assert.Equal(expectedResult, result);
+ }
+}