Skip to content

Commit

Permalink
feat(userRoles): add type to userRole (eclipse-tractusx#1024)
Browse files Browse the repository at this point in the history
Refs: eclipse-tractusx#1022
Reviewed-By: Evelyn Gurschler <evelyn.gurschler@bmw.de>
  • Loading branch information
Phil91 authored Sep 23, 2024
1 parent 418c57b commit 32105bc
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,21 @@ public async Task<ServiceAccountDetails> UpdateOwnCompanyServiceAccountDetailsAs
portalRepositories.GetInstance<IServiceAccountRepository>().GetOwnCompanyServiceAccountsUntracked(_identityData.CompanyId, clientId, isOwner, filterUserStatusIds));
}

public IAsyncEnumerable<UserRoleWithDescription> GetServiceAccountRolesAsync(string? languageShortName) =>
portalRepositories.GetInstance<IUserRolesRepository>().GetServiceAccountRolesAsync(_identityData.CompanyId, _settings.ClientId, languageShortName ?? Constants.DefaultLanguage);
public async IAsyncEnumerable<UserRoleWithDescription> GetServiceAccountRolesAsync(string? languageShortName)
{
var userRolesRepository = portalRepositories.GetInstance<IUserRolesRepository>();
var userRoles = await userRolesRepository.GetUserRoleIdsUntrackedAsync(_settings.DimUserRoles)
.ToListAsync()
.ConfigureAwait(false);
await foreach (var userRole in userRolesRepository.GetServiceAccountRolesAsync(
_identityData.CompanyId,
_settings.ClientId,
userRoles,
languageShortName ?? Constants.DefaultLanguage))
{
yield return userRole;
}
}

public async Task HandleServiceAccountCreationCallback(Guid processId, AuthenticationDetail callbackData)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public class ServiceAccountSettings

[Required]
public string AuthServiceUrl { get; set; } = null!;

[Required]
[DistinctValues("x => x.ClientId")]
public IEnumerable<UserRoleConfig> DimUserRoles { get; set; } = null!;
}

public static class ServiceAccountSettingsExtensions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
using Org.Eclipse.TractusX.Portal.Backend.Dim.Library.Models;
Expand All @@ -36,19 +37,8 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Controllers
[EnvironmentRoute("MVC_ROUTING_BASEPATH", "serviceaccount")]
[Produces("application/json")]
[Consumes("application/json")]
public class ServiceAccountController : ControllerBase
public class ServiceAccountController(IServiceAccountBusinessLogic logic) : ControllerBase
{
private readonly IServiceAccountBusinessLogic _logic;

/// <summary>
/// Creates a new instance of <see cref="ServiceAccountController"/>
/// </summary>
/// <param name="logic">The Service Account Buisness Logic</param>
public ServiceAccountController(IServiceAccountBusinessLogic logic)
{
_logic = logic;
}

/// <summary>
/// Creates a new technical user / service account with selected role under the same org as the requester
/// </summary>
Expand All @@ -66,7 +56,7 @@ public ServiceAccountController(IServiceAccountBusinessLogic logic)
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
public Task<IEnumerable<ServiceAccountDetails>> ExecuteCompanyUserCreation([FromBody] ServiceAccountCreationInfo serviceAccountCreationInfo) =>
_logic.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfo);
logic.CreateOwnCompanyServiceAccountAsync(serviceAccountCreationInfo);

/// <summary>
/// Deletes the service account with the given id
Expand All @@ -86,7 +76,7 @@ public Task<IEnumerable<ServiceAccountDetails>> ExecuteCompanyUserCreation([From
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)]
public async Task<NoContentResult> DeleteServiceAccount([FromRoute] Guid serviceAccountId)
{
await _logic.DeleteOwnCompanyServiceAccountAsync(serviceAccountId).ConfigureAwait(ConfigureAwaitOptions.None);
await logic.DeleteOwnCompanyServiceAccountAsync(serviceAccountId).ConfigureAwait(ConfigureAwaitOptions.None);
return NoContent();
}

