Files
server/test/Api.Test/AdminConsole/Models/Request/Organizations/CreateOrganizationInviteLinkRequestModelTests.cs
Rui Tomé 2a52362d33 [PM-34387] Add organization invite link creation endpoint (#7477)
* Add ConflictError type

* Add generic Handle<T> and extract MapError on BaseAdminConsoleController

* Initialize Code property with a new GUID in OrganizationInviteLink class

* Add ICreateOrganizationInviteLinkCommand interface

* Add CreateOrganizationInviteLinkRequest record for invite link creation

* Add OrganizationInviteLink request and response models for invite link management

* Refactor ICreateOrganizationInviteLinkCommand interface to use CreateOrganizationInviteLinkRequest for invite link creation

* Add CreateOrganizationInviteLinkCommand class to handle invite link creation logic, including domain sanitization and validation checks.

* Add error handling for invite link creation with specific conflict and validation errors

* Add OrganizationInviteLink service commands to OrganizationServiceCollectionExtensions

* Add OrganizationInviteLinksController to manage invite link creation for organizations

* Add integration tests for OrganizationInviteLinksController and CreateOrganizationInviteLinkCommand to validate invite link creation logic, including success and error scenarios.

* Remove unnecessary blank line in OrganizationInviteLinksControllerTests class

* Refactor CreateOrganizationInviteLinkRequestModel to use required properties for AllowedDomains and EncryptedInviteKey

* Update CreateOrganizationInviteLinkCommand to validate allowed domains by using DomainNameValidator

* Add encryption validation attributes to CreateOrganizationInviteLinkRequestModel and implement unit tests for model validation

* Refactor OrganizationInviteLink to encapsulate AllowedDomains serialization logic within methods. Update OrganizationInviteLinkResponseModel to utilize new GetAllowedDomains method for improved clarity and maintainability.

* Enhance domain sanitization in CreateOrganizationInviteLinkCommand by converting domains to lowercase during trimming for improved consistency.

* Update OrganizationInviteLinksControllerTests to use a valid encrypted invite key constant for consistency in test cases.

* Add ability check for organization invite links in CreateOrganizationInviteLinkCommand

- Introduced a new method to verify if an organization can use invite links based on its ability.
- Added a new error type for cases where invite links are not available due to organizational plan restrictions.
- Updated tests to cover scenarios where the organization lacks the ability to create invite links.

* Add documentation for Code property in OrganizationInviteLink class

- Added XML summary comments to the Code property to clarify its purpose and generation method.
- Explained the choice of using Guid.NewGuid for the Code to avoid predictability and ensure uniqueness.

* Implement domain validation in CreateOrganizationInviteLinkRequestModel

- Added IValidatableObject implementation to CreateOrganizationInviteLinkRequestModel for domain validation.
- Introduced Validate method to check the format of allowed domains and return appropriate validation results.
- Updated tests to cover scenarios for invalid domain formats and mixed valid/invalid domains.
- Removed redundant domain validation logic from CreateOrganizationInviteLinkCommand.

* Remove outdated tests from CreateOrganizationInviteLinkRequestModelTests

- Deleted tests for validating EncryptedInviteKey and EncryptedOrgKey as they are no longer relevant.
- Cleaned up the test class to focus on current validation logic for allowed domains.

* Refactor GetAllowedDomains method in OrganizationInviteLink class

- Updated the GetAllowedDomains method to return an empty array instead of throwing a JsonException when deserialization fails.
- This change improves the method's resilience by providing a default value for invalid or missing allowed domains.

* Remove unused InviteLinkInvalidDomains error type from Errors.cs

- Deleted the InviteLinkInvalidDomains record as it is no longer needed.
- This cleanup aligns with recent changes in domain validation logic and improves code maintainability.

* Update OrganizationServiceCollectionExtensions to use TryAddScoped for command registration

- Changed the registration of ICreateOrganizationInviteLinkCommand to use TryAddScoped instead of AddScoped.

* Mock organization ability retrieval in OrganizationInviteLinksControllerTests

* Add ValidateSequenceAttribute for collection validation and corresponding unit tests

* Refactor CreateOrganizationInviteLinkRequestModel to use ValidateSequenceAttribute for domain validation and update unit tests for improved error handling.

* Enhance ValidateSequenceAttribute to handle null values and improve error messaging format

* Add empty line

* Refactor ValidateSequenceAttribute to support IEnumerable interface for improved type handling

* Refactor ValidateSequenceAttribute to improve validation logic and error handling for IEnumerable types

* Remove unused using directive for Microsoft.AspNetCore.Http.HttpResults in BaseAdminConsoleController.cs

* Add MinLength validation to AllowedDomains in CreateOrganizationInviteLinkRequestModel and implement unit test for empty AllowedDomains scenario

* Refactor CreateOrganizationInviteLinkCommandTests to move SetupAbility method for better organization and readability

* Add error handling methods in BaseAdminConsoleController for improved response management

* Update CreateOrganizationInviteLinkRequestModelTests to use array initialization syntax for AllowedDomains so that MinLength attribute works

* Refactor OrganizationInviteLinkResponseModel constructor for improved readability
2026-05-01 14:23:56 +01:00

84 lines
2.6 KiB
C#

using System.ComponentModel.DataAnnotations;
using Bit.Api.AdminConsole.Models.Request.Organizations;
using Xunit;
namespace Bit.Api.Test.AdminConsole.Models.Request.Organizations;
public class CreateOrganizationInviteLinkRequestModelTests
{
private const string _validEncryptedString =
"2.AOs41Hd8OQiCPXjyJKCiDA==|O6OHgt2U2hJGBSNGnimJmg==|iD33s8B69C8JhYYhSa4V1tArjvLr8eEaGqOV7BRo5Jk=";
[Fact]
public void Validate_ValidModel_ReturnsNoErrors()
{
var model = new CreateOrganizationInviteLinkRequestModel
{
AllowedDomains = new[] { "acme.com" },
EncryptedInviteKey = _validEncryptedString,
};
var results = Validate(model);
Assert.Empty(results);
}
[Theory]
[InlineData("not a domain")]
[InlineData("<script>alert(1)</script>")]
[InlineData("double..dot.com")]
[InlineData("-starts-with-hyphen.com")]
[InlineData(" acme.com ")]
public void Validate_WithInvalidDomainFormat_ReturnsError(string invalidDomain)
{
var model = new CreateOrganizationInviteLinkRequestModel
{
AllowedDomains = new[] { invalidDomain },
EncryptedInviteKey = _validEncryptedString,
};
var results = Validate(model);
Assert.Single(results);
Assert.Contains(results, r => r.MemberNames.Contains(nameof(model.AllowedDomains)));
}
[Fact]
public void Validate_WithEmptyAllowedDomains_ReturnsError()
{
var model = new CreateOrganizationInviteLinkRequestModel
{
AllowedDomains = Array.Empty<string>(),
EncryptedInviteKey = _validEncryptedString,
};
var results = Validate(model);
Assert.Single(results);
Assert.Contains(results, r => r.MemberNames.Contains(nameof(model.AllowedDomains)));
}
[Fact]
public void Validate_WithMixedValidAndInvalidDomains_ReturnsError()
{
var model = new CreateOrganizationInviteLinkRequestModel
{
AllowedDomains = new[] { "acme.com", "not a domain", "<script>" },
EncryptedInviteKey = _validEncryptedString,
};
var results = Validate(model);
var error = Assert.Single(results);
Assert.Contains("'not a domain'", error.ErrorMessage);
Assert.Contains("'<script>'", error.ErrorMessage);
}
private static List<ValidationResult> Validate(CreateOrganizationInviteLinkRequestModel model)
{
var results = new List<ValidationResult>();
Validator.TryValidateObject(model, new ValidationContext(model), results, true);
return results;
}
}