mirror of
https://github.com/bitwarden/server
synced 2025-12-06 00:03:34 +00:00
feat(marketing-initiated-premium): (Auth) [PM-27540] Add optional Marketing Property to RegisterSendVerificationEmailRequestModel (#6598)
Adds an optional `FromMarketing` property to the RegisterSendVerificationEmailRequestModel.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
|
||||
namespace Bit.Core.Auth.Attributes;
|
||||
|
||||
public class MarketingInitiativeValidationAttribute : ValidationAttribute
|
||||
{
|
||||
private static readonly string[] _acceptedValues = [MarketingInitiativeConstants.Premium];
|
||||
|
||||
public MarketingInitiativeValidationAttribute()
|
||||
{
|
||||
ErrorMessage = $"Marketing initiative type must be one of: {string.Join(", ", _acceptedValues)}";
|
||||
}
|
||||
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value is not string str)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _acceptedValues.Contains(str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
|
||||
public static class MarketingInitiativeConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the user began the registration process on a marketing page designed
|
||||
/// to streamline users who intend to setup a premium subscription after registration.
|
||||
/// </summary>
|
||||
public const string Premium = "premium";
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#nullable enable
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Auth.Attributes;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
@@ -11,4 +12,6 @@ public class RegisterSendVerificationEmailRequestModel
|
||||
[StringLength(256)]
|
||||
public required string Email { get; set; }
|
||||
public bool ReceiveMarketingEmails { get; set; }
|
||||
[MarketingInitiativeValidation]
|
||||
public string? FromMarketing { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using Bit.Core.Auth.Attributes;
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.Auth.Attributes;
|
||||
|
||||
public class MarketingInitiativeValidationAttributeTests
|
||||
{
|
||||
[Fact]
|
||||
public void IsValid_NullValue_ReturnsTrue()
|
||||
{
|
||||
var sut = new MarketingInitiativeValidationAttribute();
|
||||
|
||||
var actual = sut.IsValid(null);
|
||||
|
||||
Assert.True(actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(MarketingInitiativeConstants.Premium)]
|
||||
public void IsValid_AcceptedValue_ReturnsTrue(string value)
|
||||
{
|
||||
var sut = new MarketingInitiativeValidationAttribute();
|
||||
|
||||
var actual = sut.IsValid(value);
|
||||
|
||||
Assert.True(actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("invalid")]
|
||||
[InlineData("")]
|
||||
[InlineData("Premium")] // case sensitive - capitalized
|
||||
[InlineData("PREMIUM")] // case sensitive - uppercase
|
||||
[InlineData("premium ")] // trailing space
|
||||
[InlineData(" premium")] // leading space
|
||||
public void IsValid_InvalidStringValue_ReturnsFalse(string value)
|
||||
{
|
||||
var sut = new MarketingInitiativeValidationAttribute();
|
||||
|
||||
var actual = sut.IsValid(value);
|
||||
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(123)] // integer
|
||||
[InlineData(true)] // boolean
|
||||
[InlineData(45.67)] // double
|
||||
public void IsValid_NonStringValue_ReturnsFalse(object value)
|
||||
{
|
||||
var sut = new MarketingInitiativeValidationAttribute();
|
||||
|
||||
var actual = sut.IsValid(value);
|
||||
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ErrorMessage_ContainsAcceptedValues()
|
||||
{
|
||||
var sut = new MarketingInitiativeValidationAttribute();
|
||||
|
||||
var errorMessage = sut.ErrorMessage;
|
||||
|
||||
Assert.NotNull(errorMessage);
|
||||
Assert.Contains("premium", errorMessage);
|
||||
Assert.Contains("Marketing initiative type must be one of:", errorMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.Auth.Models.Api.Request.Accounts;
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot tests to ensure the string constants in <see cref="MarketingInitiativeConstants"/> do not change unintentionally.
|
||||
/// If you intentionally change any of these values, please update the tests to reflect the new expected values.
|
||||
/// </summary>
|
||||
public class MarketingInitiativeConstantsSnapshotTests
|
||||
{
|
||||
[Fact]
|
||||
public void MarketingInitiativeConstants_HaveCorrectValues()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal("premium", MarketingInitiativeConstants.Premium);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user