Skip to content

Commit

Permalink
feat(user): adding admin details for GetOwnUserDetails (#32)
Browse files Browse the repository at this point in the history
* Endpoint GET: api/administration/user/ownUser is being enhanced by adding into the response body the users company administratorsAdd details of admin-users.
Ref: CPLP2598
---------
Co-authored-by: VPrasannaK94 <prasannakumar.v@partner.bmw.in>
Reviewed-By: Norbert Truchsess <norbert.truchsess@t-online.de>
  • Loading branch information
ntruchsess authored May 16, 2023
1 parent f6a4a42 commit a7028c4
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public interface IUserBusinessLogic
Task<CompanyUserDetails> GetOwnCompanyUserDetailsAsync(Guid companyUserId, string iamUserId);
Task<int> AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid companyUserId, IEnumerable<string> businessPartnerNumbers, string adminUserId);
Task<int> AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid companyUserId, string businessPartnerNumber, string adminUserId);
Task<CompanyUserDetails> GetOwnUserDetails(string iamUserId);
Task<CompanyOwnUserDetails> GetOwnUserDetails(string iamUserId);
Task<CompanyUserDetails> UpdateOwnUserDetails(Guid companyUserId, OwnCompanyUserEditableDetails ownCompanyUserEditableDetails, string iamUserId);

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,11 @@ public async Task<int> AddOwnCompanyUsersBusinessPartnerNumbersAsync(Guid compan
public Task<int> AddOwnCompanyUsersBusinessPartnerNumberAsync(Guid companyUserId, string businessPartnerNumber, string adminUserId) =>
AddOwnCompanyUsersBusinessPartnerNumbersAsync(companyUserId, Enumerable.Repeat(businessPartnerNumber, 1), adminUserId);

public async Task<CompanyUserDetails> GetOwnUserDetails(string iamUserId)
public async Task<CompanyOwnUserDetails> GetOwnUserDetails(string iamUserId)
{
var details = await _portalRepositories.GetInstance<IUserRepository>().GetUserDetailsUntrackedAsync(iamUserId).ConfigureAwait(false);
var userRoleIds = await _portalRepositories.GetInstance<IUserRolesRepository>()
.GetUserRoleIdsUntrackedAsync(_settings.UserAdminRoles).ToListAsync().ConfigureAwait(false);
var details = await _portalRepositories.GetInstance<IUserRepository>().GetUserDetailsUntrackedAsync(iamUserId, userRoleIds).ConfigureAwait(false);
if (details == null)
{
throw new NotFoundException($"no company-user data found for user {iamUserId}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ public UserSettings()
/// <value></value>
[Required]
public IEnumerable<CompanyUserStatusId> CompanyUserStatusIds { get; set; } = null!;

/// <summary>
/// Company User Status Id
/// </summary>
[Required]
public IDictionary<string,IEnumerable<string>> UserAdminRoles { get; set; } = null!;
}

public class UserSetting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,9 @@ public IAsyncEnumerable<ClientRoles> GetClientRolesAsync([FromRoute] Guid appId,
[HttpGet]
[Authorize(Roles = "view_own_user_account")]
[Route("ownUser")]
[ProducesResponseType(typeof(CompanyUserDetails), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(CompanyOwnUserDetails), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
public Task<CompanyUserDetails> GetOwnUserDetails() =>
public Task<CompanyOwnUserDetails> GetOwnUserDetails() =>
this.WithIamUserId(iamUserId => _logic.GetOwnUserDetails(iamUserId));

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;

public record CompanyUserDetails(
[property: JsonPropertyName("companyUserId")] Guid companyUserId,
[property: JsonPropertyName("created")] DateTimeOffset createdAt,
[property: JsonPropertyName("bpn")] IEnumerable<string> businessPartnerNumbers,
[property: JsonPropertyName("company")] string companyName,
[property: JsonPropertyName("status")] CompanyUserStatusId companyUserStatusId,
[property: JsonPropertyName("assignedRoles")] IEnumerable<CompanyUserAssignedRoleDetails> assignedRoles)
[property: JsonPropertyName("companyUserId")] Guid Company2UserId,
[property: JsonPropertyName("created")] DateTimeOffset CreatedAt,
[property: JsonPropertyName("bpn")] IEnumerable<string> BusinessPartnerNumbers,
[property: JsonPropertyName("company")] string CompanyName,
[property: JsonPropertyName("status")] CompanyUserStatusId CompanyUserStatusId,
[property: JsonPropertyName("assignedRoles")] IEnumerable<CompanyUserAssignedRoleDetails> AssignedRoles)
{
[JsonPropertyName("firstName")]
public string? FirstName { get; set; }
Expand All @@ -41,6 +41,29 @@ public record CompanyUserDetails(
public string? Email { get; set; }
}

public record CompanyOwnUserDetails(
[property: JsonPropertyName("companyUserId")] Guid CompanyUserId,
[property: JsonPropertyName("created")] DateTimeOffset CreatedAt,
[property: JsonPropertyName("bpn")] IEnumerable<string> BusinessPartnerNumbers,
[property: JsonPropertyName("company")] string CompanyName,
[property: JsonPropertyName("status")] CompanyUserStatusId CompanyUserStatusId,
[property: JsonPropertyName("assignedRoles")] IEnumerable<CompanyUserAssignedRoleDetails> AssignedRoles,
[property: JsonPropertyName("admin")] IEnumerable<CompanyUserAdminDetails> AdminDetails)
{
[JsonPropertyName("firstName")]
public string? FirstName { get; set; }

[JsonPropertyName("lastName")]
public string? LastName { get; set; }

[JsonPropertyName("email")]
public string? Email { get; set; }
}

public record CompanyUserAdminDetails(
[property: JsonPropertyName("id")] Guid CompanyUserId,
[property: JsonPropertyName("email")] string? Email);

public record CompanyUserAssignedRoleDetails(
[property: JsonPropertyName("appId")] Guid OfferId,
[property: JsonPropertyName("roles")] IEnumerable<string> UserRoles);
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public interface IUserRepository
/// <returns>Returns the id of the CompanyUser</returns>
Task<Guid> GetCompanyUserIdForIamUserUntrackedAsync(string userId);

Task<CompanyUserDetails?> GetUserDetailsUntrackedAsync(string iamUserId);
Task<CompanyOwnUserDetails?> GetUserDetailsUntrackedAsync(string iamUserId, IEnumerable<Guid> userRoleIds);
Task<CompanyUserWithIdpBusinessPartnerData?> GetUserWithCompanyIdpAsync(string iamUserId);
Task<Guid> GetCompanyUserIdForUserApplicationUntrackedAsync(Guid applicationId, string iamUserId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,12 @@ public Task<Guid> GetCompanyIdForIamUserUntrackedAsync(string iamUserId) =>
iamUser.CompanyUser.Company!.CompanyAssignedRoles.SelectMany(car => car.CompanyRole!.CompanyRoleAssignedRoleCollection!.UserRoleCollection!.UserRoles.Where(ur => ur.Offer!.AppInstances.Any(ai => ai.IamClient!.ClientClientId == technicalUserClientId)).Select(ur => ur.Id)).Distinct()))
.SingleOrDefaultAsync();

public Task<CompanyUserDetails?> GetUserDetailsUntrackedAsync(string iamUserId) =>
public Task<CompanyOwnUserDetails?> GetUserDetailsUntrackedAsync(string iamUserId, IEnumerable<Guid> userRoleIds) =>
_dbContext.CompanyUsers
.AsNoTracking()
.AsSplitQuery()
.Where(companyUser => companyUser.IamUser!.UserEntityId == iamUserId)
.Select(companyUser => new CompanyUserDetails(
.Select(companyUser => new CompanyOwnUserDetails(
companyUser.Id,
companyUser.DateCreated,
companyUser.CompanyUserAssignedBusinessPartners.Select(assignedPartner =>
Expand All @@ -244,8 +245,11 @@ public Task<Guid> GetCompanyIdForIamUserUntrackedAsync(string iamUserId) =>
app.Offer!.UserRoles
.Where(role => role.CompanyUsers.Any(user => user.Id == companyUser.Id))
.Select(role => role.UserRoleText)
))
)
)),
companyUser.Company.CompanyUsers.Where(user => user.UserRoles.Any(role => userRoleIds.Contains(role.Id)))
.Select(admin => new CompanyUserAdminDetails(
admin.Id,
admin.Email)))
{
FirstName = companyUser.Firstname,
LastName = companyUser.Lastname,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ public UserBusinessLogicTests()
}
};
_error = _fixture.Create<TestException>();

A.CallTo(() => _portalRepositories.GetInstance<IUserRepository>()).Returns(_userRepository);
A.CallTo(() => _portalRepositories.GetInstance<IUserRolesRepository>()).Returns(_userRolesRepository);
A.CallTo(() => _portalRepositories.GetInstance<INotificationRepository>()).Returns(_notificationRepository);
}

#region CreateOwnCompanyUsersAsync
Expand Down Expand Up @@ -1323,7 +1327,53 @@ public async Task GetOwnCompanyAppUsersAsync_WithValidData_ThrowsForbiddenExcept
}

#endregion


#region GetOwnUserDetails

[Fact]
public async Task GetOwnUserDetails_ReturnsExpected()
{
// Arrange
var companyOwnUserDetails = _fixture.Create<CompanyOwnUserDetails>();
var iamUserId = _fixture.Create<Guid>().ToString();
var userRoleIds = new [] { _fixture.Create<Guid>(), _fixture.Create<Guid>()};

A.CallTo(() => _userRolesRepository.GetUserRoleIdsUntrackedAsync(A<IDictionary<string, IEnumerable<string>>>._))
.Returns(userRoleIds.ToAsyncEnumerable());
A.CallTo(() => _userRepository.GetUserDetailsUntrackedAsync(A<string>._, A<IEnumerable<Guid>>._))
.Returns(companyOwnUserDetails);
var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, null!, _logger, _options);

// Act
var result = await sut.GetOwnUserDetails(iamUserId).ConfigureAwait(false);

// Assert
A.CallTo(() => _userRolesRepository.GetUserRoleIdsUntrackedAsync(A<IDictionary<string, IEnumerable<string>>>
.That.IsSameSequenceAs(_options.Value.UserAdminRoles))).MustHaveHappenedOnceExactly();
A.CallTo(() => _userRepository.GetUserDetailsUntrackedAsync(iamUserId, A<IEnumerable<Guid>>.That.IsSameSequenceAs(userRoleIds))).MustHaveHappenedOnceExactly();
result.Should().Be(companyOwnUserDetails);
}

