diff --git a/src/Api/AdminConsole/Controllers/OrganizationUsersController.cs b/src/Api/AdminConsole/Controllers/OrganizationUsersController.cs index 37b58bc252..081a86c9ad 100644 --- a/src/Api/AdminConsole/Controllers/OrganizationUsersController.cs +++ b/src/Api/AdminConsole/Controllers/OrganizationUsersController.cs @@ -324,6 +324,12 @@ public class OrganizationUsersController : BaseAdminConsoleController throw new UnauthorizedAccessException(); } + var organizationUser = await _organizationUserRepository.GetByIdAsync(organizationUserId); + if (organizationUser == null || organizationUser.OrganizationId != orgId) + { + throw new NotFoundException("Organization user mismatch"); + } + var useMasterPasswordPolicy = _featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements) ? (await _policyRequirementQuery.GetAsync(user.Id)).AutoEnrollEnabled(orgId) : await ShouldHandleResetPasswordAsync(orgId); diff --git a/test/Api.Test/AdminConsole/Controllers/OrganizationUsersControllerTests.cs b/test/Api.Test/AdminConsole/Controllers/OrganizationUsersControllerTests.cs index 68a63bf579..7edd3c662c 100644 --- a/test/Api.Test/AdminConsole/Controllers/OrganizationUsersControllerTests.cs +++ b/test/Api.Test/AdminConsole/Controllers/OrganizationUsersControllerTests.cs @@ -121,10 +121,37 @@ public class OrganizationUsersControllerTests [Theory] [BitAutoData] - public async Task Accept_NoMasterPasswordReset(Guid orgId, Guid orgUserId, - OrganizationUserAcceptRequestModel model, User user, SutProvider sutProvider) + public async Task Accept_WhenOrganizationUserNotFound_ThrowsNotFoundException( + Guid orgId, Guid orgUserId, OrganizationUserAcceptRequestModel model, User user, + SutProvider sutProvider) { sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user); + sutProvider.GetDependency().GetByIdAsync(orgUserId).Returns((OrganizationUser)null); + + await Assert.ThrowsAsync(() => sutProvider.Sut.Accept(orgId, orgUserId, model)); + } + + [Theory] + [BitAutoData] + public async Task Accept_WhenOrganizationIdMismatch_ThrowsNotFoundException( + Guid orgId, Guid orgUserId, OrganizationUserAcceptRequestModel model, User user, OrganizationUser organizationUser, + SutProvider sutProvider) + { + organizationUser.OrganizationId = Guid.NewGuid(); // Different org ID + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user); + sutProvider.GetDependency().GetByIdAsync(orgUserId).Returns(organizationUser); + + await Assert.ThrowsAsync(() => sutProvider.Sut.Accept(orgId, orgUserId, model)); + } + + [Theory] + [BitAutoData] + public async Task Accept_NoMasterPasswordReset(Guid orgId, Guid orgUserId, + OrganizationUserAcceptRequestModel model, User user, OrganizationUser organizationUser, SutProvider sutProvider) + { + organizationUser.OrganizationId = orgId; + sutProvider.GetDependency().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user); + sutProvider.GetDependency().GetByIdAsync(orgUserId).Returns(organizationUser); await sutProvider.Sut.Accept(orgId, orgUserId, model); @@ -137,17 +164,19 @@ public class OrganizationUsersControllerTests [Theory] [BitAutoData] public async Task Accept_WhenOrganizationUsePoliciesIsEnabledAndResetPolicyIsEnabled_ShouldHandleResetPassword(Guid orgId, Guid orgUserId, - OrganizationUserAcceptRequestModel model, User user, + OrganizationUserAcceptRequestModel model, User user, OrganizationUser organizationUser, [Policy(PolicyType.ResetPassword, true)] PolicyStatus policy, SutProvider sutProvider) { // Arrange + organizationUser.OrganizationId = orgId; var applicationCacheService = sutProvider.GetDependency(); applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true }); policy.Data = CoreHelpers.ClassToJsonData(new ResetPasswordDataModel { AutoEnrollEnabled = true, }); var userService = sutProvider.GetDependency(); userService.GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user); + sutProvider.GetDependency().GetByIdAsync(orgUserId).Returns(organizationUser); var policyQuery = sutProvider.GetDependency(); policyQuery.RunAsync(orgId, @@ -171,17 +200,19 @@ public class OrganizationUsersControllerTests [Theory] [BitAutoData] public async Task Accept_WhenOrganizationUsePoliciesIsDisabled_ShouldNotHandleResetPassword(Guid orgId, Guid orgUserId, - OrganizationUserAcceptRequestModel model, User user, + OrganizationUserAcceptRequestModel model, User user, OrganizationUser organizationUser, [Policy(PolicyType.ResetPassword, true)] PolicyStatus policy, SutProvider sutProvider) { // Arrange + organizationUser.OrganizationId = orgId; var applicationCacheService = sutProvider.GetDependency(); applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = false }); policy.Data = CoreHelpers.ClassToJsonData(new ResetPasswordDataModel { AutoEnrollEnabled = true, }); var userService = sutProvider.GetDependency(); userService.GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user); + sutProvider.GetDependency().GetByIdAsync(orgUserId).Returns(organizationUser); var policyQuery = sutProvider.GetDependency(); policyQuery.RunAsync(orgId, @@ -360,13 +391,15 @@ public class OrganizationUsersControllerTests [Theory] [BitAutoData] public async Task Accept_WhenOrganizationUsePoliciesIsEnabledAndResetPolicyIsEnabled_WithPolicyRequirementsEnabled_ShouldHandleResetPassword(Guid orgId, Guid orgUserId, - OrganizationUserAcceptRequestModel model, User user, SutProvider sutProvider) + OrganizationUserAcceptRequestModel model, User user, OrganizationUser organizationUser, SutProvider sutProvider) { // Arrange + organizationUser.OrganizationId = orgId; var applicationCacheService = sutProvider.GetDependency(); applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true }); sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.PolicyRequirements).Returns(true); + sutProvider.GetDependency().GetByIdAsync(orgUserId).Returns(organizationUser); var policy = new Policy { @@ -403,14 +436,16 @@ public class OrganizationUsersControllerTests [Theory] [BitAutoData] public async Task Accept_WithInvalidModelResetPasswordKey_WithPolicyRequirementsEnabled_ThrowsBadRequestException(Guid orgId, Guid orgUserId, - OrganizationUserAcceptRequestModel model, User user, SutProvider sutProvider) + OrganizationUserAcceptRequestModel model, User user, OrganizationUser organizationUser, SutProvider sutProvider) { // Arrange model.ResetPasswordKey = " "; + organizationUser.OrganizationId = orgId; var applicationCacheService = sutProvider.GetDependency(); applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true }); sutProvider.GetDependency().IsEnabled(FeatureFlagKeys.PolicyRequirements).Returns(true); + sutProvider.GetDependency().GetByIdAsync(orgUserId).Returns(organizationUser); var policy = new Policy {