diff --git a/CHANGELOG.md b/CHANGELOG.md
index d16597c8d3..c3ab7a1bd7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,11 +2,23 @@
New features, fixed bugs, known defects and other noteworthy changes to each release of the Catena-X Portal Backend.
+## 2.2.0-RC4
+
+### Bugfixes
+
+* **Connectors**
+ * add filter for COMPANY_CONNECTOR [#972](https://github.com/eclipse-tractusx/portal-backend/pull/972)
+ * adjust connector deletion process [#968](https://github.com/eclipse-tractusx/portal-backend/pull/968)
+* **Idp**
+ * add search functionality to idp endpoint [#982](https://github.com/eclipse-tractusx/portal-backend/pull/982)
+* **Offer Management**
+ * adjust status query param for subscription-status [#969](https://github.com/eclipse-tractusx/portal-backend/pull/969)
+
## 2.2.0-RC3
### Bugfixes
-* **REgistration Process**
+* **Registration Process**
* removed DIM authentication details from logs [#951](https://github.com/eclipse-tractusx/portal-backend/pull/951)
* adjust retrigger process for sd creation [#938](https://github.com/eclipse-tractusx/portal-backend/pull/938)
* **Connector creation**
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 7fdb463953..d1ee1e9c14 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -20,6 +20,6 @@
2.2.0
- RC3
+ RC4
diff --git a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs
index 942ebb4e78..14d16f234e 100644
--- a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs
@@ -45,6 +45,7 @@ public class ConnectorsBusinessLogic(
IOptions options,
ISdFactoryBusinessLogic sdFactoryBusinessLogic,
IIdentityService identityService,
+ IServiceAccountManagement serviceAccountManagement,
ILogger logger)
: IConnectorsBusinessLogic
{
@@ -242,22 +243,26 @@ await sdFactoryBusinessLogic
}
///
- public async Task DeleteConnectorAsync(Guid connectorId)
+ public async Task DeleteConnectorAsync(Guid connectorId, bool deleteServiceAccount)
{
var companyId = _identityData.CompanyId;
var connectorsRepository = portalRepositories.GetInstance();
- var result = await connectorsRepository.GetConnectorDeleteDataAsync(connectorId, companyId).ConfigureAwait(ConfigureAwaitOptions.None) ?? throw NotFoundException.Create(AdministrationConnectorErrors.CONNECTOR_NOT_FOUND, new ErrorParameter[] { new("connectorId", connectorId.ToString()) });
+ var processStepsToFilter = new[]
+ {
+ ProcessStepTypeId.CREATE_DIM_TECHNICAL_USER, ProcessStepTypeId.RETRIGGER_CREATE_DIM_TECHNICAL_USER,
+ ProcessStepTypeId.AWAIT_CREATE_DIM_TECHNICAL_USER_RESPONSE,
+ ProcessStepTypeId.RETRIGGER_AWAIT_CREATE_DIM_TECHNICAL_USER_RESPONSE
+ };
+
+ var result = await connectorsRepository.GetConnectorDeleteDataAsync(connectorId, companyId, processStepsToFilter).ConfigureAwait(ConfigureAwaitOptions.None) ?? throw NotFoundException.Create(AdministrationConnectorErrors.CONNECTOR_NOT_FOUND, new ErrorParameter[] { new("connectorId", connectorId.ToString()) });
if (!result.IsProvidingOrHostCompany)
{
throw ForbiddenException.Create(AdministrationConnectorErrors.CONNECTOR_NOT_PROVIDER_COMPANY_NOR_HOST, new ErrorParameter[] { new("companyId", companyId.ToString()), new("connectorId", connectorId.ToString()) });
}
- if (result.ServiceAccountId.HasValue && result.UserStatusId != UserStatusId.INACTIVE)
+ if (result is { ServiceAccountId: not null, UserStatusId: UserStatusId.ACTIVE or UserStatusId.PENDING } && deleteServiceAccount)
{
- portalRepositories.GetInstance().AttachAndModifyIdentity(result.ServiceAccountId.Value, null, i =>
- {
- i.UserStatusId = UserStatusId.INACTIVE;
- });
+ await serviceAccountManagement.DeleteServiceAccount(result.ServiceAccountId!.Value, result.DeleteServiceAccountData).ConfigureAwait(false);
}
switch (result.ConnectorStatus)
@@ -290,6 +295,7 @@ private async Task DeleteUpdateConnectorDetail(Guid connectorId, IConnectorsRepo
{
connectorsRepository.AttachAndModifyConnector(connectorId, null, con =>
{
+ con.CompanyServiceAccountId = null;
con.StatusId = ConnectorStatusId.INACTIVE;
con.DateLastChanged = DateTimeOffset.UtcNow;
});
diff --git a/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs
index c1ae735aa8..3c3ee577de 100644
--- a/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs
@@ -67,7 +67,8 @@ public interface IConnectorsBusinessLogic
/// Remove a connector from persistence layer by id.
///
/// ID of the connector to be deleted.
- Task DeleteConnectorAsync(Guid connectorId);
+ /// if true the linked service account will be deleted, otherwise the connection to the connector will just be removed
+ Task DeleteConnectorAsync(Guid connectorId, bool deleteServiceAccount);
///
/// Retrieve connector end point along with bpns
diff --git a/src/administration/Administration.Service/BusinessLogic/IIdentityProviderBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IIdentityProviderBusinessLogic.cs
index 5f1231e530..2d4d5eaa7a 100644
--- a/src/administration/Administration.Service/BusinessLogic/IIdentityProviderBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/IIdentityProviderBusinessLogic.cs
@@ -26,7 +26,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog
public interface IIdentityProviderBusinessLogic
{
- IAsyncEnumerable GetOwnCompanyIdentityProvidersAsync();
+ IAsyncEnumerable GetOwnCompanyIdentityProvidersAsync(string? displayName, string? alias);
ValueTask CreateOwnCompanyIdentityProviderAsync(IamIdentityProviderProtocol protocol, IdentityProviderTypeId typeId, string? displayName);
ValueTask GetOwnCompanyIdentityProviderAsync(Guid identityProviderId);
ValueTask SetOwnCompanyIdentityProviderStatusAsync(Guid identityProviderId, bool enabled);
diff --git a/src/administration/Administration.Service/BusinessLogic/IServiceAccountManagement.cs b/src/administration/Administration.Service/BusinessLogic/IServiceAccountManagement.cs
new file mode 100644
index 0000000000..81cc828866
--- /dev/null
+++ b/src/administration/Administration.Service/BusinessLogic/IServiceAccountManagement.cs
@@ -0,0 +1,28 @@
+/********************************************************************************
+ * 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.Administration.Service.Models;
+using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
+
+namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;
+
+public interface IServiceAccountManagement
+{
+ Task DeleteServiceAccount(Guid serviceAccountId, DeleteServiceAccountData result);
+}
diff --git a/src/administration/Administration.Service/BusinessLogic/IdentityProviderBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IdentityProviderBusinessLogic.cs
index 191793bd29..18a9f38bcf 100644
--- a/src/administration/Administration.Service/BusinessLogic/IdentityProviderBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/IdentityProviderBusinessLogic.cs
@@ -41,47 +41,35 @@
namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;
-public class IdentityProviderBusinessLogic : IIdentityProviderBusinessLogic
+public class IdentityProviderBusinessLogic(
+ IPortalRepositories portalRepositories,
+ IProvisioningManager provisioningManager,
+ IIdentityService identityService,
+ IErrorMessageService errorMessageService,
+ IMailingProcessCreation mailingProcessCreation,
+ IOptions options,
+ ILogger logger)
+ : IIdentityProviderBusinessLogic
{
- private readonly IPortalRepositories _portalRepositories;
- private readonly IProvisioningManager _provisioningManager;
- private readonly IIdentityData _identityData;
- private readonly IErrorMessageService _errorMessageService;
- private readonly IMailingProcessCreation _mailingProcessCreation;
- private readonly IdentityProviderSettings _settings;
- private readonly ILogger _logger;
+ private readonly IIdentityData _identityData = identityService.IdentityData;
+ private readonly IdentityProviderSettings _settings = options.Value;
private static readonly Regex DisplayNameValidationExpression = new(@"^[a-zA-Z0-9\!\?\@\&\#\'\x22\(\)_\-\=\/\*\.\,\;\: ]+$", RegexOptions.None, TimeSpan.FromSeconds(1));
- public IdentityProviderBusinessLogic(
- IPortalRepositories portalRepositories,
- IProvisioningManager provisioningManager,
- IIdentityService identityService,
- IErrorMessageService errorMessageService,
- IMailingProcessCreation mailingProcessCreation,
- IOptions options,
- ILogger logger)
- {
- _portalRepositories = portalRepositories;
- _provisioningManager = provisioningManager;
- _identityData = identityService.IdentityData;
- _errorMessageService = errorMessageService;
- _mailingProcessCreation = mailingProcessCreation;
- _settings = options.Value;
- _logger = logger;
- }
-
- public async IAsyncEnumerable GetOwnCompanyIdentityProvidersAsync()
+ public async IAsyncEnumerable GetOwnCompanyIdentityProvidersAsync(string? displayName, string? alias)
{
var companyId = _identityData.CompanyId;
- await foreach (var identityProviderData in _portalRepositories.GetInstance().GetCompanyIdentityProviderCategoryDataUntracked(companyId).ConfigureAwait(false))
+ await foreach (var identityProviderData in portalRepositories.GetInstance().GetCompanyIdentityProviderCategoryDataUntracked(companyId, alias).ConfigureAwait(false))
{
- yield return identityProviderData.CategoryId switch
+ var details = identityProviderData.CategoryId switch
{
IdentityProviderCategoryId.KEYCLOAK_OIDC => await GetIdentityProviderDetailsOidc(identityProviderData.IdentityProviderId, identityProviderData.Alias, identityProviderData.CategoryId, identityProviderData.TypeId, identityProviderData.MetadataUrl).ConfigureAwait(false),
IdentityProviderCategoryId.KEYCLOAK_SAML => await GetIdentityProviderDetailsSaml(identityProviderData.IdentityProviderId, identityProviderData.Alias, identityProviderData.TypeId),
_ => throw new ControllerArgumentException($"unexpected value for category '{identityProviderData.CategoryId}'")
};
+
+ if (displayName == null || (details.DisplayName != null && details.DisplayName.Contains(displayName)))
+ yield return details;
}
}
@@ -122,8 +110,8 @@ private static void ValidateDisplayName(string displayName)
private async ValueTask CreateOwnCompanyIdentityProviderInternalAsync(IdentityProviderCategoryId identityProviderCategory, IamIdentityProviderProtocol protocol, IdentityProviderTypeId typeId, string? displayName, IEnumerable requiredCompanyRoles)
{
var companyId = _identityData.CompanyId;
- var identityProviderRepository = _portalRepositories.GetInstance();
- var result = await _portalRepositories.GetInstance().CheckCompanyAndCompanyRolesAsync(companyId, requiredCompanyRoles).ConfigureAwait(ConfigureAwaitOptions.None);
+ var identityProviderRepository = portalRepositories.GetInstance();
+ var result = await portalRepositories.GetInstance().CheckCompanyAndCompanyRolesAsync(companyId, requiredCompanyRoles).ConfigureAwait(ConfigureAwaitOptions.None);
if (!result.IsValidCompany)
{
throw new ControllerArgumentException($"company {companyId} does not exist", nameof(companyId));
@@ -134,14 +122,14 @@ private async ValueTask CreateOwnCompanyIdentityProvide
throw new ForbiddenException($"Not allowed to create an identityProvider of type {typeId}");
}
- var alias = await _provisioningManager.CreateOwnIdpAsync(displayName ?? result.CompanyName, result.CompanyName, protocol).ConfigureAwait(ConfigureAwaitOptions.None);
+ var alias = await provisioningManager.CreateOwnIdpAsync(displayName ?? result.CompanyName, result.CompanyName, protocol).ConfigureAwait(ConfigureAwaitOptions.None);
var identityProviderId = identityProviderRepository.CreateIdentityProvider(identityProviderCategory, typeId, companyId, null).Id;
if (typeId == IdentityProviderTypeId.OWN)
{
identityProviderRepository.CreateCompanyIdentityProvider(companyId, identityProviderId);
}
identityProviderRepository.CreateIamIdentityProvider(identityProviderId, alias);
- await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
+ await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
return protocol switch
{
@@ -166,7 +154,7 @@ public async ValueTask GetOwnCompanyIdentityProviderAsy
private async ValueTask<(string Alias, IdentityProviderCategoryId Category, IdentityProviderTypeId TypeId, string? MetadataUrl)> ValidateGetOwnCompanyIdentityProviderArguments(Guid identityProviderId)
{
var companyId = _identityData.CompanyId;
- var (alias, category, isOwnOrOwnerCompany, typeId, metadataUrl) = await _portalRepositories.GetInstance().GetOwnCompanyIdentityProviderAliasUntrackedAsync(identityProviderId, companyId).ConfigureAwait(ConfigureAwaitOptions.None);
+ var (alias, category, isOwnOrOwnerCompany, typeId, metadataUrl) = await portalRepositories.GetInstance().GetOwnCompanyIdentityProviderAliasUntrackedAsync(identityProviderId, companyId).ConfigureAwait(ConfigureAwaitOptions.None);
if (!isOwnOrOwnerCompany)
{
throw new ConflictException($"identityProvider {identityProviderId} is not associated with company {companyId}");
@@ -192,17 +180,17 @@ public async ValueTask SetOwnCompanyIdentityProviderSta
switch (category)
{
case IdentityProviderCategoryId.KEYCLOAK_OIDC when typeId is IdentityProviderTypeId.SHARED:
- await _provisioningManager.SetSharedIdentityProviderStatusAsync(alias, enabled).ConfigureAwait(false);
+ await provisioningManager.SetSharedIdentityProviderStatusAsync(alias, enabled).ConfigureAwait(false);
return await GetIdentityProviderDetailsOidc(identityProviderId, alias, category, typeId, null).ConfigureAwait(false);
case IdentityProviderCategoryId.KEYCLOAK_OIDC:
- await _provisioningManager.SetCentralIdentityProviderStatusAsync(alias, enabled).ConfigureAwait(false);
+ await provisioningManager.SetCentralIdentityProviderStatusAsync(alias, enabled).ConfigureAwait(false);
if (typeId == IdentityProviderTypeId.MANAGED && !enabled && companyUsersLinked)
{
await SendIdpMail(identityProviderId, alias, ownerCompanyName, _settings.DeactivateIdpRoles).ConfigureAwait(ConfigureAwaitOptions.None);
}
return await GetIdentityProviderDetailsOidc(identityProviderId, alias, category, typeId, metadataUrl).ConfigureAwait(false);
case IdentityProviderCategoryId.KEYCLOAK_SAML:
- await _provisioningManager.SetCentralIdentityProviderStatusAsync(alias, enabled).ConfigureAwait(false);
+ await provisioningManager.SetCentralIdentityProviderStatusAsync(alias, enabled).ConfigureAwait(false);
if (typeId == IdentityProviderTypeId.MANAGED && !enabled && companyUsersLinked)
{
await SendIdpMail(identityProviderId, alias, ownerCompanyName, _settings.DeactivateIdpRoles).ConfigureAwait(ConfigureAwaitOptions.None);
@@ -214,7 +202,7 @@ public async ValueTask SetOwnCompanyIdentityProviderSta
}
private Task SendIdpMail(Guid identityProviderId, string? alias, string ownerCompanyName, IEnumerable idpRoles) =>
- _mailingProcessCreation.RoleBaseSendMailForIdp(
+ mailingProcessCreation.RoleBaseSendMailForIdp(
idpRoles,
new[] { ("idpAlias", alias ?? identityProviderId.ToString()), ("ownerCompanyName", ownerCompanyName) },
("username", "User"),
@@ -224,7 +212,7 @@ private Task SendIdpMail(Guid identityProviderId, string? alias, string ownerCom
private async ValueTask<(IdentityProviderCategoryId Category, string Alias, IdentityProviderTypeId TypeId, bool CompanyUsersLinked, string OwnerCompanyName, string? MetadataUrl)> ValidateSetOwnCompanyIdentityProviderStatusArguments(Guid identityProviderId, bool enabled)
{
var companyId = _identityData.CompanyId;
- var result = await _portalRepositories.GetInstance().GetOwnCompanyIdentityProviderStatusUpdateData(identityProviderId, companyId, !enabled).ConfigureAwait(ConfigureAwaitOptions.None);
+ var result = await portalRepositories.GetInstance().GetOwnCompanyIdentityProviderStatusUpdateData(identityProviderId, companyId, !enabled).ConfigureAwait(ConfigureAwaitOptions.None);
if (result == default)
{
throw new NotFoundException($"identityProvider {identityProviderId} does not exist");
@@ -274,7 +262,7 @@ public async ValueTask UpdateOwnCompanyIdentityProvider
var companyId = _identityData.CompanyId;
ValidateDisplayName(details.DisplayName);
- var result = await _portalRepositories.GetInstance().GetOwnCompanyIdentityProviderUpdateData(identityProviderId, companyId).ConfigureAwait(ConfigureAwaitOptions.None);
+ var result = await portalRepositories.GetInstance().GetOwnCompanyIdentityProviderUpdateData(identityProviderId, companyId).ConfigureAwait(ConfigureAwaitOptions.None);
if (result == default)
{
throw new NotFoundException($"identityProvider {identityProviderId} does not exist");
@@ -301,7 +289,7 @@ private async ValueTask UpdateIdentityProviderOidc(string alias, string? metadat
{
throw new ControllerArgumentException("property 'saml' must be null", nameof(details.Saml));
}
- await _provisioningManager.UpdateCentralIdentityProviderDataOIDCAsync(
+ await provisioningManager.UpdateCentralIdentityProviderDataOIDCAsync(
new IdentityProviderEditableConfigOidc(
alias,
details.DisplayName,
@@ -311,7 +299,7 @@ await _provisioningManager.UpdateCentralIdentityProviderDataOIDCAsync(
details.Oidc.Secret,
details.Oidc.SignatureAlgorithm), cancellationToken)
.ConfigureAwait(false);
- _portalRepositories.GetInstance()
+ portalRepositories.GetInstance()
.AttachAndModifyIamIdentityProvider(
alias,
iamIdentityProvider => iamIdentityProvider.MetadataUrl = metadataUrl,
@@ -328,7 +316,7 @@ private async ValueTask UpdateIdentityProviderSaml(string alias, IdentityProvide
{
throw new ControllerArgumentException("property 'oidc' must be null", nameof(details.Oidc));
}
- await _provisioningManager.UpdateCentralIdentityProviderDataSAMLAsync(
+ await provisioningManager.UpdateCentralIdentityProviderDataSAMLAsync(
new IdentityProviderEditableConfigSaml(
alias,
details.DisplayName,
@@ -347,19 +335,19 @@ private async ValueTask UpdateIdentityProviderShared(string alias, IdentityProvi
{
throw new ControllerArgumentException("property 'saml' must be null", nameof(details.Saml));
}
- await _provisioningManager.UpdateSharedIdentityProviderAsync(alias, details.DisplayName).ConfigureAwait(false);
+ await provisioningManager.UpdateSharedIdentityProviderAsync(alias, details.DisplayName).ConfigureAwait(false);
}
private async ValueTask ValidateOtherActiveIdentityProvider(string? alias, IEnumerable<(Guid CompanyId, IEnumerable Aliase)> companyIdAliase)
{
- var aliasStatus = (await Task.WhenAll(companyIdAliase.SelectMany(x => x.Aliase).Where(x => x != alias).Distinct().Select(async alias => (Alias: alias, Enabled: await _provisioningManager.IsCentralIdentityProviderEnabled(alias).ConfigureAwait(false)))).ConfigureAwait(ConfigureAwaitOptions.None)).ToDictionary(x => x.Alias, x => x.Enabled);
+ var aliasStatus = (await Task.WhenAll(companyIdAliase.SelectMany(x => x.Aliase).Where(x => x != alias).Distinct().Select(async alias => (Alias: alias, Enabled: await provisioningManager.IsCentralIdentityProviderEnabled(alias).ConfigureAwait(false)))).ConfigureAwait(ConfigureAwaitOptions.None)).ToDictionary(x => x.Alias, x => x.Enabled);
return companyIdAliase.All(x =>
x.Aliase.Where(a => a != alias).Any(a => aliasStatus[a]));
}
public async ValueTask DeleteCompanyIdentityProviderAsync(Guid identityProviderId)
{
- var identityProviderRepository = _portalRepositories.GetInstance();
+ var identityProviderRepository = portalRepositories.GetInstance();
var (alias, typeId, ownerCompanyName) = await ValidateDeleteOwnCompanyIdentityProviderArguments(identityProviderId, identityProviderRepository).ConfigureAwait(false);
if (alias != null)
@@ -367,9 +355,9 @@ public async ValueTask DeleteCompanyIdentityProviderAsync(Guid identityProviderI
identityProviderRepository.DeleteIamIdentityProvider(alias);
if (typeId == IdentityProviderTypeId.SHARED)
{
- await _provisioningManager.DeleteSharedIdpRealmAsync(alias).ConfigureAwait(false);
+ await provisioningManager.DeleteSharedIdpRealmAsync(alias).ConfigureAwait(false);
}
- await _provisioningManager.DeleteCentralIdentityProviderAsync(alias).ConfigureAwait(ConfigureAwaitOptions.None);
+ await provisioningManager.DeleteCentralIdentityProviderAsync(alias).ConfigureAwait(ConfigureAwaitOptions.None);
}
if (typeId == IdentityProviderTypeId.MANAGED)
@@ -378,19 +366,19 @@ public async ValueTask DeleteCompanyIdentityProviderAsync(Guid identityProviderI
}
identityProviderRepository.DeleteIdentityProvider(identityProviderId);
- await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
+ await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
}
private async Task DeleteManagedIdpLinks(Guid identityProviderId, string? alias, string ownerCompanyName, IIdentityProviderRepository identityProviderRepository)
{
- var roleIds = await _mailingProcessCreation.GetRoleData(_settings.DeleteIdpRoles).ConfigureAwait(ConfigureAwaitOptions.None);
+ var roleIds = await mailingProcessCreation.GetRoleData(_settings.DeleteIdpRoles).ConfigureAwait(ConfigureAwaitOptions.None);
var idpLinkedData = identityProviderRepository.GetManagedIdpLinkedData(identityProviderId, roleIds.Distinct());
async IAsyncEnumerable<(string Email, IReadOnlyDictionary Parameters)> DeleteLinksReturningMaildata()
{
- var companyRepository = _portalRepositories.GetInstance();
- var userRepository = _portalRepositories.GetInstance();
- var userRolesRepository = _portalRepositories.GetInstance();
+ var companyRepository = portalRepositories.GetInstance();
+ var userRepository = portalRepositories.GetInstance();
+ var userRolesRepository = portalRepositories.GetInstance();
await foreach (var data in idpLinkedData.ConfigureAwait(false))
{
@@ -420,7 +408,7 @@ private async Task DeleteManagedIdpLinks(Guid identityProviderId, string? alias,
await foreach (var mailData in DeleteLinksReturningMaildata().ConfigureAwait(false))
{
- _mailingProcessCreation.CreateMailProcess(mailData.Email, "DeleteManagedIdp", mailData.Parameters);
+ mailingProcessCreation.CreateMailProcess(mailData.Email, "DeleteManagedIdp", mailData.Parameters);
}
}
@@ -429,9 +417,9 @@ private async Task DeleteKeycloakUsers(IEnumerable identityIds)
foreach (var identityId in identityIds)
{
string? userId;
- if ((userId = await _provisioningManager.GetUserByUserName(identityId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None)) != null)
+ if ((userId = await provisioningManager.GetUserByUserName(identityId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None)) != null)
{
- await _provisioningManager.DeleteCentralRealmUserAsync(userId).ConfigureAwait(ConfigureAwaitOptions.None);
+ await provisioningManager.DeleteCentralRealmUserAsync(userId).ConfigureAwait(ConfigureAwaitOptions.None);
}
}
}
@@ -456,7 +444,7 @@ private async Task DeleteKeycloakUsers(IEnumerable identityIds)
return (alias, typeId, ownerCompanyName);
}
- if (await _provisioningManager.IsCentralIdentityProviderEnabled(alias).ConfigureAwait(false))
+ if (await provisioningManager.IsCentralIdentityProviderEnabled(alias).ConfigureAwait(false))
{
throw new ControllerArgumentException($"cannot delete identityProvider {identityProviderId} as it is enabled");
}
@@ -481,19 +469,19 @@ private async ValueTask GetIdentityProviderDetailsOidc(
bool aliasExisting;
try
{
- identityProviderDataOidc = await _provisioningManager.GetCentralIdentityProviderDataOIDCAsync(alias)
+ identityProviderDataOidc = await provisioningManager.GetCentralIdentityProviderDataOIDCAsync(alias)
.ConfigureAwait(false);
aliasExisting = true;
}
catch (KeycloakEntityNotFoundException ex)
{
- _logger.LogInformation("Can't receive oidc data for {Alias} with following exception {Exception}", alias, ex.Message);
+ logger.LogInformation("Can't receive oidc data for {Alias} with following exception {Exception}", alias, ex.Message);
aliasExisting = false;
}
if (aliasExisting)
{
- identityProviderMapper = await _provisioningManager.GetIdentityProviderMappers(alias).ToListAsync().ConfigureAwait(false);
+ identityProviderMapper = await provisioningManager.GetIdentityProviderMappers(alias).ToListAsync().ConfigureAwait(false);
}
}
@@ -530,19 +518,19 @@ private async ValueTask GetIdentityProviderDetailsSaml(
bool aliasExisting;
try
{
- identityProviderDataSaml = await _provisioningManager
+ identityProviderDataSaml = await provisioningManager
.GetCentralIdentityProviderDataSAMLAsync(alias).ConfigureAwait(false);
aliasExisting = true;
}
catch (KeycloakEntityNotFoundException ex)
{
- _logger.LogInformation("Can't receive saml data for {Alias} with following exception {Exception}", alias, ex.Message);
+ logger.LogInformation("Can't receive saml data for {Alias} with following exception {Exception}", alias, ex.Message);
aliasExisting = false;
}
if (aliasExisting)
{
- identityProviderMapper = await _provisioningManager.GetIdentityProviderMappers(alias).ToListAsync()
+ identityProviderMapper = await provisioningManager.GetIdentityProviderMappers(alias).ToListAsync()
.ConfigureAwait(false);
}
}
@@ -572,14 +560,14 @@ public async ValueTask CreateOrUpdateOwnCompanyUse
try
{
- await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias);
+ await provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias);
}
catch (KeycloakEntityNotFoundException)
{
// for create-and-update semantics this is expected and not an error
}
- await _provisioningManager.AddProviderUserLinkToCentralUserAsync(
+ await provisioningManager.AddProviderUserLinkToCentralUserAsync(
iamUserId,
new IdentityProviderLink(
alias,
@@ -598,7 +586,7 @@ public async ValueTask GetOwnCompanyUserIdentityPr
var companyId = _identityData.CompanyId;
var (iamUserId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);
- var result = await _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(iamUserId).FirstOrDefaultAsync(identityProviderLink => identityProviderLink.Alias == alias).ConfigureAwait(false);
+ var result = await provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(iamUserId).FirstOrDefaultAsync(identityProviderLink => identityProviderLink.Alias == alias).ConfigureAwait(false);
if (result == default)
{
throw new NotFoundException($"identityProviderLink for identityProvider {identityProviderId} not found in keycloak for user {companyUserId}");
@@ -616,7 +604,7 @@ public async ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync(Guid compan
var (iamUserId, alias) = await GetUserAliasDataAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(false);
try
{
- await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias).ConfigureAwait(ConfigureAwaitOptions.None);
+ await provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias).ConfigureAwait(ConfigureAwaitOptions.None);
}
catch (KeycloakEntityNotFoundException e)
{
@@ -628,7 +616,7 @@ public async ValueTask GetOwnIden
{
var companyId = _identityData.CompanyId;
- var (alias, category, isOwnerCompany, typeId, metadataUrl, connectedCompanies) = await _portalRepositories.GetInstance().GetOwnIdentityProviderWithConnectedCompanies(identityProviderId, companyId).ConfigureAwait(ConfigureAwaitOptions.None);
+ var (alias, category, isOwnerCompany, typeId, metadataUrl, connectedCompanies) = await portalRepositories.GetInstance().GetOwnIdentityProviderWithConnectedCompanies(identityProviderId, companyId).ConfigureAwait(ConfigureAwaitOptions.None);
if (!isOwnerCompany)
{
throw new ConflictException($"identityProvider {identityProviderId} is not associated with company {companyId}");
@@ -701,7 +689,7 @@ public ValueTask UploadOwnCompanyUsersIdentityProvi
private async ValueTask UploadOwnCompanyUsersIdentityProviderLinkDataInternalAsync(IFormFile document, CancellationToken cancellationToken)
{
- var userRepository = _portalRepositories.GetInstance();
+ var userRepository = portalRepositories.GetInstance();
var companyId = _identityData.CompanyId;
var (sharedIdp, existingAliase) = await GetCompanyAliasDataAsync(companyId).ConfigureAwait(false);
@@ -734,7 +722,7 @@ private async ValueTask UploadOwnCompanyUsersIdenti
private UserUpdateError CreateUserUpdateError(int line, Exception error) =>
error switch
{
- DetailException detailException when detailException.HasDetails => new UserUpdateError(line, detailException.GetErrorMessage(_errorMessageService), detailException.GetErrorDetails(_errorMessageService)),
+ DetailException detailException when detailException.HasDetails => new UserUpdateError(line, detailException.GetErrorMessage(errorMessageService), detailException.GetErrorDetails(errorMessageService)),
_ => new UserUpdateError(line, error.Message, Enumerable.Empty())
};
@@ -792,8 +780,8 @@ private UserUpdateError CreateUserUpdateError(int line, Exception error) =>
private async ValueTask<((Guid IdentityProviderId, string Alias) SharedIdp, IEnumerable<(Guid IdentityProviderId, string Alias)> ValidAliase)> GetCompanyAliasDataAsync(Guid companyId)
{
- var identityProviderCategoryData = await _portalRepositories.GetInstance()
- .GetCompanyIdentityProviderCategoryDataUntracked(companyId)
+ var identityProviderCategoryData = await portalRepositories.GetInstance()
+ .GetCompanyIdentityProviderCategoryDataUntracked(companyId, null)
.Where(data => data.Alias != null)
.Select(data => (data.IdentityProviderId, data.TypeId, Alias: data.Alias!))
.ToListAsync().ConfigureAwait(false);
@@ -811,12 +799,12 @@ private UserUpdateError CreateUserUpdateError(int line, Exception error) =>
}
var (existingFirstName, existingLastName, existingEmail) = userEntityData;
- var iamUserId = await _provisioningManager.GetUserByUserName(companyUserId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None) ?? throw new ConflictException($"user {companyUserId} does not exist in keycloak");
+ var iamUserId = await provisioningManager.GetUserByUserName(companyUserId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None) ?? throw new ConflictException($"user {companyUserId} does not exist in keycloak");
return (
iamUserId,
new UserProfile(existingFirstName, existingLastName, existingEmail),
- _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(iamUserId)
+ provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(iamUserId)
);
}
@@ -845,16 +833,16 @@ private async ValueTask UpdateIdentityProviderLinksAsync(
if (existingLink != null)
{
- await _provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias).ConfigureAwait(ConfigureAwaitOptions.None);
+ await provisioningManager.DeleteProviderUserLinkToCentralUserAsync(iamUserId, alias).ConfigureAwait(ConfigureAwaitOptions.None);
}
- await _provisioningManager.AddProviderUserLinkToCentralUserAsync(iamUserId, identityProviderLink).ConfigureAwait(ConfigureAwaitOptions.None);
+ await provisioningManager.AddProviderUserLinkToCentralUserAsync(iamUserId, identityProviderLink).ConfigureAwait(ConfigureAwaitOptions.None);
await InsertUpdateCompanyUserAssignedIdentityProvider(companyUserId, existingIdps.Single(x => x.Alias == alias).IdentityProviderId, identityProviderLink).ConfigureAwait(ConfigureAwaitOptions.None);
return true;
}
private async Task InsertUpdateCompanyUserAssignedIdentityProvider(Guid companyUserId, Guid identityProviderId, IdentityProviderLink providerLink)
{
- var userRepository = _portalRepositories.GetInstance();
+ var userRepository = portalRepositories.GetInstance();
var data = await userRepository.GetCompanyUserAssignedIdentityProvider(companyUserId, identityProviderId).ConfigureAwait(ConfigureAwaitOptions.None);
if (data == default)
{
@@ -880,14 +868,14 @@ private async ValueTask UpdateUserProfileAsync(IUserRepository userRepository, s
{
var (firstName, lastName, email) = (profile.FirstName ?? "", profile.LastName ?? "", profile.Email ?? "");
- await _provisioningManager.UpdateCentralUserAsync(iamUserId, firstName, lastName, email).ConfigureAwait(ConfigureAwaitOptions.None);
+ await provisioningManager.UpdateCentralUserAsync(iamUserId, firstName, lastName, email).ConfigureAwait(ConfigureAwaitOptions.None);
if (sharedIdp != default)
{
var sharedIdpLink = existingLinks.FirstOrDefault(link => link.Alias == sharedIdp.Alias);
if (sharedIdpLink != default)
{
- await _provisioningManager.UpdateSharedRealmUserAsync(sharedIdp.Alias, sharedIdpLink.UserId, firstName, lastName, email).ConfigureAwait(ConfigureAwaitOptions.None);
+ await provisioningManager.UpdateSharedRealmUserAsync(sharedIdp.Alias, sharedIdpLink.UserId, firstName, lastName, email).ConfigureAwait(ConfigureAwaitOptions.None);
}
}
@@ -897,7 +885,7 @@ private async ValueTask UpdateUserProfileAsync(IUserRepository userRepository, s
companyUser.Lastname = profile.LastName;
companyUser.Email = profile.Email;
});
- await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
+ await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
}
private int ParseCSVFirstLineReturningNumIdps(string firstLine)
@@ -1050,7 +1038,7 @@ private async IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataLin
{
throw new ControllerArgumentException("at least one identityProviderId must be specified", nameof(identityProviderIds));
}
- var identityProviderData = await _portalRepositories.GetInstance().GetOwnCompanyIdentityProviderAliasDataUntracked(companyId, identityProviderIds).ToListAsync().ConfigureAwait(false);
+ var identityProviderData = await portalRepositories.GetInstance().GetOwnCompanyIdentityProviderAliasDataUntracked(companyId, identityProviderIds).ToListAsync().ConfigureAwait(false);
identityProviderIds.Except(identityProviderData.Select(data => data.IdentityProviderId)).IfAny(invalidIds =>
{
@@ -1062,7 +1050,7 @@ private async IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataLin
private async IAsyncEnumerable<(Guid CompanyUserId, UserProfile UserProfile, IAsyncEnumerable LinkDatas)> GetOwnCompanyIdentityProviderLinkDataInternalAsync(Guid companyId)
{
- await foreach (var (companyUserId, firstName, lastName, email) in _portalRepositories.GetInstance()
+ await foreach (var (companyUserId, firstName, lastName, email) in portalRepositories.GetInstance()
.GetOwnCompanyUserQuery(companyId)
.Select(companyUser =>
new ValueTuple(
@@ -1072,13 +1060,13 @@ private async IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataLin
companyUser.Email))
.ToAsyncEnumerable().ConfigureAwait(false))
{
- var iamUserId = await _provisioningManager.GetUserByUserName(companyUserId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None);
+ var iamUserId = await provisioningManager.GetUserByUserName(companyUserId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None);
if (iamUserId != null)
{
yield return (
companyUserId,
new UserProfile(firstName, lastName, email),
- _provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(iamUserId)
+ provisioningManager.GetProviderUserLinkDataForCentralUserIdAsync(iamUserId)
);
}
}
@@ -1086,7 +1074,7 @@ private async IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataLin
private async ValueTask<(string IamUserId, string Alias)> GetUserAliasDataAsync(Guid companyUserId, Guid identityProviderId, Guid companyId)
{
- var (isValidUser, alias, isSameCompany) = await _portalRepositories.GetInstance().GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(ConfigureAwaitOptions.None);
+ var (isValidUser, alias, isSameCompany) = await portalRepositories.GetInstance().GetIamUserIsOwnCompanyIdentityProviderAliasAsync(companyUserId, identityProviderId, companyId).ConfigureAwait(ConfigureAwaitOptions.None);
if (!isValidUser)
{
throw new NotFoundException($"companyUserId {companyUserId} does not exist");
@@ -1099,7 +1087,7 @@ private async IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataLin
{
throw new ForbiddenException($"identityProvider {identityProviderId} is not associated with company {companyId}");
}
- var iamUserId = await _provisioningManager.GetUserByUserName(companyUserId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None);
+ var iamUserId = await provisioningManager.GetUserByUserName(companyUserId.ToString()).ConfigureAwait(ConfigureAwaitOptions.None);
if (iamUserId == null)
{
throw new UnexpectedConditionException($"companyUserId {companyUserId} is not linked to keycloak");
diff --git a/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs
index 971667785d..87115f18c2 100644
--- a/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/ServiceAccountBusinessLogic.cs
@@ -28,7 +28,6 @@
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;
-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 Org.Eclipse.TractusX.Portal.Backend.Processes.Library;
@@ -44,7 +43,8 @@ public class ServiceAccountBusinessLogic(
IPortalRepositories portalRepositories,
IOptions options,
IServiceAccountCreation serviceAccountCreation,
- IIdentityService identityService)
+ IIdentityService identityService,
+ IServiceAccountManagement serviceAccountManagement)
: IServiceAccountBusinessLogic
{
private readonly IIdentityData _identityData = identityService.IdentityData;
@@ -119,34 +119,7 @@ public async Task DeleteOwnCompanyServiceAccountAsync(Guid serviceAccountId
}
// serviceAccount
- var userStatus = UserStatusId.DELETED;
- switch (result)
- {
- case { IsDimServiceAccount: true, CreationProcessInProgress: false }:
- userStatus = await CreateDeletionProcess(serviceAccountId, result).ConfigureAwait(ConfigureAwaitOptions.None);
- break;
- case { IsDimServiceAccount: true, CreationProcessInProgress: true }:
- throw ConflictException.Create(AdministrationServiceAccountErrors.TECHNICAL_USER_CREATION_IN_PROGRESS);
- default:
- if (!string.IsNullOrWhiteSpace(result.ClientClientId))
- {
- await provisioningManager.DeleteCentralClientAsync(result.ClientClientId).ConfigureAwait(ConfigureAwaitOptions.None);
- }
-
- break;
- }
-
- portalRepositories.GetInstance().AttachAndModifyIdentity(
- serviceAccountId,
- i =>
- {
- i.UserStatusId = UserStatusId.PENDING;
- },
- i =>
- {
- i.UserStatusId = userStatus;
- });
- portalRepositories.GetInstance().DeleteCompanyUserAssignedRoles(result.UserRoleIds.Select(userRoleId => (serviceAccountId, userRoleId)));
+ await serviceAccountManagement.DeleteServiceAccount(serviceAccountId, new DeleteServiceAccountData(result.UserRoleIds, result.ClientClientId, result.IsDimServiceAccount, result.CreationProcessInProgress, result.ProcessId)).ConfigureAwait(ConfigureAwaitOptions.None);
ModifyConnectorForDeleteServiceAccount(serviceAccountId, result);
return await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
@@ -168,28 +141,6 @@ private void ModifyConnectorForDeleteServiceAccount(Guid serviceAccountId, OwnSe
}
}
- private async Task CreateDeletionProcess(Guid serviceAccountId, OwnServiceAccountData result)
- {
- var processId = result.ProcessId ?? throw ConflictException.Create(AdministrationServiceAccountErrors.SERVICE_ACCOUNT_NOT_LINKED_TO_PROCESS, [new("serviceAccountId", serviceAccountId.ToString())]);
-
- var processData = await portalRepositories.GetInstance()
- .GetProcessDataForServiceAccountDeletionCallback(processId, null)
- .ConfigureAwait(ConfigureAwaitOptions.None);
-
- var context = processData.ProcessData.CreateManualProcessData(null,
- portalRepositories, () => $"externalId {processId}");
-
- context.ProcessSteps.Where(step => step.ProcessStepTypeId != ProcessStepTypeId.DELETE_DIM_TECHNICAL_USER).IfAny(pending =>
- throw ConflictException.Create(AdministrationServiceAccountErrors.SERVICE_ACCOUNT_PENDING_PROCESS_STEPS, [new("serviceAccountId", serviceAccountId.ToString()), new("processStepTypeIds", string.Join(",", pending))]));
-
- if (context.ProcessSteps.Any(step => step.ProcessStepTypeId == ProcessStepTypeId.DELETE_DIM_TECHNICAL_USER))
- return UserStatusId.DELETED;
-
- context.ScheduleProcessSteps([ProcessStepTypeId.DELETE_DIM_TECHNICAL_USER]);
- context.FinalizeProcessStep();
- return UserStatusId.PENDING_DELETION;
- }
-
public async Task GetOwnCompanyServiceAccountDetailsAsync(Guid serviceAccountId)
{
var companyId = _identityData.CompanyId;
diff --git a/src/administration/Administration.Service/BusinessLogic/ServiceAccountManagement.cs b/src/administration/Administration.Service/BusinessLogic/ServiceAccountManagement.cs
new file mode 100644
index 0000000000..b1f018c1af
--- /dev/null
+++ b/src/administration/Administration.Service/BusinessLogic/ServiceAccountManagement.cs
@@ -0,0 +1,92 @@
+/********************************************************************************
+ * 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.Administration.Service.ErrorHandling;
+using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.Linq;
+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;
+using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities;
+using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
+using Org.Eclipse.TractusX.Portal.Backend.Processes.Library;
+using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library;
+
+namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;
+
+public class ServiceAccountManagement(IProvisioningManager provisioningManager, IPortalRepositories portalRepositories) : IServiceAccountManagement
+{
+ public async Task DeleteServiceAccount(Guid serviceAccountId, DeleteServiceAccountData result)
+ {
+ var userStatus = UserStatusId.DELETED;
+ switch (result)
+ {
+ case { IsDimServiceAccount: true, CreationProcessInProgress: false }:
+ userStatus = await CreateDeletionProcess(serviceAccountId, result.ProcessId).ConfigureAwait(ConfigureAwaitOptions.None);
+ break;
+ case { IsDimServiceAccount: true, CreationProcessInProgress: true }:
+ throw ConflictException.Create(AdministrationServiceAccountErrors.TECHNICAL_USER_CREATION_IN_PROGRESS);
+ default:
+ if (!string.IsNullOrWhiteSpace(result.ClientClientId))
+ {
+ await provisioningManager.DeleteCentralClientAsync(result.ClientClientId).ConfigureAwait(ConfigureAwaitOptions.None);
+ }
+
+ break;
+ }
+
+ portalRepositories.GetInstance().AttachAndModifyIdentity(
+ serviceAccountId,
+ i =>
+ {
+ i.UserStatusId = UserStatusId.PENDING;
+ },
+ i =>
+ {
+ i.UserStatusId = userStatus;
+ });
+ portalRepositories.GetInstance().DeleteCompanyUserAssignedRoles(result.UserRoleIds.Select(userRoleId => (serviceAccountId, userRoleId)));
+ }
+
+ private async Task CreateDeletionProcess(Guid serviceAccountId, Guid? processId)
+ {
+ if (processId == null)
+ {
+ throw ConflictException.Create(AdministrationServiceAccountErrors.SERVICE_ACCOUNT_NOT_LINKED_TO_PROCESS, [new ErrorParameter("serviceAccountId", serviceAccountId.ToString())]);
+ }
+
+ var processData = await portalRepositories.GetInstance()
+ .GetProcessDataForServiceAccountDeletionCallback(processId.Value, null)
+ .ConfigureAwait(ConfigureAwaitOptions.None);
+
+ var context = processData.ProcessData.CreateManualProcessData(null,
+ portalRepositories, () => $"externalId {processId}");
+
+ context.ProcessSteps.Where(step => step.ProcessStepTypeId != ProcessStepTypeId.DELETE_DIM_TECHNICAL_USER).IfAny(pending =>
+ throw ConflictException.Create(AdministrationServiceAccountErrors.SERVICE_ACCOUNT_PENDING_PROCESS_STEPS, [new ErrorParameter("serviceAccountId", serviceAccountId.ToString()), new("processStepTypeIds", string.Join(",", pending))]));
+
+ if (context.ProcessSteps.Any(step => step.ProcessStepTypeId == ProcessStepTypeId.DELETE_DIM_TECHNICAL_USER))
+ return UserStatusId.DELETED;
+
+ context.ScheduleProcessSteps([ProcessStepTypeId.DELETE_DIM_TECHNICAL_USER]);
+ context.FinalizeProcessStep();
+ return UserStatusId.PENDING_DELETION;
+ }
+}
diff --git a/src/administration/Administration.Service/Controllers/ConnectorsController.cs b/src/administration/Administration.Service/Controllers/ConnectorsController.cs
index afd393a032..ff8aa8a64a 100644
--- a/src/administration/Administration.Service/Controllers/ConnectorsController.cs
+++ b/src/administration/Administration.Service/Controllers/ConnectorsController.cs
@@ -150,7 +150,8 @@ public async Task CreateManagedConnectorAsync([FromForm] M
/// Removes a connector from persistence layer by id.
///
/// ID of the connector to be deleted.
- /// Example: DELETE: /api/administration/connectors/5636F9B9-C3DE-4BA5-8027-00D17A2FECFB
+ /// if true the linked service account will be deleted, otherwise the connection to the connector will just be removed
+ /// Example: DELETE: /api/administration/connectors/{connectorId}?deleteServiceAccount=true
/// Empty response on success.
/// Record not found.
/// Connector status does not match a deletion scenario. Deletion declined.
@@ -161,9 +162,9 @@ public async Task CreateManagedConnectorAsync([FromForm] M
[ProducesResponseType(typeof(IActionResult), StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)]
- public async Task DeleteConnectorAsync([FromRoute] Guid connectorId)
+ public async Task DeleteConnectorAsync([FromRoute] Guid connectorId, [FromQuery] bool deleteServiceAccount = false)
{
- await logic.DeleteConnectorAsync(connectorId);
+ await logic.DeleteConnectorAsync(connectorId, deleteServiceAccount);
return NoContent();
}
diff --git a/src/administration/Administration.Service/Controllers/IdentityProviderController.cs b/src/administration/Administration.Service/Controllers/IdentityProviderController.cs
index 8adb9f2d00..c29c4518f8 100644
--- a/src/administration/Administration.Service/Controllers/IdentityProviderController.cs
+++ b/src/administration/Administration.Service/Controllers/IdentityProviderController.cs
@@ -34,21 +34,9 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Controllers
///
[EnvironmentRoute("MVC_ROUTING_BASEPATH", "identityprovider")]
[ApiController]
-public class IdentityProviderController : ControllerBase
+public class IdentityProviderController(IIdentityProviderBusinessLogic businessLogic) : ControllerBase
{
- private readonly IIdentityProviderBusinessLogic _businessLogic;
-
- ///
- /// Constructor.
- ///
- /// IdentityProvider business logic.
- public IdentityProviderController(IIdentityProviderBusinessLogic identityProviderBusinessLogic)
- {
- _businessLogic = identityProviderBusinessLogic;
- }
-
///
- ///
/// Gets the details of the own company identity provider
///
/// Returns the details of the own company identity provider
@@ -63,8 +51,8 @@ public IdentityProviderController(IIdentityProviderBusinessLogic identityProvide
[Route("owncompany/identityproviders")]
[ProducesResponseType(typeof(List), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
- public ValueTask> GetOwnCompanyIdentityProviderDetails() =>
- _businessLogic.GetOwnCompanyIdentityProvidersAsync().ToListAsync();
+ public ValueTask> GetOwnCompanyIdentityProviderDetails(string? displayName = null, string? alias = null) =>
+ businessLogic.GetOwnCompanyIdentityProvidersAsync(displayName, alias).ToListAsync();
///
/// Create an identity provider
@@ -88,7 +76,7 @@ public ValueTask> GetOwnCompanyIdentityProviderDet
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public async ValueTask> CreateOwnCompanyIdentityProvider([FromQuery] IamIdentityProviderProtocol protocol, [FromQuery] IdentityProviderTypeId typeId, [FromQuery] string? displayName = null)
{
- var details = await _businessLogic.CreateOwnCompanyIdentityProviderAsync(protocol, typeId, displayName).ConfigureAwait(false);
+ var details = await businessLogic.CreateOwnCompanyIdentityProviderAsync(protocol, typeId, displayName).ConfigureAwait(false);
return (ActionResult)CreatedAtRoute(nameof(GetOwnCompanyIdentityProvider), new { identityProviderId = details.IdentityProviderId }, details);
}
@@ -113,7 +101,7 @@ public async ValueTask> CreateOwnCompanyId
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public ValueTask GetOwnIdentityProviderWithConnectedCompanies([FromRoute] Guid identityProviderId) =>
- _businessLogic.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId);
+ businessLogic.GetOwnIdentityProviderWithConnectedCompanies(identityProviderId);
///
/// Gets a specific identity provider
@@ -136,7 +124,7 @@ public ValueTask GetOwnIdentityPr
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public ValueTask GetOwnCompanyIdentityProvider([FromRoute] Guid identityProviderId) =>
- _businessLogic.GetOwnCompanyIdentityProviderAsync(identityProviderId);
+ businessLogic.GetOwnCompanyIdentityProviderAsync(identityProviderId);
///
/// Sets the status of the given Identity Provider
@@ -164,7 +152,7 @@ public ValueTask GetOwnCompanyIdentityProvider([FromRou
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public ValueTask SetOwnCompanyIdentityProviderStatus([FromRoute] Guid identityProviderId, [FromQuery] bool enabled) =>
- _businessLogic.SetOwnCompanyIdentityProviderStatusAsync(identityProviderId, enabled);
+ businessLogic.SetOwnCompanyIdentityProviderStatusAsync(identityProviderId, enabled);
///
/// Updates the details of the identity provider
@@ -193,7 +181,7 @@ public ValueTask SetOwnCompanyIdentityProviderStatus([F
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public ValueTask UpdateOwnCompanyIdentityProvider([FromRoute] Guid identityProviderId, [FromBody] IdentityProviderEditableDetails details, CancellationToken cancellationToken) =>
- _businessLogic.UpdateOwnCompanyIdentityProviderAsync(identityProviderId, details, cancellationToken);
+ businessLogic.UpdateOwnCompanyIdentityProviderAsync(identityProviderId, details, cancellationToken);
///
/// Deletes the identity provider with the given id
@@ -221,7 +209,7 @@ public ValueTask UpdateOwnCompanyIdentityProvider([From
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public async Task DeleteOwnCompanyIdentityProvider([FromRoute] Guid identityProviderId)
{
- await _businessLogic.DeleteCompanyIdentityProviderAsync(identityProviderId).ConfigureAwait(false);
+ await businessLogic.DeleteCompanyIdentityProviderAsync(identityProviderId).ConfigureAwait(false);
return NoContent();
}
@@ -245,7 +233,7 @@ public async Task DeleteOwnCompanyIdentityProvider([FromRoute]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public IAsyncEnumerable GetOwnCompanyUsersIdentityProviderDataAsync([FromQuery] IEnumerable identityProviderIds, [FromQuery] bool unlinkedUsersOnly = false) =>
- _businessLogic.GetOwnCompanyUsersIdentityProviderDataAsync(identityProviderIds, unlinkedUsersOnly);
+ businessLogic.GetOwnCompanyUsersIdentityProviderDataAsync(identityProviderIds, unlinkedUsersOnly);
///
/// Gets the company users for the identity providers as a file
@@ -268,7 +256,7 @@ public IAsyncEnumerable GetOwnCompanyUsersIdentityProv
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public IActionResult GetOwnCompanyUsersIdentityProviderFileAsync([FromQuery] IEnumerable identityProviderIds, [FromQuery] bool unlinkedUsersOnly = false)
{
- var (stream, contentType, fileName, encoding) = _businessLogic.GetOwnCompanyUsersIdentityProviderLinkDataStream(identityProviderIds, unlinkedUsersOnly);
+ var (stream, contentType, fileName, encoding) = businessLogic.GetOwnCompanyUsersIdentityProviderLinkDataStream(identityProviderIds, unlinkedUsersOnly);
return File(stream, string.Join("; ", contentType, encoding.WebName), fileName);
}
@@ -297,7 +285,7 @@ public IActionResult GetOwnCompanyUsersIdentityProviderFileAsync([FromQuery] IEn
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status415UnsupportedMediaType)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public ValueTask UploadOwnCompanyUsersIdentityProviderFileAsync([FromForm(Name = "document")] IFormFile document, CancellationToken cancellationToken) =>
- _businessLogic.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(document, cancellationToken);
+ businessLogic.UploadOwnCompanyUsersIdentityProviderLinkDataAsync(document, cancellationToken);
///
/// Updates the given user for the given identity provider
@@ -326,7 +314,7 @@ public ValueTask UploadOwnCompanyUsersIdentityProvi
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public ValueTask CreateOrUpdateOwnCompanyUserIdentityProviderDataAsync([FromRoute] Guid companyUserId, [FromRoute] Guid identityProviderId, [FromBody] UserLinkData userLinkData) =>
- _businessLogic.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, userLinkData);
+ businessLogic.CreateOrUpdateOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId, userLinkData);
///
/// Gets the given user for the given identity provider
@@ -354,7 +342,7 @@ public ValueTask CreateOrUpdateOwnCompanyUserIdent
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public ValueTask GetOwnCompanyUserIdentityProviderDataAsync([FromRoute] Guid companyUserId, [FromRoute] Guid identityProviderId) =>
- _businessLogic.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId);
+ businessLogic.GetOwnCompanyUserIdentityProviderLinkDataAsync(companyUserId, identityProviderId);
///
/// Deletes the given user on the given identity provider
@@ -383,7 +371,7 @@ public ValueTask GetOwnCompanyUserIdentityProvider
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public async ValueTask DeleteOwnCompanyUserIdentityProviderDataAsync([FromRoute] Guid companyUserId, [FromRoute] Guid identityProviderId)
{
- await _businessLogic.DeleteOwnCompanyUserIdentityProviderDataAsync(companyUserId, identityProviderId).ConfigureAwait(false);
+ await businessLogic.DeleteOwnCompanyUserIdentityProviderDataAsync(companyUserId, identityProviderId).ConfigureAwait(false);
return NoContent();
}
}
diff --git a/src/administration/Administration.Service/Program.cs b/src/administration/Administration.Service/Program.cs
index 3f366431c3..b98e4aa26d 100644
--- a/src/administration/Administration.Service/Program.cs
+++ b/src/administration/Administration.Service/Program.cs
@@ -85,6 +85,7 @@ await WebAppHelper
builder.Services
.AddTransient()
+ .AddTransient()
.AddPartnerRegistration(builder.Configuration)
.AddNetworkRegistrationProcessHelper()
.AddIssuerComponentService(builder.Configuration.GetSection("Issuer"));
diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs
index 4bbe253efc..a9f7175f5a 100644
--- a/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs
+++ b/src/marketplace/Apps.Service/BusinessLogic/AppsBusinessLogic.cs
@@ -150,11 +150,11 @@ public async Task AddFavouriteAppForUserAsync(Guid appId)
}
///
- public Task> GetCompanySubscribedAppSubscriptionStatusesForUserAsync(int page, int size, OfferSubscriptionStatusId? statusId) =>
- _offerService.GetCompanySubscribedOfferSubscriptionStatusesForUserAsync(page, size, OfferTypeId.APP, DocumentTypeId.APP_LEADIMAGE, statusId);
+ public Task> GetCompanySubscribedAppSubscriptionStatusesForUserAsync(int page, int size, OfferSubscriptionStatusId? statusId, string? name) =>
+ _offerService.GetCompanySubscribedOfferSubscriptionStatusesForUserAsync(page, size, OfferTypeId.APP, DocumentTypeId.APP_LEADIMAGE, statusId, name);
///
- public async Task> GetCompanyProvidedAppSubscriptionStatusesForUserAsync(int page, int size, SubscriptionStatusSorting? sorting, OfferSubscriptionStatusId? statusId, Guid? offerId, string? companyName = null)
+ public async Task> GetCompanyProvidedAppSubscriptionStatusesForUserAsync(int page, int size, SubscriptionStatusSorting? sorting, OfferSubscriptionStatusId? statusId, Guid? offerId, string? companyName)
{
if (companyName != null && !companyName.IsValidCompanyName())
{
diff --git a/src/marketplace/Apps.Service/BusinessLogic/IAppsBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/IAppsBusinessLogic.cs
index 11f9636933..ec3739ed97 100644
--- a/src/marketplace/Apps.Service/BusinessLogic/IAppsBusinessLogic.cs
+++ b/src/marketplace/Apps.Service/BusinessLogic/IAppsBusinessLogic.cs
@@ -76,8 +76,9 @@ public interface IAppsBusinessLogic
/// page
/// size
///
+ ///
/// Returns the details of the subscription status for App user
- public Task> GetCompanySubscribedAppSubscriptionStatusesForUserAsync(int page, int size, OfferSubscriptionStatusId? statusId);
+ public Task> GetCompanySubscribedAppSubscriptionStatusesForUserAsync(int page, int size, OfferSubscriptionStatusId? statusId, string? name);
///
/// Retrieves subscription statuses of provided apps of the provided user's company.
@@ -89,7 +90,7 @@ public interface IAppsBusinessLogic
///
///
/// Async enumberable of user's company's provided apps' statuses.
- public Task> GetCompanyProvidedAppSubscriptionStatusesForUserAsync(int page, int size, SubscriptionStatusSorting? sorting, OfferSubscriptionStatusId? statusId, Guid? offerId, string? companyName = null);
+ public Task> GetCompanyProvidedAppSubscriptionStatusesForUserAsync(int page, int size, SubscriptionStatusSorting? sorting, OfferSubscriptionStatusId? statusId, Guid? offerId, string? companyName);
///
/// Adds a subscription relation between an application and a user's company.
diff --git a/src/marketplace/Apps.Service/Controllers/AppsController.cs b/src/marketplace/Apps.Service/Controllers/AppsController.cs
index f09f50114c..ca4f0388ae 100644
--- a/src/marketplace/Apps.Service/Controllers/AppsController.cs
+++ b/src/marketplace/Apps.Service/Controllers/AppsController.cs
@@ -158,7 +158,8 @@ public async Task RemoveFavouriteAppForCurrentUserAsync([FromRout
/// Example: GET: /api/apps/subscribed/subscription-status
/// The page that should be displayed
/// The size per page of elements that should be returned
- /// Filter for the offer subscription status. If not set all elements will be returned
+ /// Filter for the offer subscription status. If not set, all elements will be returned
+ /// An optional search query for the name
/// Returns list of applicable apps subscription statuses.
/// If sub claim is empty/invalid or user does not exist.
[HttpGet]
@@ -167,8 +168,8 @@ public async Task RemoveFavouriteAppForCurrentUserAsync([FromRout
[Authorize(Policy = PolicyTypes.ValidCompany)]
[ProducesResponseType(typeof(Pagination.Response), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
- public Task> GetCompanySubscribedAppSubscriptionStatusesForUserAsync([FromQuery] int page = 0, [FromQuery] int size = 15, [FromQuery] OfferSubscriptionStatusId? statusId = null) =>
- _appsBusinessLogic.GetCompanySubscribedAppSubscriptionStatusesForUserAsync(page, size, statusId);
+ public Task> GetCompanySubscribedAppSubscriptionStatusesForUserAsync([FromQuery] int page = 0, [FromQuery] int size = 15, [FromQuery] OfferSubscriptionStatusId? status = null, [FromQuery] string? name = null) =>
+ _appsBusinessLogic.GetCompanySubscribedAppSubscriptionStatusesForUserAsync(page, size, status, name);
///
/// Retrieves subscription statuses of provided apps of the currently logged in user's company.
diff --git a/src/marketplace/Offers.Library/Service/IOfferService.cs b/src/marketplace/Offers.Library/Service/IOfferService.cs
index edce3661c1..09ad726b3a 100644
--- a/src/marketplace/Offers.Library/Service/IOfferService.cs
+++ b/src/marketplace/Offers.Library/Service/IOfferService.cs
@@ -240,8 +240,9 @@ Task CreateOrUpdateOfferSubscriptionAgreementConsentAsync(Guid subscriptionId,
///
///
///
+ ///
/// Returns the details of the subscription status for user by OfferType
- Task> GetCompanySubscribedOfferSubscriptionStatusesForUserAsync(int page, int size, OfferTypeId offerTypeId, DocumentTypeId documentTypeId, OfferSubscriptionStatusId? statusId);
+ Task> GetCompanySubscribedOfferSubscriptionStatusesForUserAsync(int page, int size, OfferTypeId offerTypeId, DocumentTypeId documentTypeId, OfferSubscriptionStatusId? statusId, string? name);
///
/// Gets the information for the subscription for the provider
diff --git a/src/marketplace/Offers.Library/Service/OfferService.cs b/src/marketplace/Offers.Library/Service/OfferService.cs
index bc6a5acd23..61f6f82657 100644
--- a/src/marketplace/Offers.Library/Service/OfferService.cs
+++ b/src/marketplace/Offers.Library/Service/OfferService.cs
@@ -889,12 +889,12 @@ private async Task> ValidateRoleData(IEnumerable
- public async Task> GetCompanySubscribedOfferSubscriptionStatusesForUserAsync(int page, int size, OfferTypeId offerTypeId, DocumentTypeId documentTypeId, OfferSubscriptionStatusId? statusId)
+ public async Task> GetCompanySubscribedOfferSubscriptionStatusesForUserAsync(int page, int size, OfferTypeId offerTypeId, DocumentTypeId documentTypeId, OfferSubscriptionStatusId? statusId, string? name)
{
async Task?> GetCompanySubscribedOfferSubscriptionStatusesData(int skip, int take)
{
var offerCompanySubscriptionResponse = await _portalRepositories.GetInstance()
- .GetOwnCompanySubscribedOfferSubscriptionStatusAsync(_identityData.CompanyId, offerTypeId, documentTypeId, statusId)(skip, take).ConfigureAwait(ConfigureAwaitOptions.None);
+ .GetOwnCompanySubscribedOfferSubscriptionStatusAsync(_identityData.CompanyId, offerTypeId, documentTypeId, statusId, name)(skip, take).ConfigureAwait(ConfigureAwaitOptions.None);
return offerCompanySubscriptionResponse == null
? null
diff --git a/src/marketplace/Services.Service/BusinessLogic/IServiceBusinessLogic.cs b/src/marketplace/Services.Service/BusinessLogic/IServiceBusinessLogic.cs
index 580d8a5c1e..c45304a0c9 100644
--- a/src/marketplace/Services.Service/BusinessLogic/IServiceBusinessLogic.cs
+++ b/src/marketplace/Services.Service/BusinessLogic/IServiceBusinessLogic.cs
@@ -134,7 +134,7 @@ public interface IServiceBusinessLogic
/// size
///
/// Returns the details of the subscription status for Service user
- Task> GetCompanySubscribedServiceSubscriptionStatusesForUserAsync(int page, int size, OfferSubscriptionStatusId? statusId);
+ Task> GetCompanySubscribedServiceSubscriptionStatusesForUserAsync(int page, int size, OfferSubscriptionStatusId? statusId, string? name);
///
/// Starts the auto setup process.
diff --git a/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs b/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs
index 366cc59eea..468e0e777c 100644
--- a/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs
+++ b/src/marketplace/Services.Service/BusinessLogic/ServiceBusinessLogic.cs
@@ -217,8 +217,8 @@ public Task GetSubscriptionDetailForSubscriber
_offerService.GetSubscriptionDetailsForSubscriberAsync(serviceId, subscriptionId, OfferTypeId.SERVICE, _settings.SalesManagerRoles);
///
- public Task> GetCompanySubscribedServiceSubscriptionStatusesForUserAsync(int page, int size, OfferSubscriptionStatusId? statusId) =>
- _offerService.GetCompanySubscribedOfferSubscriptionStatusesForUserAsync(page, size, OfferTypeId.SERVICE, DocumentTypeId.SERVICE_LEADIMAGE, statusId);
+ public Task> GetCompanySubscribedServiceSubscriptionStatusesForUserAsync(int page, int size, OfferSubscriptionStatusId? statusId, string? name) =>
+ _offerService.GetCompanySubscribedOfferSubscriptionStatusesForUserAsync(page, size, OfferTypeId.SERVICE, DocumentTypeId.SERVICE_LEADIMAGE, statusId, name);
///
public Task StartAutoSetupAsync(OfferAutoSetupData data) =>
diff --git a/src/marketplace/Services.Service/Controllers/ServicesController.cs b/src/marketplace/Services.Service/Controllers/ServicesController.cs
index 045af23642..a10b6a9926 100644
--- a/src/marketplace/Services.Service/Controllers/ServicesController.cs
+++ b/src/marketplace/Services.Service/Controllers/ServicesController.cs
@@ -297,7 +297,8 @@ public Task GetSubscriptionDetailForSubscriber
/// Example: GET: /api/services/subscribed/subscription-status
/// The page that should be displayed
/// The size per page of elements that should be returned
- /// Filter for the offer subscription status. If not set all elements will be returned
+ /// Filter for the offer subscription status. If not set, all elements will be returned
+ /// Optional search query to filter for the name
/// Returns list of applicable service subscription statuses.
/// If sub claim is empty/invalid or user does not exist.
[HttpGet]
@@ -306,8 +307,8 @@ public Task GetSubscriptionDetailForSubscriber
[Authorize(Policy = PolicyTypes.ValidCompany)]
[ProducesResponseType(typeof(Pagination.Response), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
- public Task> GetCompanySubscribedServiceSubscriptionStatusesForUserAsync([FromQuery] int page = 0, [FromQuery] int size = 15, [FromQuery] OfferSubscriptionStatusId? statusId = null) =>
- _serviceBusinessLogic.GetCompanySubscribedServiceSubscriptionStatusesForUserAsync(page, size, statusId);
+ public Task> GetCompanySubscribedServiceSubscriptionStatusesForUserAsync([FromQuery] int page = 0, [FromQuery] int size = 15, [FromQuery] OfferSubscriptionStatusId? status = null, [FromQuery] string? name = null) =>
+ _serviceBusinessLogic.GetCompanySubscribedServiceSubscriptionStatusesForUserAsync(page, size, status, name);
///
/// Unsubscribes an service from the current user's company's subscriptions.
diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorData.cs
index 54451cf40b..587c3b2ac6 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorData.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorData.cs
@@ -74,7 +74,8 @@ public record DeleteConnectorData(
ConnectorStatusId ConnectorStatus,
IEnumerable ConnectorOfferSubscriptions,
UserStatusId? UserStatusId,
- Guid? ServiceAccountId
+ Guid? ServiceAccountId,
+ DeleteServiceAccountData DeleteServiceAccountData
);
public record ConnectorOfferSubscription(Guid AssignedOfferSubscriptionIds, OfferSubscriptionStatusId OfferSubscriptionStatus);
diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/DeleteServiceAccountData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/DeleteServiceAccountData.cs
new file mode 100644
index 0000000000..87e60850ab
--- /dev/null
+++ b/src/portalbackend/PortalBackend.DBAccess/Models/DeleteServiceAccountData.cs
@@ -0,0 +1,28 @@
+/********************************************************************************
+ * 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
+ ********************************************************************************/
+
+namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
+
+public record DeleteServiceAccountData(
+ IEnumerable UserRoleIds,
+ string? ClientClientId,
+ bool IsDimServiceAccount,
+ bool CreationProcessInProgress,
+ Guid? ProcessId
+);
diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/OwnServiceAccountData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/OwnServiceAccountData.cs
index 99c59d7936..07df725b72 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Models/OwnServiceAccountData.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Models/OwnServiceAccountData.cs
@@ -33,5 +33,3 @@ public record OwnServiceAccountData(
bool CreationProcessInProgress,
Guid? ProcessId
);
-
-public record ProcessData(Guid ProcessId, IEnumerable ProcessStepIds);
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs
index bfef9302d8..267a6a3b85 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs
@@ -26,29 +26,20 @@
namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
-/// Implementation of accessing database with EF Core.
-public class ConnectorsRepository : IConnectorsRepository
+///
+public class ConnectorsRepository(PortalDbContext dbContext) : IConnectorsRepository
{
- private readonly PortalDbContext _context;
-
- ///
- /// Constructor.
- ///
- /// PortalDb context.
- public ConnectorsRepository(PortalDbContext portalDbContext)
- {
- _context = portalDbContext;
- }
-
///
public Func?>> GetAllCompanyConnectorsForCompanyId(Guid companyId) =>
(skip, take) => Pagination.CreateSourceQueryAsync(
skip,
take,
- _context.Connectors.AsNoTracking()
- .Where(x => x.ProviderId == companyId && x.StatusId != ConnectorStatusId.INACTIVE)
+ dbContext.Connectors.AsNoTracking()
+ .Where(x => x.ProviderId == companyId &&
+ x.StatusId != ConnectorStatusId.INACTIVE &&
+ x.TypeId == ConnectorTypeId.COMPANY_CONNECTOR)
.GroupBy(c => c.ProviderId),
- connector => connector.OrderByDescending(connector => connector.Name),
+ connector => connector.OrderByDescending(c => c.Name),
con => new ConnectorData(
con.Name,
con.Location!.Alpha2Code,
@@ -71,7 +62,7 @@ public ConnectorsRepository(PortalDbContext portalDbContext)
(skip, take) => Pagination.CreateSourceQueryAsync(
skip,
take,
- _context.Connectors.AsNoTracking()
+ dbContext.Connectors.AsNoTracking()
.Where(c => c.HostId == companyId &&
c.StatusId != ConnectorStatusId.INACTIVE &&
c.TypeId == ConnectorTypeId.CONNECTOR_AS_A_SERVICE)
@@ -94,7 +85,7 @@ public ConnectorsRepository(PortalDbContext portalDbContext)
).SingleOrDefaultAsync();
public Task<(ConnectorData ConnectorData, bool IsProviderCompany)> GetConnectorByIdForCompany(Guid connectorId, Guid companyId) =>
- _context.Connectors
+ dbContext.Connectors
.AsNoTracking()
.Where(connector => connector.Id == connectorId && connector.StatusId != ConnectorStatusId.INACTIVE)
.Select(connector => new ValueTuple(
@@ -118,7 +109,7 @@ public ConnectorsRepository(PortalDbContext portalDbContext)
.SingleOrDefaultAsync();
public Task<(ConnectorInformationData ConnectorInformationData, bool IsProviderUser)> GetConnectorInformationByIdForIamUser(Guid connectorId, Guid userCompanyId) =>
- _context.Connectors
+ dbContext.Connectors
.AsNoTracking()
.Where(connector => connector.Id == connectorId && connector.StatusId != ConnectorStatusId.INACTIVE)
.Select(connector => new ValueTuple(
@@ -132,12 +123,12 @@ public Connector CreateConnector(string name, string location, string connectorU
{
var connector = new Connector(Guid.NewGuid(), name, location, connectorUrl);
setupOptionalFields?.Invoke(connector);
- return _context.Connectors.Add(connector).Entity;
+ return dbContext.Connectors.Add(connector).Entity;
}
///
public IAsyncEnumerable<(string BusinessPartnerNumber, string ConnectorEndpoint)> GetConnectorEndPointDataAsync(IEnumerable bpns) =>
- _context.Connectors
+ dbContext.Connectors
.AsNoTracking()
.Where(connector => connector.StatusId == ConnectorStatusId.ACTIVE && (!bpns.Any() || bpns.Contains(connector.Provider!.BusinessPartnerNumber)))
.OrderBy(connector => connector.ProviderId)
@@ -153,21 +144,21 @@ public Connector AttachAndModifyConnector(Guid connectorId, Action? i
{
var connector = new Connector(connectorId, null!, null!, null!);
initialize?.Invoke(connector);
- _context.Attach(connector);
+ dbContext.Attach(connector);
setOptionalParameters(connector);
return connector;
}
///
public Task<(Guid ConnectorId, Guid? SelfDescriptionDocumentId)> GetConnectorDataById(Guid connectorId) =>
- _context.Connectors
+ dbContext.Connectors
.Where(x => x.Id == connectorId && x.StatusId != ConnectorStatusId.INACTIVE)
.Select(x => new ValueTuple(x.Id, x.SelfDescriptionDocumentId))
.SingleOrDefaultAsync();
///
- public Task GetConnectorDeleteDataAsync(Guid connectorId, Guid companyId) =>
- _context.Connectors
+ public Task GetConnectorDeleteDataAsync(Guid connectorId, Guid companyId, IEnumerable processStepsToFilter) =>
+ dbContext.Connectors
.Where(x => x.Id == connectorId)
.Select(connector => new DeleteConnectorData(
connector.ProviderId == companyId || connector.HostId == companyId,
@@ -179,12 +170,21 @@ public Connector AttachAndModifyConnector(Guid connectorId, Action? i
x.OfferSubscription!.OfferSubscriptionStatusId
)),
connector.CompanyServiceAccount!.Identity!.UserStatusId,
- connector.CompanyServiceAccountId
+ connector.CompanyServiceAccountId,
+ new DeleteServiceAccountData(
+ connector.CompanyServiceAccount!.Identity!.IdentityAssignedRoles.Select(r => r.UserRoleId),
+ connector.CompanyServiceAccount.ClientClientId,
+ connector.CompanyServiceAccount.CompanyServiceAccountKindId == CompanyServiceAccountKindId.EXTERNAL,
+ connector.CompanyServiceAccount.DimUserCreationData!.Process!.ProcessSteps
+ .Any(ps =>
+ ps.ProcessStepStatusId == ProcessStepStatusId.TODO &&
+ processStepsToFilter.Contains(ps.ProcessStepTypeId)),
+ connector.CompanyServiceAccount.DimUserCreationData == null ? null : connector.CompanyServiceAccount.DimUserCreationData!.ProcessId)
)).SingleOrDefaultAsync();
///
public Task GetConnectorUpdateInformation(Guid connectorId, Guid companyId) =>
- _context.Connectors
+ dbContext.Connectors
.Where(c => c.Id == connectorId)
.Select(c => new ConnectorUpdateInformation(
c.StatusId,
@@ -196,21 +196,21 @@ public Connector AttachAndModifyConnector(Guid connectorId, Action? i
.SingleOrDefaultAsync();
public void DeleteConnector(Guid connectorId) =>
- _context.Connectors.Remove(new Connector(connectorId, null!, null!, null!));
+ dbContext.Connectors.Remove(new Connector(connectorId, null!, null!, null!));
///
public ConnectorAssignedOfferSubscription CreateConnectorAssignedSubscriptions(Guid connectorId, Guid subscriptionId) =>
- _context.ConnectorAssignedOfferSubscriptions.Add(new ConnectorAssignedOfferSubscription(connectorId, subscriptionId)).Entity;
+ dbContext.ConnectorAssignedOfferSubscriptions.Add(new ConnectorAssignedOfferSubscription(connectorId, subscriptionId)).Entity;
///
public void DeleteConnectorAssignedSubscriptions(Guid connectorId, IEnumerable assignedOfferSubscriptions) =>
- _context.ConnectorAssignedOfferSubscriptions.RemoveRange(assignedOfferSubscriptions.Select(x => new ConnectorAssignedOfferSubscription(connectorId, x)));
+ dbContext.ConnectorAssignedOfferSubscriptions.RemoveRange(assignedOfferSubscriptions.Select(x => new ConnectorAssignedOfferSubscription(connectorId, x)));
public Func?>> GetConnectorsWithMissingSdDocument() =>
(skip, take) => Pagination.CreateSourceQueryAsync(
skip,
take,
- _context.Connectors.AsNoTracking()
+ dbContext.Connectors.AsNoTracking()
.Where(x => x.StatusId == ConnectorStatusId.ACTIVE && x.SelfDescriptionDocumentId == null)
.GroupBy(c => c.StatusId),
connector => connector.OrderByDescending(c => c.Name),
@@ -222,13 +222,13 @@ public void DeleteConnectorAssignedSubscriptions(Guid connectorId, IEnumerable GetConnectorIdsWithMissingSelfDescription() =>
- _context.Connectors
+ dbContext.Connectors
.Where(c => c.StatusId == ConnectorStatusId.ACTIVE && c.SelfDescriptionDocumentId == null && c.Provider!.SelfDescriptionDocumentId != null)
.Select(c => c.Id)
.ToAsyncEnumerable();
public Task<(Guid Id, string? BusinessPartnerNumber, Guid SelfDescriptionDocumentId)> GetConnectorForProcessId(Guid processId) =>
- _context.Connectors
+ dbContext.Connectors
.Where(c => c.SdCreationProcessId == processId)
.Select(c => new ValueTuple(c.Id, c.Provider!.BusinessPartnerNumber, c.Provider.SelfDescriptionDocumentId!.Value))
.SingleOrDefaultAsync();
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IConnectorsRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IConnectorsRepository.cs
index 0d4fd47593..07da1a7c26 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IConnectorsRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IConnectorsRepository.cs
@@ -20,6 +20,7 @@
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.Entities;
+using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
@@ -84,8 +85,9 @@ public interface IConnectorsRepository
///
/// Id of the connector
/// Id of the company
+ ///
/// returns SelfDescriptionDocument Data/c>
- Task GetConnectorDeleteDataAsync(Guid connectorId, Guid companyId);
+ Task GetConnectorDeleteDataAsync(Guid connectorId, Guid companyId, IEnumerable processStepsToFilter);
///
/// Gets the data required for the connector update
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IIdentityProviderRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IIdentityProviderRepository.cs
index 1d288aa6dc..44ec276a19 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IIdentityProviderRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IIdentityProviderRepository.cs
@@ -44,7 +44,7 @@ public interface IIdentityProviderRepository
Task<(bool IsOwner, (string? Alias, IdentityProviderCategoryId IdentityProviderCategory, IdentityProviderTypeId IdentityProviderTypeId, string? MetadataUrl) IdentityProviderData, IEnumerable<(Guid CompanyId, IEnumerable Aliase)>? CompanyIdAliase, bool CompanyUsersLinked, string IdpOwnerName)> GetOwnCompanyIdentityProviderStatusUpdateData(Guid identityProviderId, Guid companyId, bool queryAliase);
Task<(bool IsOwner, string? Alias, IdentityProviderCategoryId IdentityProviderCategory, IdentityProviderTypeId IdentityProviderTypeId, string? MetadataUrl)> GetOwnCompanyIdentityProviderUpdateData(Guid identityProviderId, Guid companyId);
Task<(bool IsOwner, string? Alias, IdentityProviderTypeId IdentityProviderTypeId, IEnumerable<(Guid CompanyId, IEnumerable Aliase)> CompanyIdAliase, string IdpOwnerName)> GetOwnCompanyIdentityProviderUpdateDataForDelete(Guid identityProviderId, Guid companyId);
- IAsyncEnumerable<(Guid IdentityProviderId, IdentityProviderCategoryId CategoryId, string? Alias, IdentityProviderTypeId TypeId, string? MetadataUrl)> GetCompanyIdentityProviderCategoryDataUntracked(Guid companyId);
+ IAsyncEnumerable<(Guid IdentityProviderId, IdentityProviderCategoryId CategoryId, string? Alias, IdentityProviderTypeId TypeId, string? MetadataUrl)> GetCompanyIdentityProviderCategoryDataUntracked(Guid companyId, string? alias);
IAsyncEnumerable<(Guid IdentityProviderId, string Alias)> GetOwnCompanyIdentityProviderAliasDataUntracked(Guid companyId, IEnumerable identityProviderIds);
Task<(Guid IdentityProviderId, string? Alias)> GetSingleManagedIdentityProviderAliasDataUntracked(Guid companyId);
IAsyncEnumerable<(Guid IdentityProviderId, string? Alias)> GetManagedIdentityProviderAliasDataUntracked(Guid companyId, IEnumerable identityProviderIds);
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IOfferSubscriptionsRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IOfferSubscriptionsRepository.cs
index df7fc3b27c..ba49f924f5 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IOfferSubscriptionsRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IOfferSubscriptionsRepository.cs
@@ -141,10 +141,11 @@ public interface IOfferSubscriptionsRepository
/// Id of the offer type
/// Id of the document type
///
+ ///
/// Returns a func with skip, take and the pagination of the source
Func?>>
GetOwnCompanySubscribedOfferSubscriptionStatusAsync(Guid userCompanyId, OfferTypeId offerTypeId,
- DocumentTypeId documentTypeId, OfferSubscriptionStatusId? statusId);
+ DocumentTypeId documentTypeId, OfferSubscriptionStatusId? statusId, string? name);
///
///
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IdentityProviderRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IdentityProviderRepository.cs
index 43d7149a19..8f97dbce56 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IdentityProviderRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IdentityProviderRepository.cs
@@ -18,6 +18,7 @@
********************************************************************************/
using Microsoft.EntityFrameworkCore;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities;
@@ -195,10 +196,13 @@ public void AttachAndModifyIamIdentityProvider(string idpAlias, Action GetCompanyIdentityProviderCategoryDataUntracked(Guid companyId) =>
+ public IAsyncEnumerable<(Guid IdentityProviderId, IdentityProviderCategoryId CategoryId, string? Alias, IdentityProviderTypeId TypeId, string? MetadataUrl)> GetCompanyIdentityProviderCategoryDataUntracked(Guid companyId, string? alias) =>
_context.IdentityProviders
.AsNoTracking()
- .Where(identityProvider => identityProvider.OwnerId == companyId || identityProvider.Companies.Any(company => company.Id == companyId))
+ .Where(identityProvider =>
+ (identityProvider.OwnerId == companyId || identityProvider.Companies.Any(company => company.Id == companyId)) &&
+ (alias == null || EF.Functions.ILike(identityProvider.IamIdentityProvider!.IamIdpAlias, $"{alias.EscapeForILike()}%"))
+ )
.Select(identityProvider => new ValueTuple(
identityProvider.Id,
identityProvider.IdentityProviderCategoryId,
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs
index 86c2caef5b..d486968057 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/OfferSubscriptionsRepository.cs
@@ -309,7 +309,8 @@ public void AttachAndModifyAppSubscriptionDetail(Guid detailId, Guid subscriptio
///
public Func?>>
- GetOwnCompanySubscribedOfferSubscriptionStatusAsync(Guid userCompanyId, OfferTypeId offerTypeId, DocumentTypeId documentTypeId, OfferSubscriptionStatusId? statusId) =>
+ GetOwnCompanySubscribedOfferSubscriptionStatusAsync(Guid userCompanyId, OfferTypeId offerTypeId,
+ DocumentTypeId documentTypeId, OfferSubscriptionStatusId? statusId, string? name) =>
(skip, take) => Pagination.CreateSourceQueryAsync(
skip,
take,
@@ -318,7 +319,8 @@ public void AttachAndModifyAppSubscriptionDetail(Guid detailId, Guid subscriptio
.Where(os =>
os.Offer!.OfferTypeId == offerTypeId &&
os.CompanyId == userCompanyId &&
- (statusId == null || os.OfferSubscriptionStatusId == statusId))
+ (statusId == null || os.OfferSubscriptionStatusId == statusId) &&
+ (name == null || (os.Offer.Name != null && EF.Functions.ILike(os.Offer!.Name, $"%{name.EscapeForILike()}%"))))
.GroupBy(os => os.CompanyId),
null,
os => new OfferSubscriptionStatusData(
diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs
index ae7ef30b4f..fcd1fc8056 100644
--- a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs
+++ b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs
@@ -63,8 +63,8 @@ public class ConnectorsBusinessLogicTests
private readonly ConnectorsBusinessLogic _logic;
private readonly IDocumentRepository _documentRepository;
private readonly IServiceAccountRepository _serviceAccountRepository;
- private readonly IOptions _options;
private readonly IIdentityService _identityService;
+ private readonly IServiceAccountManagement _serviceAccountManagement;
public ConnectorsBusinessLogicTests()
{
@@ -76,6 +76,7 @@ public ConnectorsBusinessLogicTests()
_connectorsRepository = A.Fake();
_userRepository = A.Fake();
_sdFactoryBusinessLogic = A.Fake();
+ _serviceAccountManagement = A.Fake();
_serviceAccountRepository = A.Fake();
_offerSubscriptionRepository = A.Fake();
_identityService = A.Fake();
@@ -83,7 +84,7 @@ public ConnectorsBusinessLogicTests()
_portalRepositories = A.Fake();
_identity = A.Fake();
_connectors = new List();
- _options = A.Fake>();
+ var options = A.Fake>();
var settings = new ConnectorsSettings
{
MaxPageSize = 15,
@@ -97,12 +98,12 @@ public ConnectorsBusinessLogicTests()
_documentRepository = A.Fake();
SetupRepositoryMethods();
- A.CallTo(() => _options.Value).Returns(settings);
+ A.CallTo(() => options.Value).Returns(settings);
A.CallTo(() => _identityService.IdentityData).Returns(_identity);
SetupIdentity();
- _logic = new ConnectorsBusinessLogic(_portalRepositories, _options, _sdFactoryBusinessLogic, _identityService, A.Fake>());
+ _logic = new ConnectorsBusinessLogic(_portalRepositories, options, _sdFactoryBusinessLogic, _identityService, _serviceAccountManagement, A.Fake>());
}
#region GetAllCompanyConnectorDatas
@@ -133,6 +134,30 @@ public async Task GetAllCompanyConnectorDatas_WithValidData_ReturnsExpected(int
result.Content.Should().HaveCount(resultPageSize);
}
+ [Theory]
+ [InlineData(0, 10, 5, 1, 0, 5)]
+ public async Task GetAllCompanyConnectorDatasWithCheckTypeCompanyConnector_WithValidData_ReturnsExpected(int page, int size, int numberOfElements, int numberOfPages, int resultPage, int resultPageSize)
+ {
+ var data = _fixture.Build()
+ .With(x => x.Type, ConnectorTypeId.COMPANY_CONNECTOR)
+ .CreateMany(numberOfElements).ToImmutableArray();
+
+ A.CallTo(() => _connectorsRepository.GetAllCompanyConnectorsForCompanyId(A._))
+ .Returns((int skip, int take) => Task.FromResult?>(new(data.Length, data.Skip(skip).Take(take))));
+
+ // Act
+ var result = await _logic.GetAllCompanyConnectorDatas(page, size);
+
+ // Assert
+ A.CallTo(() => _connectorsRepository.GetAllCompanyConnectorsForCompanyId(_identity.CompanyId)).MustHaveHappenedOnceExactly();
+ result.Should().NotBeNull();
+ result.Meta.NumberOfElements.Should().Be(numberOfElements);
+ result.Meta.NumberOfPages.Should().Be(numberOfPages);
+ result.Meta.Page.Should().Be(resultPage);
+ result.Meta.PageSize.Should().Be(resultPageSize);
+ result.Content.Should().HaveCount(resultPageSize);
+ result.Content.Should().Contain(x => x.Type == ConnectorTypeId.COMPANY_CONNECTOR);
+ }
#endregion
#region Create Connector
@@ -153,7 +178,7 @@ public async Task CreateConnectorAsync_WithValidInput_ReturnsCreatedConnectorDat
"application/pkix-cert"
},
ClearinghouseConnectDisabled = clearingHouseDisabled
- }), _sdFactoryBusinessLogic, _identityService, A.Fake>());
+ }), _sdFactoryBusinessLogic, _identityService, _serviceAccountManagement, A.Fake>());
var connectorInput = new ConnectorInputModel("connectorName", "https://test.de", "de", ServiceAccountUserId);
@@ -218,7 +243,7 @@ public async Task CreateConnectorAsync_WithoutSelfDescriptionDocumentAndSdConnec
"application/pkix-cert"
},
ClearinghouseConnectDisabled = true
- }), _sdFactoryBusinessLogic, _identityService, A.Fake>());
+ }), _sdFactoryBusinessLogic, _identityService, _serviceAccountManagement, A.Fake>());
var connectorInput = new ConnectorInputModel("connectorName", "https://test.de", "de", null);
A.CallTo(() => _identity.CompanyId).Returns(CompanyIdWithoutSdDocument);
@@ -310,7 +335,7 @@ public async Task CreateManagedConnectorAsync_WithValidInput_ReturnsCreatedConne
"application/pkix-cert"
},
ClearinghouseConnectDisabled = clearingHouseDisabled
- }), _sdFactoryBusinessLogic, _identityService, A.Fake>());
+ }), _sdFactoryBusinessLogic, _identityService, _serviceAccountManagement, A.Fake>());
var connectorInput = new ManagedConnectorInputModel("connectorName", "https://test.de", "de", _validOfferSubscriptionId, ServiceAccountUserId);
SetupCheckActiveServiceAccountExistsForCompanyAsyncForManaged();
@@ -342,7 +367,7 @@ public async Task CreateManagedConnectorAsync_WithTechnicalUser_ReturnsCreatedCo
"application/pkix-cert"
},
ClearinghouseConnectDisabled = clearingHouseDisabled
- }), _sdFactoryBusinessLogic, _identityService, A.Fake>());
+ }), _sdFactoryBusinessLogic, _identityService, _serviceAccountManagement, A.Fake>());
var connectorInput = new ManagedConnectorInputModel("connectorName", "https://test.de", "de", _validOfferSubscriptionId, null);
@@ -588,9 +613,8 @@ public async Task DeleteConnectorAsync_WithDocumentId_AndActiveUser_ExpectedCall
new ConnectorOfferSubscription(_fixture.Create(), OfferSubscriptionStatusId.PENDING),
};
var userId = Guid.NewGuid();
- Identity? identity = null;
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId))
- .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.ACTIVE, connectorOfferSubscriptions, UserStatusId.ACTIVE, userId));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.ACTIVE, connectorOfferSubscriptions, UserStatusId.ACTIVE, userId, _fixture.Create()));
A.CallTo(() => _documentRepository.AttachAndModifyDocument(A._, A>._, A>._))
.Invokes((Guid docId, Action? initialize, Action modify)
@@ -606,21 +630,14 @@ public async Task DeleteConnectorAsync_WithDocumentId_AndActiveUser_ExpectedCall
initialize?.Invoke(connector);
setOptionalFields.Invoke(connector);
});
- A.CallTo(() => _userRepository.AttachAndModifyIdentity(A._, A>._, A>._))
- .Invokes((Guid id, Action? initialize, Action modify) =>
- {
- identity = new Identity(id, default, Guid.Empty, default, default);
- initialize?.Invoke(identity);
- modify.Invoke(identity);
- });
+
// Act
- await _logic.DeleteConnectorAsync(connectorId);
+ await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
connector.StatusId.Should().Be(ConnectorStatusId.INACTIVE);
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId)).MustHaveHappenedOnceExactly();
- A.CallTo(() => _userRepository.AttachAndModifyIdentity(userId, A>._, A>._)).MustHaveHappenedOnceExactly();
- identity.Should().NotBeNull().And.Match(x => x.Id == userId && x.UserStatusId == UserStatusId.INACTIVE);
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId, A>._)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _serviceAccountManagement.DeleteServiceAccount(userId, A._)).MustHaveHappenedOnceExactly();
A.CallTo(() => _documentRepository.AttachAndModifyDocument(selfDescriptionDocumentId, A>._, A>._)).MustHaveHappenedOnceExactly();
A.CallTo(() => _connectorsRepository.AttachAndModifyConnector(connectorId, A>._, A>._)).MustHaveHappenedOnceExactly();
A.CallTo(() => _connectorsRepository.DeleteConnectorAssignedSubscriptions(connectorId, A>.That.Matches(x => x.Count() == 2))).MustHaveHappenedOnceExactly();
@@ -642,8 +659,8 @@ public async Task DeleteConnectorAsync_WithDocumentId_WithInactiveOrNoUser_Expec
new ConnectorOfferSubscription(_fixture.Create(), OfferSubscriptionStatusId.PENDING),
};
var userId = id == null ? default(Guid?) : new Guid(id);
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId))
- .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.ACTIVE, connectorOfferSubscriptions, statusId, userId));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.ACTIVE, connectorOfferSubscriptions, statusId, userId, _fixture.Create()));
A.CallTo(() => _documentRepository.AttachAndModifyDocument(A._, A>._, A>._))
.Invokes((Guid docId, Action? initialize, Action modify)
@@ -660,11 +677,11 @@ public async Task DeleteConnectorAsync_WithDocumentId_WithInactiveOrNoUser_Expec
setOptionalFields.Invoke(connector);
});
// Act
- await _logic.DeleteConnectorAsync(connectorId);
+ await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
connector.StatusId.Should().Be(ConnectorStatusId.INACTIVE);
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId, A>._)).MustHaveHappenedOnceExactly();
A.CallTo(() => _userRepository.AttachAndModifyIdentity(A._, A>._, A>._)).MustNotHaveHappened();
A.CallTo(() => _documentRepository.AttachAndModifyDocument(selfDescriptionDocumentId, A>._, A>._)).MustHaveHappenedOnceExactly();
A.CallTo(() => _connectorsRepository.AttachAndModifyConnector(connectorId, A>._, A>._)).MustHaveHappenedOnceExactly();
@@ -681,14 +698,14 @@ public async Task DeleteConnectorAsync_WithPendingAndWithoutDocumentId_ExpectedC
new ConnectorOfferSubscription(_fixture.Create(), OfferSubscriptionStatusId.PENDING),
new ConnectorOfferSubscription(_fixture.Create(), OfferSubscriptionStatusId.PENDING),
};
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId))
- .Returns(new DeleteConnectorData(true, null, null, ConnectorStatusId.PENDING, connectorOfferSubscriptions, UserStatusId.ACTIVE, Guid.NewGuid()));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(true, null, null, ConnectorStatusId.PENDING, connectorOfferSubscriptions, UserStatusId.ACTIVE, Guid.NewGuid(), _fixture.Create()));
// Act
- await _logic.DeleteConnectorAsync(connectorId);
+ await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId, A>._)).MustHaveHappenedOnceExactly();
A.CallTo(() => _connectorsRepository.DeleteConnector(connectorId)).MustHaveHappenedOnceExactly();
A.CallTo(() => _connectorsRepository.DeleteConnectorAssignedSubscriptions(connectorId, A>.That.Matches(x => x.Count() == 2))).MustHaveHappenedOnceExactly();
A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly();
@@ -705,14 +722,14 @@ public async Task DeleteConnectorAsync_WithPendingAndDocumentId_ExpectedCalls()
new ConnectorOfferSubscription(_fixture.Create(), OfferSubscriptionStatusId.PENDING),
new ConnectorOfferSubscription(_fixture.Create(), OfferSubscriptionStatusId.PENDING),
};
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId))
- .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.PENDING, connectorOfferSubscriptions, UserStatusId.ACTIVE, Guid.NewGuid()));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.PENDING, connectorOfferSubscriptions, UserStatusId.ACTIVE, Guid.NewGuid(), _fixture.Create()));
// Act
- await _logic.DeleteConnectorAsync(connectorId);
+ await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId, A>._)).MustHaveHappenedOnceExactly();
A.CallTo(() => _documentRepository.RemoveDocument(selfDescriptionDocumentId)).MustHaveHappenedOnceExactly();
A.CallTo(() => _connectorsRepository.DeleteConnector(connectorId)).MustHaveHappenedOnceExactly();
A.CallTo(() => _connectorsRepository.DeleteConnectorAssignedSubscriptions(connectorId, A>.That.Matches(x => x.Count() == 2))).MustHaveHappenedOnceExactly();
@@ -726,14 +743,14 @@ public async Task DeleteConnectorAsync_WithoutAssignedOfferSubscriptions_Expecte
const DocumentStatusId DocumentStatusId = DocumentStatusId.LOCKED;
var connectorId = Guid.NewGuid();
var selfDescriptionDocumentId = Guid.NewGuid();
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId))
- .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.PENDING, Enumerable.Empty(), UserStatusId.ACTIVE, Guid.NewGuid()));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.PENDING, Enumerable.Empty(), UserStatusId.ACTIVE, Guid.NewGuid(), _fixture.Create()));
// Act
- await _logic.DeleteConnectorAsync(connectorId);
+ await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId, A>._)).MustHaveHappenedOnceExactly();
A.CallTo(() => _documentRepository.RemoveDocument(selfDescriptionDocumentId)).MustHaveHappenedOnceExactly();
A.CallTo(() => _connectorsRepository.DeleteConnector(connectorId)).MustHaveHappenedOnceExactly();
A.CallTo(() => _connectorsRepository.DeleteConnectorAssignedSubscriptions(connectorId, A>._)).MustNotHaveHappened();
@@ -745,11 +762,11 @@ public async Task DeleteConnectorAsync_WithOutDocumentId_ExpectedCalls()
{
// Arrange
var connectorId = Guid.NewGuid();
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId))
- .Returns(new DeleteConnectorData(true, null, null, ConnectorStatusId.ACTIVE, Enumerable.Empty(), UserStatusId.ACTIVE, Guid.NewGuid()));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(true, null, null, ConnectorStatusId.ACTIVE, Enumerable.Empty(), UserStatusId.ACTIVE, Guid.NewGuid(), _fixture.Create()));
// Act
- async Task Act() => await _logic.DeleteConnectorAsync(connectorId);
+ async Task Act() => await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
var ex = await Assert.ThrowsAsync(Act);
@@ -761,11 +778,11 @@ public async Task DeleteConnectorAsync_WithInactiveConnector_ThrowsConflictExcep
{
// Arrange
var connectorId = Guid.NewGuid();
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId))
- .Returns(new DeleteConnectorData(true, null, null, ConnectorStatusId.ACTIVE, Enumerable.Empty(), UserStatusId.ACTIVE, Guid.NewGuid()));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(true, null, null, ConnectorStatusId.ACTIVE, Enumerable.Empty(), UserStatusId.ACTIVE, Guid.NewGuid(), _fixture.Create()));
// Act
- async Task Act() => await _logic.DeleteConnectorAsync(connectorId);
+ async Task Act() => await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
var ex = await Assert.ThrowsAsync(Act);
@@ -777,11 +794,11 @@ public async Task DeleteConnectorAsync_ThrowsNotFoundException()
{
// Arrange
var connectorId = Guid.NewGuid();
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId))
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId, A>._))
.Returns(default(DeleteConnectorData));
// Act
- async Task Act() => await _logic.DeleteConnectorAsync(connectorId);
+ async Task Act() => await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
var ex = await Assert.ThrowsAsync(Act);
@@ -793,11 +810,11 @@ public async Task DeleteConnectorAsync_ThrowsForbiddenException()
{
// Arrange
var connectorId = Guid.NewGuid();
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId))
- .Returns(new DeleteConnectorData(false, null, null, default, Enumerable.Empty(), UserStatusId.ACTIVE, Guid.NewGuid()));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(connectorId, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(false, null, null, default, Enumerable.Empty(), UserStatusId.ACTIVE, Guid.NewGuid(), _fixture.Create()));
// Act
- async Task Act() => await _logic.DeleteConnectorAsync(connectorId);
+ async Task Act() => await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
var ex = await Assert.ThrowsAsync(Act);
@@ -817,11 +834,11 @@ public async Task DeleteConnectorAsync_WithPendingAndWithoutDocumentId_ThrowsFor
new ConnectorOfferSubscription(offerSubscriptionId2, OfferSubscriptionStatusId.ACTIVE),
new ConnectorOfferSubscription(offerSubscriptionId3, OfferSubscriptionStatusId.PENDING),
};
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId))
- .Returns(new DeleteConnectorData(true, null, null, ConnectorStatusId.PENDING, connectorOfferSubscriptions, UserStatusId.ACTIVE, Guid.NewGuid()));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(true, null, null, ConnectorStatusId.PENDING, connectorOfferSubscriptions, UserStatusId.ACTIVE, Guid.NewGuid(), _fixture.Create()));
// Act
- async Task Act() => await _logic.DeleteConnectorAsync(connectorId);
+ async Task Act() => await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
var ex = await Assert.ThrowsAsync(Act);
@@ -843,11 +860,11 @@ public async Task DeleteConnectorAsync_WithPendingAndDocumentId_ThrowsForbiddenE
new ConnectorOfferSubscription(offerSubscriptionId2, OfferSubscriptionStatusId.ACTIVE),
new ConnectorOfferSubscription(offerSubscriptionId3, OfferSubscriptionStatusId.PENDING),
};
- A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId))
- .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.PENDING, connectorOfferSubscriptions, UserStatusId.ACTIVE, Guid.NewGuid()));
+ A.CallTo(() => _connectorsRepository.GetConnectorDeleteDataAsync(A._, _identity.CompanyId, A>._))
+ .Returns(new DeleteConnectorData(true, selfDescriptionDocumentId, DocumentStatusId, ConnectorStatusId.PENDING, connectorOfferSubscriptions, UserStatusId.ACTIVE, Guid.NewGuid(), _fixture.Create()));
// Act
- async Task Act() => await _logic.DeleteConnectorAsync(connectorId);
+ async Task Act() => await _logic.DeleteConnectorAsync(connectorId, true);
// Assert
var ex = await Assert.ThrowsAsync(Act);
diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/IdentityProviderBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/IdentityProviderBusinessLogicTests.cs
index 5b1bba1af8..eb0409efcc 100644
--- a/tests/administration/Administration.Service.Tests/BusinessLogic/IdentityProviderBusinessLogicTests.cs
+++ b/tests/administration/Administration.Service.Tests/BusinessLogic/IdentityProviderBusinessLogicTests.cs
@@ -939,7 +939,7 @@ public async Task GetOwnCompanyIdentityProvidersAsync_WithValidId_ReturnsExpecte
var samlGuid = Guid.NewGuid();
var oidc = (oidcGuid, IdentityProviderCategoryId.KEYCLOAK_OIDC, "oidc-alias", IdentityProviderTypeId.OWN, "http://metadata");
var saml = (samlGuid, IdentityProviderCategoryId.KEYCLOAK_SAML, "saml-alias", IdentityProviderTypeId.OWN, default(string?));
- A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(A._))
+ A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(A._, A._))
.Returns(new (Guid, IdentityProviderCategoryId, string?, IdentityProviderTypeId, string?)[] { oidc, saml }.ToAsyncEnumerable());
A.CallTo(() => _provisioningManager.GetCentralIdentityProviderDataOIDCAsync("oidc-alias"))
.Returns(_fixture.Build().With(x => x.Enabled, true).With(x => x.DisplayName, "dis-oidc").Create());
@@ -951,16 +951,88 @@ public async Task GetOwnCompanyIdentityProvidersAsync_WithValidId_ReturnsExpecte
.Returns(_fixture.CreateMany(2).ToAsyncEnumerable());
// Act
- var result = await sut.GetOwnCompanyIdentityProvidersAsync().ToListAsync();
+ var result = await sut.GetOwnCompanyIdentityProvidersAsync(null, null).ToListAsync();
// Assert
- A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(_companyId)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(_companyId, null)).MustHaveHappenedOnceExactly();
result.Should().HaveCount(2).And.Satisfy(
x => x.DisplayName == "dis-oidc" && x.Mappers != null && x.Mappers.Count() == 3,
x => x.DisplayName == "dis-saml" && x.Mappers != null && x.Mappers.Count() == 2
);
}
+ [Fact]
+ public async Task GetOwnCompanyIdentityProvidersAsync_WithValidIdAndDisplayNameFilter_ReturnsExpected()
+ {
+ // Arrange
+ var sut = new IdentityProviderBusinessLogic(
+ _portalRepositories,
+ _provisioningManager,
+ _identityService,
+ _errorMessageService,
+ _mailingProcessCreation,
+ _options,
+ _logger);
+ var oidcGuid = Guid.NewGuid();
+ var samlGuid = Guid.NewGuid();
+ var oidc = (oidcGuid, IdentityProviderCategoryId.KEYCLOAK_OIDC, "oidc-alias", IdentityProviderTypeId.OWN, "http://metadata");
+ var saml = (samlGuid, IdentityProviderCategoryId.KEYCLOAK_SAML, "saml-alias", IdentityProviderTypeId.OWN, default(string?));
+ A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(A._, A._))
+ .Returns(new (Guid, IdentityProviderCategoryId, string?, IdentityProviderTypeId, string?)[] { oidc, saml }.ToAsyncEnumerable());
+ A.CallTo(() => _provisioningManager.GetCentralIdentityProviderDataOIDCAsync("oidc-alias"))
+ .Returns(_fixture.Build().With(x => x.Enabled, true).With(x => x.DisplayName, "dis-oidc").Create());
+ A.CallTo(() => _provisioningManager.GetIdentityProviderMappers("oidc-alias"))
+ .Returns(_fixture.CreateMany(3).ToAsyncEnumerable());
+ A.CallTo(() => _provisioningManager.GetCentralIdentityProviderDataSAMLAsync("saml-alias"))
+ .Returns(_fixture.Build().With(x => x.Enabled, true).With(x => x.DisplayName, "dis-saml").Create());
+ A.CallTo(() => _provisioningManager.GetIdentityProviderMappers("saml-alias"))
+ .Returns(_fixture.CreateMany(2).ToAsyncEnumerable());
+
+ // Act
+ var result = await sut.GetOwnCompanyIdentityProvidersAsync("oidc", null).ToListAsync();
+
+ // Assert
+ A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(_companyId, null)).MustHaveHappenedOnceExactly();
+ result.Should().ContainSingle().And.Satisfy(
+ x => x.DisplayName == "dis-oidc" && x.Mappers != null && x.Mappers.Count() == 3
+ );
+ }
+
+ [Fact]
+ public async Task GetOwnCompanyIdentityProvidersAsync_WithValidIdAndAliasFilter_ReturnsExpected()
+ {
+ // Arrange
+ var sut = new IdentityProviderBusinessLogic(
+ _portalRepositories,
+ _provisioningManager,
+ _identityService,
+ _errorMessageService,
+ _mailingProcessCreation,
+ _options,
+ _logger);
+ var samlGuid = Guid.NewGuid();
+ var saml = (samlGuid, IdentityProviderCategoryId.KEYCLOAK_SAML, "saml-alias", IdentityProviderTypeId.OWN, default(string?));
+ A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(A._, A._))
+ .Returns(new (Guid, IdentityProviderCategoryId, string?, IdentityProviderTypeId, string?)[] { saml }.ToAsyncEnumerable());
+ A.CallTo(() => _provisioningManager.GetCentralIdentityProviderDataOIDCAsync("oidc-alias"))
+ .Returns(_fixture.Build().With(x => x.Enabled, true).With(x => x.DisplayName, "dis-oidc").Create());
+ A.CallTo(() => _provisioningManager.GetIdentityProviderMappers("oidc-alias"))
+ .Returns(_fixture.CreateMany(3).ToAsyncEnumerable());
+ A.CallTo(() => _provisioningManager.GetCentralIdentityProviderDataSAMLAsync("saml-alias"))
+ .Returns(_fixture.Build().With(x => x.Enabled, true).With(x => x.DisplayName, "dis-saml").Create());
+ A.CallTo(() => _provisioningManager.GetIdentityProviderMappers("saml-alias"))
+ .Returns(_fixture.CreateMany(2).ToAsyncEnumerable());
+
+ // Act
+ var result = await sut.GetOwnCompanyIdentityProvidersAsync(null, "saml").ToListAsync();
+
+ // Assert
+ A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(_companyId, "saml")).MustHaveHappenedOnceExactly();
+ result.Should().ContainSingle().And.Satisfy(
+ x => x.DisplayName == "dis-saml" && x.Mappers != null && x.Mappers.Count() == 2
+ );
+ }
+
#endregion
#region GetOwnCompanyIdentityProviderAsync
@@ -2501,9 +2573,9 @@ private void SetupFakes(IEnumerable userData, IEnumerable
(Guid companyUserId, Guid _) => _existingUserId == companyUserId ?
(true, _userProviderId, _username) :
default((bool, string, string)));
- A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(A.That.Not.IsEqualTo(_companyId))).Returns(
+ A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(A.That.Not.IsEqualTo(_companyId), A._)).Returns(
Enumerable.Empty<(Guid, IdentityProviderCategoryId, string?, IdentityProviderTypeId, string?)>().ToAsyncEnumerable());
- A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(A.That.IsEqualTo(_companyId))).Returns(
+ A.CallTo(() => _identityProviderRepository.GetCompanyIdentityProviderCategoryDataUntracked(A.That.IsEqualTo(_companyId), A._)).Returns(
new (Guid, IdentityProviderCategoryId, string?, IdentityProviderTypeId, string?)[] {
(_sharedIdentityProviderId, IdentityProviderCategoryId.KEYCLOAK_OIDC, _sharedIdpAlias, IdentityProviderTypeId.SHARED, null),
(_otherIdentityProviderId, IdentityProviderCategoryId.KEYCLOAK_OIDC, _otherIdpAlias, IdentityProviderTypeId.OWN, "http://metadata"),
diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs
index e1f768ef04..653bb9e70d 100644
--- a/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs
+++ b/tests/administration/Administration.Service.Tests/BusinessLogic/ServiceAccountBusinessLogicTests.cs
@@ -63,26 +63,29 @@ public class ServiceAccountBusinessLogicTests
private readonly IServiceAccountRepository _serviceAccountRepository;
private readonly IConnectorsRepository _connectorsRepository;
private readonly IProvisioningManager _provisioningManager;
+ private readonly IServiceAccountManagement _serviceAccountManagement;
private readonly IPortalRepositories _portalRepositories;
private readonly IFixture _fixture;
private readonly IOptions _options;
private readonly IIdentityService _identityService;
- private readonly byte[] _encryptionKey;
public ServiceAccountBusinessLogicTests()
{
_fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true });
_fixture.ConfigureFixture();
+ _provisioningManager = A.Fake();
+ _serviceAccountCreation = A.Fake();
+ _serviceAccountManagement = A.Fake();
+
_companyRepository = A.Fake();
_userRepository = A.Fake();
_userRolesRepository = A.Fake();
_serviceAccountRepository = A.Fake();
_connectorsRepository = A.Fake();
_processStepRepository = A.Fake();
- _provisioningManager = A.Fake();
_portalRepositories = A.Fake();
- _serviceAccountCreation = A.Fake();
+ A.CallTo(() => _portalRepositories.GetInstance()).Returns(_processStepRepository);
_identity = A.Fake