Expand All @@ -107,7 +97,7 @@ public async Task<NoContentResult> DeleteServiceAccount([FromRoute] Guid service
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)]
public Task<ServiceAccountConnectorOfferData> GetServiceAccountDetails([FromRoute] Guid serviceAccountId) =>
_logic.GetOwnCompanyServiceAccountDetailsAsync(serviceAccountId);
logic.GetOwnCompanyServiceAccountDetailsAsync(serviceAccountId);

/// <summary>
/// Updates the service account details with the given id.
Expand All @@ -134,7 +124,7 @@ public Task<ServiceAccountConnectorOfferData> GetServiceAccountDetails([FromRout
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)]
public Task<ServiceAccountDetails> PutServiceAccountDetails([FromRoute] Guid serviceAccountId, [FromBody] ServiceAccountEditableDetails serviceAccountDetails) =>
_logic.UpdateOwnCompanyServiceAccountDetailsAsync(serviceAccountId, serviceAccountDetails);
logic.UpdateOwnCompanyServiceAccountDetailsAsync(serviceAccountId, serviceAccountDetails);

/// <summary>
/// Resets the service account credentials for the given service account Id.
Expand All @@ -156,7 +146,7 @@ public Task<ServiceAccountDetails> PutServiceAccountDetails([FromRoute] Guid ser
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status409Conflict)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status502BadGateway)]
public Task<ServiceAccountDetails> ResetServiceAccountCredentials([FromRoute] Guid serviceAccountId) =>
_logic.ResetOwnCompanyServiceAccountSecretAsync(serviceAccountId);
logic.ResetOwnCompanyServiceAccountSecretAsync(serviceAccountId);