[Fact]
public async Task GetOwnUserDetails_ThrowsNotFoundException()
{
// Arrange
var iamUserId = _fixture.Create<Guid>().ToString();

A.CallTo(() => _userRepository.GetUserDetailsUntrackedAsync(iamUserId,A<IEnumerable<Guid>>._))
.Returns((CompanyOwnUserDetails) default!);
var sut = new UserBusinessLogic(_provisioningManager, null!, null!, _portalRepositories, null!, _logger, _options);

// Act
async Task Act() => await sut.GetOwnUserDetails(iamUserId).ConfigureAwait(false);

// Assert
var error = await Assert.ThrowsAsync<NotFoundException>(Act).ConfigureAwait(false);
error.Message.Should().Be($"no company-user data found for user {iamUserId}");
}

#endregion

#region Setup

private void SetupFakesForUserCreation(bool isBulkUserCreation)
Expand Down Expand Up @@ -1465,9 +1515,6 @@ private void SetupFakesForUserRoleModification(List<Notification>? notifications
}

_fixture.Inject(_provisioningManager);
A.CallTo(() => _portalRepositories.GetInstance<IUserRepository>()).Returns(_userRepository);
A.CallTo(() => _portalRepositories.GetInstance<IUserRolesRepository>()).Returns(_userRolesRepository);
A.CallTo(() => _portalRepositories.GetInstance<INotificationRepository>()).Returns(_notificationRepository);
}

