Ensure org user belongs to org they're being invited to

This commit is contained in:
Sven 2026-02-02 15:01:30 -06:00
parent d4de03a762
commit 6a46488c89
No known key found for this signature in database
2 changed files with 47 additions and 6 deletions

View File

@ -324,6 +324,12 @@ public class OrganizationUsersController : BaseAdminConsoleController
throw new UnauthorizedAccessException(); 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) var useMasterPasswordPolicy = _featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements)
? (await _policyRequirementQuery.GetAsync<ResetPasswordPolicyRequirement>(user.Id)).AutoEnrollEnabled(orgId) ? (await _policyRequirementQuery.GetAsync<ResetPasswordPolicyRequirement>(user.Id)).AutoEnrollEnabled(orgId)
: await ShouldHandleResetPasswordAsync(orgId); : await ShouldHandleResetPasswordAsync(orgId);

View File

@ -121,10 +121,37 @@ public class OrganizationUsersControllerTests
[Theory] [Theory]
[BitAutoData] [BitAutoData]
public async Task Accept_NoMasterPasswordReset(Guid orgId, Guid orgUserId, public async Task Accept_WhenOrganizationUserNotFound_ThrowsNotFoundException(
OrganizationUserAcceptRequestModel model, User user, SutProvider<OrganizationUsersController> sutProvider) Guid orgId, Guid orgUserId, OrganizationUserAcceptRequestModel model, User user,
SutProvider<OrganizationUsersController> sutProvider)
{ {
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user); sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user);
sutProvider.GetDependency<IOrganizationUserRepository>().GetByIdAsync(orgUserId).Returns((OrganizationUser)null);
await Assert.ThrowsAsync<NotFoundException>(() => 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<OrganizationUsersController> sutProvider)
{
organizationUser.OrganizationId = Guid.NewGuid(); // Different org ID
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user);
sutProvider.GetDependency<IOrganizationUserRepository>().GetByIdAsync(orgUserId).Returns(organizationUser);
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.Accept(orgId, orgUserId, model));
}
[Theory]
[BitAutoData]
public async Task Accept_NoMasterPasswordReset(Guid orgId, Guid orgUserId,
OrganizationUserAcceptRequestModel model, User user, OrganizationUser organizationUser, SutProvider<OrganizationUsersController> sutProvider)
{
organizationUser.OrganizationId = orgId;
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user);
sutProvider.GetDependency<IOrganizationUserRepository>().GetByIdAsync(orgUserId).Returns(organizationUser);
await sutProvider.Sut.Accept(orgId, orgUserId, model); await sutProvider.Sut.Accept(orgId, orgUserId, model);
@ -137,17 +164,19 @@ public class OrganizationUsersControllerTests
[Theory] [Theory]
[BitAutoData] [BitAutoData]
public async Task Accept_WhenOrganizationUsePoliciesIsEnabledAndResetPolicyIsEnabled_ShouldHandleResetPassword(Guid orgId, Guid orgUserId, 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, [Policy(PolicyType.ResetPassword, true)] PolicyStatus policy,
SutProvider<OrganizationUsersController> sutProvider) SutProvider<OrganizationUsersController> sutProvider)
{ {
// Arrange // Arrange
organizationUser.OrganizationId = orgId;
var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>(); var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>();
applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true }); applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true });
policy.Data = CoreHelpers.ClassToJsonData(new ResetPasswordDataModel { AutoEnrollEnabled = true, }); policy.Data = CoreHelpers.ClassToJsonData(new ResetPasswordDataModel { AutoEnrollEnabled = true, });
var userService = sutProvider.GetDependency<IUserService>(); var userService = sutProvider.GetDependency<IUserService>();
userService.GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user); userService.GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user);
sutProvider.GetDependency<IOrganizationUserRepository>().GetByIdAsync(orgUserId).Returns(organizationUser);
var policyQuery = sutProvider.GetDependency<IPolicyQuery>(); var policyQuery = sutProvider.GetDependency<IPolicyQuery>();
policyQuery.RunAsync(orgId, policyQuery.RunAsync(orgId,
@ -171,17 +200,19 @@ public class OrganizationUsersControllerTests
[Theory] [Theory]
[BitAutoData] [BitAutoData]
public async Task Accept_WhenOrganizationUsePoliciesIsDisabled_ShouldNotHandleResetPassword(Guid orgId, Guid orgUserId, 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, [Policy(PolicyType.ResetPassword, true)] PolicyStatus policy,
SutProvider<OrganizationUsersController> sutProvider) SutProvider<OrganizationUsersController> sutProvider)
{ {
// Arrange // Arrange
organizationUser.OrganizationId = orgId;
var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>(); var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>();
applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = false }); applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = false });
policy.Data = CoreHelpers.ClassToJsonData(new ResetPasswordDataModel { AutoEnrollEnabled = true, }); policy.Data = CoreHelpers.ClassToJsonData(new ResetPasswordDataModel { AutoEnrollEnabled = true, });
var userService = sutProvider.GetDependency<IUserService>(); var userService = sutProvider.GetDependency<IUserService>();
userService.GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user); userService.GetUserByPrincipalAsync(default).ReturnsForAnyArgs(user);
sutProvider.GetDependency<IOrganizationUserRepository>().GetByIdAsync(orgUserId).Returns(organizationUser);
var policyQuery = sutProvider.GetDependency<IPolicyQuery>(); var policyQuery = sutProvider.GetDependency<IPolicyQuery>();
policyQuery.RunAsync(orgId, policyQuery.RunAsync(orgId,
@ -360,13 +391,15 @@ public class OrganizationUsersControllerTests
[Theory] [Theory]
[BitAutoData] [BitAutoData]
public async Task Accept_WhenOrganizationUsePoliciesIsEnabledAndResetPolicyIsEnabled_WithPolicyRequirementsEnabled_ShouldHandleResetPassword(Guid orgId, Guid orgUserId, public async Task Accept_WhenOrganizationUsePoliciesIsEnabledAndResetPolicyIsEnabled_WithPolicyRequirementsEnabled_ShouldHandleResetPassword(Guid orgId, Guid orgUserId,
OrganizationUserAcceptRequestModel model, User user, SutProvider<OrganizationUsersController> sutProvider) OrganizationUserAcceptRequestModel model, User user, OrganizationUser organizationUser, SutProvider<OrganizationUsersController> sutProvider)
{ {
// Arrange // Arrange
organizationUser.OrganizationId = orgId;
var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>(); var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>();
applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true }); applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true });
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.PolicyRequirements).Returns(true); sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.PolicyRequirements).Returns(true);
sutProvider.GetDependency<IOrganizationUserRepository>().GetByIdAsync(orgUserId).Returns(organizationUser);
var policy = new Policy var policy = new Policy
{ {
@ -403,14 +436,16 @@ public class OrganizationUsersControllerTests
[Theory] [Theory]
[BitAutoData] [BitAutoData]
public async Task Accept_WithInvalidModelResetPasswordKey_WithPolicyRequirementsEnabled_ThrowsBadRequestException(Guid orgId, Guid orgUserId, public async Task Accept_WithInvalidModelResetPasswordKey_WithPolicyRequirementsEnabled_ThrowsBadRequestException(Guid orgId, Guid orgUserId,
OrganizationUserAcceptRequestModel model, User user, SutProvider<OrganizationUsersController> sutProvider) OrganizationUserAcceptRequestModel model, User user, OrganizationUser organizationUser, SutProvider<OrganizationUsersController> sutProvider)
{ {
// Arrange // Arrange
model.ResetPasswordKey = " "; model.ResetPasswordKey = " ";
organizationUser.OrganizationId = orgId;
var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>(); var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>();
applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true }); applicationCacheService.GetOrganizationAbilityAsync(orgId).Returns(new OrganizationAbility { UsePolicies = true });
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.PolicyRequirements).Returns(true); sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.PolicyRequirements).Returns(true);
sutProvider.GetDependency<IOrganizationUserRepository>().GetByIdAsync(orgUserId).Returns(organizationUser);
var policy = new Policy var policy = new Policy
{ {