diff --git a/src/clients/Dim.Clients/Api/Div/Models/ServiceKeyOperationCreationRequest.cs b/src/clients/Dim.Clients/Api/Div/Models/ServiceKeyOperationCreationRequest.cs index 72c4122..bf9fb61 100644 --- a/src/clients/Dim.Clients/Api/Div/Models/ServiceKeyOperationCreationRequest.cs +++ b/src/clients/Dim.Clients/Api/Div/Models/ServiceKeyOperationCreationRequest.cs @@ -18,6 +18,8 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using System; +using System.Collections.Generic; using System.Text.Json.Serialization; namespace Dim.Clients.Api.Div.Models; @@ -30,7 +32,12 @@ public record ServiceKeyOperationCreationRequest( public record ServiceKeyCreationPayloadData( [property: JsonPropertyName("customerWalletId")] Guid CustomerWalletId, - [property: JsonPropertyName("divWalletServiceName")] string ServiceKeyName + [property: JsonPropertyName("divWalletServiceName")] string ServiceKeyName, + [property: JsonPropertyName("divWalletServiceParameters")] ServiceKeyParameter Parameter +); + +public record ServiceKeyParameter( + [property: JsonPropertyName("authorities")] IEnumerable Authorities ); public record ServiceKeyOperationDeletionRequest( diff --git a/src/clients/Dim.Clients/Api/Div/ProvisioningClient.cs b/src/clients/Dim.Clients/Api/Div/ProvisioningClient.cs index 5591e53..c21ffd3 100644 --- a/src/clients/Dim.Clients/Api/Div/ProvisioningClient.cs +++ b/src/clients/Dim.Clients/Api/Div/ProvisioningClient.cs @@ -25,8 +25,12 @@ using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.HttpClientExtensions; +using System; +using System.Linq; using System.Net.Http.Json; using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; namespace Dim.Clients.Api.Div; @@ -138,7 +142,8 @@ public async Task CreateServiceKey(string technicalUserName, Guid walletId "create", new ServiceKeyCreationPayloadData( walletId, - technicalUserName + technicalUserName, + new ServiceKeyParameter(new[] { "IatpOperations", "ReadCompanyIdentity", "ResolveDID" }) ) ); var client = await basicAuthTokenService diff --git a/src/clients/Dim.Clients/Token/IBasicAuthTokenService.cs b/src/clients/Dim.Clients/Token/IBasicAuthTokenService.cs index 299030b..58d736a 100644 --- a/src/clients/Dim.Clients/Token/IBasicAuthTokenService.cs +++ b/src/clients/Dim.Clients/Token/IBasicAuthTokenService.cs @@ -18,6 +18,10 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + namespace Dim.Clients.Token; public interface IBasicAuthTokenService diff --git a/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs b/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs index 2ba198c..4746e1f 100644 --- a/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs +++ b/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs @@ -42,13 +42,12 @@ public class DimBusinessLogic( IOptions options) : IDimBusinessLogic { - private static readonly Regex TenantName = new(@"(?<=[^\w-])|(?<=[^-])[\W_]+|(?<=[^-])$", RegexOptions.Compiled, new TimeSpan(0, 0, 0, 1)); - private static readonly Regex TechnicalUserName = new("[^a-zA-Z0-9]+", RegexOptions.Compiled, new TimeSpan(0, 0, 0, 1)); + private static readonly Regex NameRegex = new("[^a-zA-Z0-9]+", RegexOptions.Compiled, new TimeSpan(0, 0, 0, 1)); private readonly DimSettings _settings = options.Value; public async Task StartSetupDim(string companyName, string bpn, string didDocumentLocation, bool isIssuer) { - var tenant = TenantName.Replace(companyName, string.Empty).TrimStart('-').TrimEnd('-').ToLower(); + var tenant = GetName(companyName, bpn); if (await dimRepositories.GetInstance().IsTenantExisting(companyName, bpn).ConfigureAwait(ConfigureAwaitOptions.None)) { throw ConflictException.Create(DimErrors.TENANT_ALREADY_EXISTS, new ErrorParameter[] { new("companyName", companyName), new("bpn", bpn) }); @@ -138,7 +137,7 @@ public async Task CreateTechnicalUser(string bpn, TechnicalUserData technicalUse var processId = processStepRepository.CreateProcess(ProcessTypeId.TECHNICAL_USER).Id; processStepRepository.CreateProcessStep(ProcessStepTypeId.CREATE_TECHNICAL_USER, ProcessStepStatusId.TODO, processId); - var technicalUserName = TechnicalUserName.Replace(technicalUserData.Name, string.Empty).ToLower(); + var technicalUserName = GetName(technicalUserData.Name); dimRepositories.GetInstance().CreateTenantTechnicalUser(tenantId, technicalUserName, technicalUserData.ExternalId, processId); await dimRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); @@ -146,7 +145,7 @@ public async Task CreateTechnicalUser(string bpn, TechnicalUserData technicalUse public async Task DeleteTechnicalUser(string bpn, TechnicalUserData technicalUserData) { - var technicalUserName = TechnicalUserName.Replace(technicalUserData.Name, string.Empty).ToLower(); + var technicalUserName = GetName(technicalUserData.Name); var (exists, technicalUserId, processId) = await dimRepositories.GetInstance().GetTechnicalUserForBpn(bpn, technicalUserName).ConfigureAwait(ConfigureAwaitOptions.None); if (!exists) { @@ -171,6 +170,18 @@ public async Task DeleteTechnicalUser(string bpn, TechnicalUserData technicalUse await dimRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } + private static string GetName(string name, string? additionalName = null) + { + name = NameRegex.Replace(name, string.Empty).TrimStart('-').TrimEnd('-').ToLower(); + if (additionalName is null) + { + return name[..(name.Length <= 32 ? name.Length : 32)]; + } + + var maxLength = name.Length + additionalName.Length <= 32 ? name.Length : 32 - additionalName.Length; + return name[..maxLength]; + } + public async Task GetSetupProcess(string bpn, string companyName) { var processData = await dimRepositories.GetInstance().GetWalletProcessForTenant(bpn, companyName) diff --git a/tests/web/Dim.Web.Tests/DimBusinessLogicTests.cs b/tests/web/Dim.Web.Tests/DimBusinessLogicTests.cs index bf40d2a..74b97f4 100644 --- a/tests/web/Dim.Web.Tests/DimBusinessLogicTests.cs +++ b/tests/web/Dim.Web.Tests/DimBusinessLogicTests.cs @@ -104,7 +104,9 @@ public async Task StartSetupDim_WithExisting_ThrowsConflictException() [InlineData("abc-123", "abc123")] [InlineData("abc#123", "abc123")] [InlineData("abc'123", "abc123")] - [InlineData("abc\"123", "abc123")] + [InlineData("ä+slidfböü123üü", "slidfb123")] + [InlineData("averylongnamethatexeedsthemaxlengthbysomecharacters", "averylongnametha")] + [InlineData("a test company", "atestcompany")] public async Task StartSetupDim_WithNewData_CreatesExpected(string companyName, string expectedCompanyName) { // Arrange @@ -309,8 +311,16 @@ public async Task CreateTechnicalUser_WithExisting_ThrowsNotFoundException() result.Message.Should().Be(DimErrors.NO_COMPANY_FOR_BPN.ToString()); } - [Fact] - public async Task CreateTechnicalUser_WithNewData_CreatesExpected() + [Theory] + [InlineData("testCompany", "testcompany")] + [InlineData("-abc123", "abc123")] + [InlineData("abc-123", "abc123")] + [InlineData("abc#123", "abc123")] + [InlineData("abc'123", "abc123")] + [InlineData("ä+slidfböü123üü", "slidfb123")] + [InlineData("averylongnamethatexeedsthemaxlengthbysomecharacters", "averylongnamethatexeedsthemaxlen")] + [InlineData("a test company", "atestcompany")] + public async Task CreateTechnicalUser_WithNewData_CreatesExpected(string name, string expectedName) { // Arrange const string Bpn = "BPNL00001Test"; @@ -333,20 +343,20 @@ public async Task CreateTechnicalUser_WithNewData_CreatesExpected() }); A.CallTo(() => _technicalUserRepository.CreateTenantTechnicalUser(A._, A._, A._, A._)) - .Invokes((Guid tenantId, string name, Guid externalId, Guid pId) => + .Invokes((Guid tenantId, string technicalUserName, Guid externalId, Guid pId) => { - technicalUsers.Add(new TechnicalUser(Guid.NewGuid(), tenantId, externalId, name, pId)); + technicalUsers.Add(new TechnicalUser(Guid.NewGuid(), tenantId, externalId, technicalUserName, pId)); }); // Act - await _sut.CreateTechnicalUser(Bpn, _fixture.Create()); + await _sut.CreateTechnicalUser(Bpn, _fixture.Build().With(x => x.Name, name).Create()); // Assert processes.Should().ContainSingle() .Which.ProcessTypeId.Should().Be(ProcessTypeId.TECHNICAL_USER); processSteps.Should().ContainSingle() .And.Satisfy(x => x.ProcessId == processId && x.ProcessStepTypeId == ProcessStepTypeId.CREATE_TECHNICAL_USER); - technicalUsers.Should().ContainSingle(); + technicalUsers.Should().ContainSingle().And.Satisfy(x => x.TechnicalUserName == expectedName); } #endregion