private UserCreationInfo CreateUserCreationInfo() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ public class UserControllerTest
private readonly IUserBusinessLogic _logic;
private readonly IUserRolesBusinessLogic _rolesLogic;
private readonly UserController _controller;
private readonly Fixture _fixture;

public UserControllerTest()
{
_fixture = new Fixture();
_logic = A.Fake<IUserBusinessLogic>();
_rolesLogic = A.Fake<IUserRolesBusinessLogic>();
var logger = A.Fake<ILogger<UserController>>();
Expand All @@ -62,4 +64,20 @@ public async Task ModifyUserRolesAsync_WithValidData_ReturnsExpectedResult()
Assert.IsType<List<UserRoleWithId>>(result);
result.Should().BeEmpty();
}

[Fact]
public async Task GetOwnUserDetails_ReturnsExpectedResult()
{
// Arrange
var data = _fixture.Create<CompanyOwnUserDetails>();
A.CallTo(() => _logic.GetOwnUserDetails(IamUserId))
.Returns(data);

// Act
var result = await this._controller.GetOwnUserDetails().ConfigureAwait(false);

// Assert
A.CallTo(() => _logic.GetOwnUserDetails(IamUserId)).MustHaveHappenedOnceExactly();
result.Should().Be(data);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,12 @@
"Portal": {
"KeycloakClientID": "test",
"BasePortalAddress": "https://test-portal.azurewebsites.net"
},
"UserAdminRoles": {
"Cl2-CX-Portal": [
"Company Admin",
"IT Admin"
]
}
},
"ApplicationChecklist": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,15 @@
"company_user_id": "ac1cf001-7fbc-1f2f-817f-bce058020006",
"user_role_id": "aabcdfeb-6669-4c74-89f0-19cda090873e",
"last_editor_id": null
},
{
"company_user_id": "ac1cf001-7fbc-1f2f-817f-bce058019992",
"user_role_id": "efc20368-9e82-46ff-b88f-6495b9810254",
"last_editor_id": null
},
{
"company_user_id": "ac1cf001-7fbc-1f2f-817f-bce058019993",
"user_role_id": "efc20368-9e82-46ff-b88f-6495b9810254",
"last_editor_id": null
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,18 @@
"user_role": "test",
"offer_id": "a16e73b9-5277-4b69-9f8d-3b227495dfea",
"last_editor_id": null
},
{
"id": "efc20368-9e82-46ff-b88f-6495b9810254",
"user_role": "Company Admin",
"offer_id": "a16e73b9-5277-4b69-9f8d-3b227495dfea",
"last_editor_id": null
}
,
{
"id": "efc20368-9e82-46ff-b88f-6495b9810255",
"user_role": "IT Admin",
"offer_id": "a16e73b9-5277-4b69-9f8d-3b227495dfea",
"last_editor_id": null
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,36 @@ public async Task GetCoreOfferAssignedIamClientUserDataUntrackedAsync_ReturnsExp

#endregion

#region GetUserDetails

[Fact]
public async Task GetUserDetailsUntrackedAsync_ReturnsExpected()
{
// Arrange
var sut = await CreateSut().ConfigureAwait(false);
var userRoleIds = new []{
new Guid("efc20368-9e82-46ff-b88f-6495b9810255"),
new Guid("efc20368-9e82-46ff-b88f-6495b9810254")};

// Act
var result = await sut.GetUserDetailsUntrackedAsync("e5e403d5-3bd9-48f6-8931-7c0c717c3f40", userRoleIds).ConfigureAwait(false);

// Assert
result.Should().NotBeNull();
result!.CompanyName.Should().Be("Security Company");
result.CompanyUserId.Should().Be("ac1cf001-7fbc-1f2f-817f-bce058019992");
result.Email.Should().Be("julia.jeroch@bmw.de");
result.FirstName.Should().Be("Test User");
result.BusinessPartnerNumbers.Should().BeEmpty();
result.AdminDetails.Should().NotBeEmpty()
.And.HaveCount(2)
.And.Satisfy(
x => x.CompanyUserId == new Guid("ac1cf001-7fbc-1f2f-817f-bce058019992") && x.Email == "julia.jeroch@bmw.de",
x => x.CompanyUserId == new Guid("ac1cf001-7fbc-1f2f-817f-bce058019993") && x.Email == "julia.jeroch@bmw.de");
}

#endregion

private async Task<UserRepository> CreateSut()
{
var context = await _dbTestDbFixture.GetPortalDbContext().ConfigureAwait(false);
Expand Down

0 comments on commit a7028c4

Please sign in to comment.