/// <summary>
/// Gets the service account data as pagination
Expand All @@ -176,7 +166,7 @@ public Task<ServiceAccountDetails> ResetServiceAccountCredentials([FromRoute] Gu
[Route("owncompany/serviceaccounts")]
[ProducesResponseType(typeof(Pagination.Response<CompanyServiceAccountData>), StatusCodes.Status200OK)]
public Task<Pagination.Response<CompanyServiceAccountData>> GetServiceAccountsData([FromQuery] int page, [FromQuery] int size, [FromQuery] bool? isOwner, [FromQuery] string? clientId, [FromQuery] bool filterForInactive = false, [FromQuery] IEnumerable<UserStatusId>? userStatus = null) =>
_logic.GetOwnCompanyServiceAccountsDataAsync(page, size, clientId, isOwner, filterForInactive, userStatus);
logic.GetOwnCompanyServiceAccountsDataAsync(page, size, clientId, isOwner, filterForInactive, userStatus);

/// <summary>
/// Get all service account roles
Expand All @@ -190,8 +180,8 @@ public Task<ServiceAccountDetails> ResetServiceAccountCredentials([FromRoute] Gu
[Authorize(Policy = PolicyTypes.ValidCompany)]
[Route("user/roles")]
[ProducesResponseType(typeof(List<UserRoleWithDescription>), StatusCodes.Status200OK)]
public IAsyncEnumerable<UserRoleWithDescription> GetServiceAccountRolesAsync(string? languageShortName = null) =>
_logic.GetServiceAccountRolesAsync(languageShortName);
public IAsyncEnumerable<UserRoleWithDescription> GetServiceAccountRolesAsync(string? languageShortName = null)
=> logic.GetServiceAccountRolesAsync(languageShortName);

/// <summary>
/// Get all service account roles
Expand All @@ -206,7 +196,7 @@ public IAsyncEnumerable<UserRoleWithDescription> GetServiceAccountRolesAsync(str
[Route("callback/{processId}")]
public async Task<OkResult> ServiceAccountCreationCallback([FromRoute] Guid processId, [FromBody] AuthenticationDetail callbackData)
{
await _logic.HandleServiceAccountCreationCallback(processId, callbackData).ConfigureAwait(ConfigureAwaitOptions.None);
await logic.HandleServiceAccountCreationCallback(processId, callbackData).ConfigureAwait(ConfigureAwaitOptions.None);
return Ok();
}

Expand All @@ -222,7 +212,7 @@ public async Task<OkResult> ServiceAccountCreationCallback([FromRoute] Guid proc
[Route("callback/{processId}/retrigger-create-dim-technical-user")]
public async Task<OkResult> RetriggerCreateDimTechnicalUser([FromRoute] Guid processId)
{
await _logic.RetriggerDimTechnicalUser(processId, ProcessStepTypeId.RETRIGGER_CREATE_DIM_TECHNICAL_USER).ConfigureAwait(ConfigureAwaitOptions.None);
await logic.RetriggerDimTechnicalUser(processId, ProcessStepTypeId.RETRIGGER_CREATE_DIM_TECHNICAL_USER).ConfigureAwait(ConfigureAwaitOptions.None);
return Ok();
}

Expand All @@ -238,7 +228,7 @@ public async Task<OkResult> RetriggerCreateDimTechnicalUser([FromRoute] Guid pro
[Route("callback/{processId}/retrigger-delete-dim-technical-user")]
public async Task<OkResult> RetriggerDeleteDimTechnicalUser([FromRoute] Guid processId)
{
await _logic.RetriggerDimTechnicalUser(processId, ProcessStepTypeId.RETRIGGER_DELETE_DIM_TECHNICAL_USER).ConfigureAwait(ConfigureAwaitOptions.None);
await logic.RetriggerDimTechnicalUser(processId, ProcessStepTypeId.RETRIGGER_DELETE_DIM_TECHNICAL_USER).ConfigureAwait(ConfigureAwaitOptions.None);
return Ok();
}

Expand All @@ -254,7 +244,7 @@ public async Task<OkResult> RetriggerDeleteDimTechnicalUser([FromRoute] Guid pro
[Route("callback/{processId}/delete")]
public async Task<OkResult> ServiceAccountDeletionCallback([FromRoute] Guid processId)
{
await _logic.HandleServiceAccountDeletionCallback(processId).ConfigureAwait(ConfigureAwaitOptions.None);
await logic.HandleServiceAccountDeletionCallback(processId).ConfigureAwait(ConfigureAwaitOptions.None);
return Ok();
}
}
3 changes: 2 additions & 1 deletion src/administration/Administration.Service/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,8 @@
"ClientId": "",
"EncryptionConfigIndex": 0,
"EncryptionConfigs": [],
"AuthServiceUrl": ""
"AuthServiceUrl": "",
"DimUserRoles": []
},
"Connectors": {
"MaxPageSize": 20,
Expand Down
10 changes: 9 additions & 1 deletion src/portalbackend/PortalBackend.DBAccess/Models/UserRoleData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,16 @@ public record UserRoleData(
public record UserRoleWithDescription(
[property: JsonPropertyName("roleId")] Guid UserRoleId,
[property: JsonPropertyName("roleName")] string UserRoleText,
[property: JsonPropertyName("roleDescription")] string? RoleDescription);
[property: JsonPropertyName("roleDescription")] string? RoleDescription,
[property: JsonPropertyName("roleType")] UserRoleType RoleType
);

public record UserRoleInformation(
[property: JsonPropertyName("roleId")] Guid UserRoleId,
[property: JsonPropertyName("roleName")] string UserRoleText);

public enum UserRoleType
{
Internal = 1,
External = 2
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public interface IUserRolesRepository
IAsyncEnumerable<OfferRoleInfo> GetAppRolesAsync(Guid offerId, Guid companyId, string languageShortName);
IAsyncEnumerable<string> GetClientRolesCompositeAsync(string keyCloakClientId);

IAsyncEnumerable<UserRoleWithDescription> GetServiceAccountRolesAsync(Guid companyId, string clientId, string languageShortName);
IAsyncEnumerable<UserRoleWithDescription> GetServiceAccountRolesAsync(Guid companyId, string clientId, IEnumerable<Guid> externalRoleIds, string languageShortName);

/// <summary>
/// Gets all user role ids for the given offerId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public IAsyncEnumerable<string> GetClientRolesCompositeAsync(string keyCloakClie
.Select(userRole => userRole.UserRoleText)
.AsAsyncEnumerable();

IAsyncEnumerable<UserRoleWithDescription> IUserRolesRepository.GetServiceAccountRolesAsync(Guid companyId, string clientId, string languageShortName) =>
IAsyncEnumerable<UserRoleWithDescription> IUserRolesRepository.GetServiceAccountRolesAsync(Guid companyId, string clientId, IEnumerable<Guid> externalRoleIds, string languageShortName) =>
_dbContext.UserRoles
.AsNoTracking()
.Where(ur => ur.Offer!.AppInstances.Any(ai => ai.IamClient!.ClientClientId == clientId) &&
Expand All @@ -225,7 +225,8 @@ IAsyncEnumerable<UserRoleWithDescription> IUserRolesRepository.GetServiceAccount
userRole.Id,
userRole.UserRoleText,
userRole.UserRoleDescriptions.SingleOrDefault(desc =>
desc.LanguageShortName == languageShortName)!.Description))
desc.LanguageShortName == languageShortName)!.Description,
externalRoleIds.Contains(userRole.Id) ? UserRoleType.External : UserRoleType.Internal))
.AsAsyncEnumerable();

/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ public async Task GetServiceAccountRolesAsync_GetsExpectedData()
// Arrange
var data = _fixture.CreateMany<UserRoleWithDescription>(15);

A.CallTo(() => _userRolesRepository.GetServiceAccountRolesAsync(A<Guid>._, A<string>._, A<string>._))
A.CallTo(() => _userRolesRepository.GetServiceAccountRolesAsync(A<Guid>._, A<string>._, A<IEnumerable<Guid>>._, A<string>._))
.Returns(data.ToAsyncEnumerable());

A.CallTo(() => _portalRepositories.GetInstance<IUserRolesRepository>()).Returns(_userRolesRepository);
Expand All @@ -651,7 +651,7 @@ public async Task GetServiceAccountRolesAsync_GetsExpectedData()
var result = await sut.GetServiceAccountRolesAsync(null).ToListAsync();

// Assert
A.CallTo(() => _userRolesRepository.GetServiceAccountRolesAsync(_identity.CompanyId, ClientId, A<string>._)).MustHaveHappenedOnceExactly();
A.CallTo(() => _userRolesRepository.GetServiceAccountRolesAsync(_identity.CompanyId, ClientId, A<IEnumerable<Guid>>._, A<string>._)).MustHaveHappenedOnceExactly();

result.Should().NotBeNull();
result.Should().HaveCount(15);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,15 @@
"PaddingMode": "PKCS7"
}
],
"AuthServiceUrl": "https://auth.test/auth"
"AuthServiceUrl": "https://auth.test/auth",
"DimUserRoles": [
{
"ClientId": "technical_roles_management",
"UserRoleNames": [
"Identity Wallet Management"
]
}
]
},
"Connectors": {
"MaxPageSize": 20,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration;
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.DBAccess.Tests.Setup;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
Expand Down Expand Up @@ -131,11 +132,13 @@ public async Task GetServiceAccountRolesAsync_WithValidData_ReturnsExpected()
var sut = await CreateSut();

// Act
var data = await sut.GetServiceAccountRolesAsync(_validCompanyId, ClientId, Constants.DefaultLanguage).ToListAsync();
var data = await sut.GetServiceAccountRolesAsync(_validCompanyId, ClientId, Enumerable.Repeat(new Guid("607818be-4978-41f4-bf63-fa8d2de51157"), 1), Constants.DefaultLanguage).ToListAsync();

// Assert
data.Should().HaveCount(13);
data.Should().OnlyHaveUniqueItems();
data.Where(x => x.RoleType == UserRoleType.Internal).Should().HaveCount(12);
data.Where(x => x.RoleType == UserRoleType.External).Should().ContainSingle();
}

#endregion
Expand Down

0 comments on commit 32105bc

Please sign in to comment.