From d0639fa8eeed8dc47baed58590a0e0cb08da4d08 Mon Sep 17 00:00:00 2001 From: VPrasannaK94 <117351802+VPrasannaK94@users.noreply.github.com> Date: Wed, 13 Dec 2023 19:59:07 +0530 Subject: [PATCH] feat(serviceAccount): added filter and lasteditorData (#381) Ref: CPLP-3137 Reviewed-By: Phil Schneider --- .../IServiceAccountBusinessLogic.cs | 2 +- .../ServiceAccountBusinessLogic.cs | 6 ++-- .../Controllers/ServiceAccountController.cs | 5 +-- .../ServiceAccountConnectorOfferData.cs | 2 ++ .../CompanyServiceAccountDetailedData.cs | 5 ++- .../Repositories/IServiceAccountRepository.cs | 2 +- .../Repositories/ServiceAccountRepository.cs | 12 +++++-- .../ServiceAccountBusinessLogicTests.cs | 10 +++--- .../ServiceAccountControllerTests.cs | 32 +++++++++++++++++++ .../Data/company_service_accounts.test.json | 9 ++++++ .../Seeder/Data/identities.test.json | 9 ++++++ .../ServiceAccountRespotitoryTests.cs | 30 ++++++++++++++--- 12 files changed, 105 insertions(+), 19 deletions(-) diff --git a/src/administration/Administration.Service/BusinessLogic/IServiceAccountBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IServiceAccountBusinessLogic.cs index 3e80897454..059369322d 100644 --- a/src/administration/Administration.Service/BusinessLogic/IServiceAccountBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IServiceAccountBusinessLogic.cs @@ -32,6 +32,6 @@ public interface IServiceAccountBusinessLogic Task GetOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId); Task UpdateOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId, ServiceAccountEditableDetails serviceAccountDetails); Task ResetOwnCompanyServiceAccountSecretAsync(Guid serviceAccountId); - Task> GetOwnCompanyServiceAccountsDataAsync(int page, int size, string? clientId, bool? isOwner); + Task> GetOwnCompanyServiceAccountsDataAsync(int page, int size, string? clientId, bool? isOwner, bool isUserStatusActive); IAsyncEnumerable GetServiceAccountRolesAsync(string? languageShortName); } diff --git a/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs index 917b3d3da1..b3c0dd22d6 100644 --- a/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs @@ -169,6 +169,8 @@ public async Task GetOwnCompanyServiceAccountD authData.Secret, result.ConnectorData, result.OfferSubscriptionData, + result.CompanyLastEditorData!.Name, + result.CompanyLastEditorData.CompanyName, result.SubscriptionId); } @@ -264,12 +266,12 @@ await _provisioningManager.UpdateCentralClientAsync( result.OfferSubscriptionId); } - public Task> GetOwnCompanyServiceAccountsDataAsync(int page, int size, string? clientId, bool? isOwner) => + public Task> GetOwnCompanyServiceAccountsDataAsync(int page, int size, string? clientId, bool? isOwner, bool isUserStatusActive) => Pagination.CreateResponseAsync( page, size, 15, - _portalRepositories.GetInstance().GetOwnCompanyServiceAccountsUntracked(_identityService.IdentityData.CompanyId, clientId, isOwner)); + _portalRepositories.GetInstance().GetOwnCompanyServiceAccountsUntracked(_identityService.IdentityData.CompanyId, clientId, isOwner, isUserStatusActive ? UserStatusId.ACTIVE : UserStatusId.INACTIVE)); public IAsyncEnumerable GetServiceAccountRolesAsync(string? languageShortName) => _portalRepositories.GetInstance().GetServiceAccountRolesAsync(_identityService.IdentityData.CompanyId, _settings.ClientId, languageShortName ?? Constants.DefaultLanguage); diff --git a/src/administration/Administration.Service/Controllers/ServiceAccountController.cs b/src/administration/Administration.Service/Controllers/ServiceAccountController.cs index 019f045b80..f9474cafbf 100644 --- a/src/administration/Administration.Service/Controllers/ServiceAccountController.cs +++ b/src/administration/Administration.Service/Controllers/ServiceAccountController.cs @@ -162,6 +162,7 @@ public Task ResetServiceAccountCredentials([FromRoute] Gu /// number of service account data /// isOwner either true or false /// clientId is string clientclientid + /// isUserStatusActive is True or False /// Returns the specific number of service account data for the given page. /// Example: GET: api/administration/serviceaccount/owncompany/serviceaccounts /// Returns the specific number of service account data for the given page. @@ -170,8 +171,8 @@ public Task ResetServiceAccountCredentials([FromRoute] Gu [Authorize(Policy = PolicyTypes.ValidCompany)] [Route("owncompany/serviceaccounts")] [ProducesResponseType(typeof(Pagination.Response), StatusCodes.Status200OK)] - public Task> GetServiceAccountsData([FromQuery] int page, [FromQuery] int size, [FromQuery] bool? isOwner, [FromQuery] string? clientId) => - _logic.GetOwnCompanyServiceAccountsDataAsync(page, size, clientId, isOwner); + public Task> GetServiceAccountsData([FromQuery] int page, [FromQuery] int size, [FromQuery] bool? isOwner, [FromQuery] string? clientId, [FromQuery] bool isUserStatusActive) => + _logic.GetOwnCompanyServiceAccountsDataAsync(page, size, clientId, isOwner, isUserStatusActive); /// /// Get all service account roles diff --git a/src/administration/Administration.Service/Models/ServiceAccountConnectorOfferData.cs b/src/administration/Administration.Service/Models/ServiceAccountConnectorOfferData.cs index cfbaeb3f52..87750f12a0 100644 --- a/src/administration/Administration.Service/Models/ServiceAccountConnectorOfferData.cs +++ b/src/administration/Administration.Service/Models/ServiceAccountConnectorOfferData.cs @@ -36,5 +36,7 @@ public record ServiceAccountConnectorOfferData( [property: JsonPropertyName("secret")] string? Secret, [property: JsonPropertyName("connector")] ConnectorResponseData? Connector, [property: JsonPropertyName("offer")] OfferResponseData? Offer, + [property: JsonPropertyName("LastEditorName")] string? LastName, + [property: JsonPropertyName("LastEditorCompanyName")] string? CompanyName, [property: JsonPropertyName("subscriptionId")] Guid? SubscriptionId = null ); diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/CompanyServiceAccountDetailedData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/CompanyServiceAccountDetailedData.cs index 629e74271d..b0b9ae6e61 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Models/CompanyServiceAccountDetailedData.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Models/CompanyServiceAccountDetailedData.cs @@ -33,8 +33,11 @@ public record CompanyServiceAccountDetailedData( CompanyServiceAccountTypeId CompanyServiceAccountTypeId, Guid? SubscriptionId, ConnectorResponseData? ConnectorData, - OfferResponseData? OfferSubscriptionData); + OfferResponseData? OfferSubscriptionData, + CompanyLastEditorData? CompanyLastEditorData); public record ConnectorResponseData(Guid Id, string Name); public record OfferResponseData(Guid Id, OfferTypeId Type, string? Name, Guid? SubscriptionId); + +public record CompanyLastEditorData(string? Name, string CompanyName); diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IServiceAccountRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IServiceAccountRepository.cs index 39b2ab76ca..6338e8951c 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IServiceAccountRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IServiceAccountRepository.cs @@ -39,6 +39,6 @@ CompanyServiceAccount CreateCompanyServiceAccount(Guid identityId, Task GetOwnCompanyServiceAccountWithIamClientIdAsync(Guid serviceAccountId, Guid userCompanyId); Task<(IEnumerable UserRoleIds, Guid? ConnectorId, string? ClientId, ConnectorStatusId? statusId, OfferSubscriptionStatusId? OfferStatusId)> GetOwnCompanyServiceAccountWithIamServiceAccountRolesAsync(Guid serviceAccountId, Guid companyId); Task GetOwnCompanyServiceAccountDetailedDataUntrackedAsync(Guid serviceAccountId, Guid companyId); - Func?>> GetOwnCompanyServiceAccountsUntracked(Guid userCompanyId, string? clientId, bool? isOwner); + Func?>> GetOwnCompanyServiceAccountsUntracked(Guid userCompanyId, string? clientId, bool? isOwner, UserStatusId userStatusId); Task CheckActiveServiceAccountExistsForCompanyAsync(Guid technicalUserId, Guid companyId); } diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ServiceAccountRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ServiceAccountRepository.cs index 59e8167ce8..e1779f35e2 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ServiceAccountRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ServiceAccountRepository.cs @@ -144,10 +144,16 @@ public void AttachAndModifyCompanyServiceAccount( serviceAccount.OfferSubscription.OfferId, serviceAccount.OfferSubscription.Offer!.OfferTypeId, serviceAccount.OfferSubscription.Offer.Name, - serviceAccount.OfferSubscription.Id))) + serviceAccount.OfferSubscription.Id), + serviceAccount.Identity.LastEditorId == null ? null : + new CompanyLastEditorData( + serviceAccount.Identity.LastEditor!.IdentityTypeId == IdentityTypeId.COMPANY_USER + ? serviceAccount.Identity.LastEditor.CompanyUser!.Lastname + : serviceAccount.Identity.LastEditor.CompanyServiceAccount!.Name, + serviceAccount.Identity.LastEditor.Company!.Name))) .SingleOrDefaultAsync(); - public Func?>> GetOwnCompanyServiceAccountsUntracked(Guid userCompanyId, string? clientId, bool? isOwner) => + public Func?>> GetOwnCompanyServiceAccountsUntracked(Guid userCompanyId, string? clientId, bool? isOwner, UserStatusId userStatusId) => (skip, take) => Pagination.CreateSourceQueryAsync( skip, take, @@ -156,7 +162,7 @@ public void AttachAndModifyCompanyServiceAccount( .Where(serviceAccount => (!isOwner.HasValue && (serviceAccount.CompaniesLinkedServiceAccount!.Owners == userCompanyId || serviceAccount.CompaniesLinkedServiceAccount!.Provider == userCompanyId) || isOwner.HasValue && (isOwner.Value && serviceAccount.CompaniesLinkedServiceAccount!.Owners == userCompanyId || !isOwner.Value && serviceAccount.CompaniesLinkedServiceAccount!.Provider == userCompanyId)) && - serviceAccount.Identity!.UserStatusId == UserStatusId.ACTIVE && + serviceAccount.Identity!.UserStatusId == userStatusId && (clientId == null || EF.Functions.ILike(serviceAccount.ClientClientId!, $"%{clientId.EscapeForILike()}%"))) .GroupBy(serviceAccount => serviceAccount.Identity!.UserStatusId), serviceAccounts => serviceAccounts.OrderBy(serviceAccount => serviceAccount.Name), diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs index 67f45502c2..ad0c9b6643 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs @@ -374,19 +374,21 @@ public async Task UpdateOwnCompanyServiceAccountDetailsAsync_WithInactiveService #region GetOwnCompanyServiceAccountsDataAsync - [Fact] - public async Task GetOwnCompanyServiceAccountsDataAsync_GetsExpectedData() + [Theory] + [InlineData(UserStatusId.ACTIVE, true)] + [InlineData(UserStatusId.INACTIVE, false)] + public async Task GetOwnCompanyServiceAccountsDataAsync_GetsExpectedData(UserStatusId userStatusId, bool isUserStatusActive) { // Arrange var data = _fixture.CreateMany(15); - A.CallTo(() => _serviceAccountRepository.GetOwnCompanyServiceAccountsUntracked(_identity.CompanyId, null, null)) + A.CallTo(() => _serviceAccountRepository.GetOwnCompanyServiceAccountsUntracked(_identity.CompanyId, null, null, userStatusId)) .Returns((int skip, int take) => Task.FromResult((Pagination.Source?)new Pagination.Source(data.Count(), data.Skip(skip).Take(take)))); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_serviceAccountRepository); var sut = new ServiceAccountBusinessLogic(_provisioningManager, _portalRepositories, _options, null!, _identityService); // Act - var result = await sut.GetOwnCompanyServiceAccountsDataAsync(1, 10, null, null).ConfigureAwait(false); + var result = await sut.GetOwnCompanyServiceAccountsDataAsync(1, 10, null, null, isUserStatusActive).ConfigureAwait(false); // Assert result.Should().NotBeNull(); diff --git a/tests/administration/Administration.Service.Tests/Controllers/ServiceAccountControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/ServiceAccountControllerTests.cs index 74a1ddd582..76f23126d3 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/ServiceAccountControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/ServiceAccountControllerTests.cs @@ -22,6 +22,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Controllers; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; @@ -92,4 +93,35 @@ public async Task GetServiceAccountRolesAsync_CallsExpected() result.Should().NotBeNull(); result.Should().HaveCount(5); } + + [Fact] + public async Task GetServiceAccountDetails_CallsExpected() + { + // Arrange + var serviceAcountId = _fixture.Create(); + + // Act + await _controller.GetServiceAccountDetails(serviceAcountId).ConfigureAwait(false); + + // Assert + A.CallTo(() => _logic.GetOwnCompanyServiceAccountDetailsAsync(serviceAcountId)).MustHaveHappenedOnceExactly(); + + } + + [Fact] + public async Task GetServiceAccountsData_CallsExpected() + { + //Arrange + var paginationResponse = new Pagination.Response(new Pagination.Metadata(15, 1, 1, 15), _fixture.CreateMany(5)); + A.CallTo(() => _logic.GetOwnCompanyServiceAccountsDataAsync(0, 15, null, null, true)) + .Returns(paginationResponse); + + //Act + var result = await this._controller.GetServiceAccountsData(0, 15, null, null, true).ConfigureAwait(false); + + //Assert + A.CallTo(() => _logic.GetOwnCompanyServiceAccountsDataAsync(0, 15, null, null, true)).MustHaveHappenedOnceExactly(); + Assert.IsType>(result); + result.Content.Should().HaveCount(5); + } } diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/company_service_accounts.test.json b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/company_service_accounts.test.json index 863a10bfbc..a684a4d957 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/company_service_accounts.test.json +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/company_service_accounts.test.json @@ -59,5 +59,14 @@ "offer_subscription_id": null, "company_id": "729e0af2-6723-4a7f-85a1-833d84b39bdf", "client_client_id": "sa-x-inactive" + }, + { + "id": "38c92162-6328-40ce-80f3-22e3f3e9b94e", + "name": "test-user-service-account-0", + "description": "test-user-service-account-desc-0", + "company_service_account_type_id": 1, + "offer_subscription_id": null, + "company_id": "729e0af2-6723-4a7f-85a1-833d84b39bdf", + "client_client_id": "sa-x-0" } ] diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/identities.test.json b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/identities.test.json index be40a1f939..91042a1e3a 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/identities.test.json +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/Seeder/Data/identities.test.json @@ -158,5 +158,14 @@ "user_status_id": 2, "user_entity_id": null, "identity_type_id": 2 + }, + { + "id": "38c92162-6328-40ce-80f3-22e3f3e9b94e", + "date_created": "2022-06-01 18:01:33.439000 +00:00", + "company_id": "729e0af2-6723-4a7f-85a1-833d84b39bdf", + "user_status_id": 1, + "user_entity_id": "3d8142f1-860b-48aa-8c2b-1ccb18699f66", + "identity_type_id": 2, + "last_editor_id":"8b42e6de-7b59-4217-a63c-198e83d93777" } ] diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/ServiceAccountRespotitoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/ServiceAccountRespotitoryTests.cs index fd0dedabde..2212638aba 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/ServiceAccountRespotitoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/ServiceAccountRespotitoryTests.cs @@ -172,6 +172,8 @@ public async Task GetOwnCompanyServiceAccountDetailedDataUntrackedAsync_ReturnsE // Assert result.Should().NotBeNull(); result!.CompanyServiceAccountTypeId.Should().Be(CompanyServiceAccountTypeId.OWN); + result.CompanyLastEditorData!.CompanyName.Should().Be("CX-Test-Access"); + result.CompanyLastEditorData.Name.Should().Be("CX Admin"); } [Fact] @@ -228,7 +230,7 @@ public async Task GetOwnCompanyServiceAccountsUntracked_ReturnsExpectedResult(in var newvalidCompanyId = new Guid("41fd2ab8-71cd-4546-9bef-a388d91b2542"); var (sut, _) = await CreateSut().ConfigureAwait(false); // Act - var result = await sut.GetOwnCompanyServiceAccountsUntracked(newvalidCompanyId, null, null)(page, size).ConfigureAwait(false); + var result = await sut.GetOwnCompanyServiceAccountsUntracked(newvalidCompanyId, null, null, UserStatusId.ACTIVE)(page, size).ConfigureAwait(false); // Assert result.Should().NotBeNull(); @@ -248,7 +250,7 @@ public async Task GetOwnCompanyServiceAccountsUntracked_WithClientIdAndOwner_Ret var (sut, _) = await CreateSut().ConfigureAwait(false); // Act - var result = await sut.GetOwnCompanyServiceAccountsUntracked(_validCompanyId, "sa-cl5-custodian-1", true)(0, 10).ConfigureAwait(false); + var result = await sut.GetOwnCompanyServiceAccountsUntracked(_validCompanyId, "sa-cl5-custodian-1", true, UserStatusId.ACTIVE)(0, 10).ConfigureAwait(false); // Assert result!.Count.Should().Be(1); @@ -263,7 +265,7 @@ public async Task GetOwnCompanyServiceAccountsUntracked_WithClientIdAndProvider_ var (sut, _) = await CreateSut().ConfigureAwait(false); // Act - var result = await sut.GetOwnCompanyServiceAccountsUntracked(new("41fd2ab8-71cd-4546-9bef-a388d91b2543"), "sa-x-2", false)(0, 10).ConfigureAwait(false); + var result = await sut.GetOwnCompanyServiceAccountsUntracked(new("41fd2ab8-71cd-4546-9bef-a388d91b2543"), "sa-x-2", false, UserStatusId.ACTIVE)(0, 10).ConfigureAwait(false); // Assert result!.Count.Should().Be(1); @@ -278,7 +280,7 @@ public async Task GetOwnCompanyServiceAccountsUntracked_WithOnlyClientId_Returns var (sut, _) = await CreateSut().ConfigureAwait(false); // Act - var result = await sut.GetOwnCompanyServiceAccountsUntracked(_validCompanyId, "sa-cl5-custodian-1", null)(0, 10).ConfigureAwait(false); + var result = await sut.GetOwnCompanyServiceAccountsUntracked(_validCompanyId, "sa-cl5-custodian-1", null, UserStatusId.ACTIVE)(0, 10).ConfigureAwait(false); // Assert result!.Count.Should().Be(1); @@ -293,13 +295,31 @@ public async Task GetOwnCompanyServiceAccountsUntracked_WithSearch_ReturnsExpect var (sut, _) = await CreateSut().ConfigureAwait(false); // Act - var result = await sut.GetOwnCompanyServiceAccountsUntracked(_validCompanyId, "sa-cl", null)(0, 10).ConfigureAwait(false); + var result = await sut.GetOwnCompanyServiceAccountsUntracked(_validCompanyId, "sa-cl", null, UserStatusId.ACTIVE)(0, 10).ConfigureAwait(false); // Assert result!.Count.Should().Be(11); result.Data.Should().HaveCount(10); } + [Fact] + public async Task GetOwnCompanyServiceAccountsUntracked_WithUserStatusId_InActive_ReturnsExpectedResult() + { + // Arrange + var (sut, _) = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetOwnCompanyServiceAccountsUntracked(new Guid("729e0af2-6723-4a7f-85a1-833d84b39bdf"), null, null, UserStatusId.INACTIVE)(0, 10).ConfigureAwait(false); + + // Assert + result!.Count.Should().Be(1); + result.Data.Should().HaveCount(1) + .And.Satisfy(x => + x.ServiceAccountId == new Guid("38c92162-6328-40ce-80f3-22e3f3e9b94d") + && x.ClientId == "sa-x-inactive" + && x.CompanyServiceAccountTypeId == CompanyServiceAccountTypeId.MANAGED); + } + #endregion #region CheckActiveServiceAccountExistsForCompanyAsync