Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auth/PM-5092 - Registration with Email verification - Send Email Verification Endpoint #4173

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7b626f9
PM-5092 - Add new EnableEmailVerification global setting.
JaredSnider-Bitwarden Jun 4, 2024
5c227ed
PM-5092 - WIP - AccountsController.cs - create stub for new PostRโ€ฆ
JaredSnider-Bitwarden Jun 4, 2024
904729a
PM-5092 - RegisterSendEmailVerificationRequestModel
JaredSnider-Bitwarden Jun 4, 2024
8455827
PM-5092 - Create EmailVerificationTokenable.cs and get started on tesโ€ฆ
JaredSnider-Bitwarden Jun 4, 2024
40f0f61
PM-5092 - EmailVerificationTokenable.cs finished + tests working.
JaredSnider-Bitwarden Jun 5, 2024
c7e2e65
PM-5092 - Add token data factory for new EmailVerificationTokenable fโ€ฆ
JaredSnider-Bitwarden Jun 6, 2024
55e101f
PM-5092 - EmailVerificationTokenable.cs - set expiration to match exiโ€ฆ
JaredSnider-Bitwarden Jun 6, 2024
b0ec45b
PM-5092 - Get SendVerificationEmailForRegistrationCommand command mosโ€ฆ
JaredSnider-Bitwarden Jun 6, 2024
db78901
PM-5092 - Rename tokenable to be more clear and differentiate it fromโ€ฆ
JaredSnider-Bitwarden Jun 6, 2024
1b04b81
PM-5092 - Add new registration verify email method on mail service.
JaredSnider-Bitwarden Jun 6, 2024
2a4493a
PM-5092 - Refactor SendVerificationEmailForRegistrationCommand and adโ€ฆ
JaredSnider-Bitwarden Jun 6, 2024
790fb0e
PM-5092 - NoopMailService.cs needs to implement all interface methods.
JaredSnider-Bitwarden Jun 6, 2024
2bc000c
PM-5092 - AccountsController.cs - get PostRegisterSendEmailVerificatiโ€ฆ
JaredSnider-Bitwarden Jun 6, 2024
5037692
PM-5092 - AccountsControllerTests.cs - Add some unit tests - WIP
JaredSnider-Bitwarden Jun 6, 2024
f1ab36f
PM-5092 - SendVerificationEmailForRegistrationCommandTests
JaredSnider-Bitwarden Jun 7, 2024
6bcdc44
PM-5092 - Add integration tests for new acct controller method
JaredSnider-Bitwarden Jun 7, 2024
fa95144
PM-5092 - Cleanup unit tests
JaredSnider-Bitwarden Jun 7, 2024
dbc2b9f
PM-5092 - AccountsController.cs - PostRegisterSendEmailVerification -โ€ฆ
JaredSnider-Bitwarden Jun 7, 2024
ad0014e
PM-5092 - Rename to read better - send verification email > send emaiโ€ฆ
JaredSnider-Bitwarden Jun 7, 2024
eafc065
PM-5092 - Revert primary constructor approach so DI works.
JaredSnider-Bitwarden Jun 7, 2024
d6eb0db
PM-5092 - (1) Cleanup new but now not needed global setting (2) Add cโ€ฆ
JaredSnider-Bitwarden Jun 7, 2024
ecccb42
PM-5092 - Fix email text
JaredSnider-Bitwarden Jun 7, 2024
bd370cc
Merge branch 'main' into auth/pm-5092/email-verification-send-email-eโ€ฆ
JaredSnider-Bitwarden Jun 10, 2024
5750d45
PM-5092 - (1) Modify ReferenceEvent.cs to allow nullable values for tโ€ฆ
JaredSnider-Bitwarden Jun 12, 2024
69c50aa
PM-5092 - RegistrationEmailVerificationTokenable - update prefix, purโ€ฆ
JaredSnider-Bitwarden Jun 12, 2024
8fdf1f4
PM-5092 - Per PR feedback, cleanup used dict.
JaredSnider-Bitwarden Jun 13, 2024
aacf554
PM-5092 - formatting pass (manual + dotnet format)
JaredSnider-Bitwarden Jun 13, 2024
49aecb5
PM-5092 - Per PR feedback, log reference event after core business loโ€ฆ
JaredSnider-Bitwarden Jun 13, 2024
fa5fea7
PM-5092 - Per PR feedback, add validation + added nullable flag to naโ€ฆ
JaredSnider-Bitwarden Jun 13, 2024
9428401
PM-5092 - Per PR feedback, add constructor validation for required toโ€ฆ
JaredSnider-Bitwarden Jun 13, 2024
3c32aa6
Merge branch 'main' into auth/pm-5092/email-verification-send-email-eโ€ฆ
JaredSnider-Bitwarden Jun 14, 2024
93f7535
PM-5092 - RegisterVerifyEmail url now contains email as that is requiโ€ฆ
JaredSnider-Bitwarden Jun 15, 2024
21968c3
Merge branch 'main' into auth/pm-5092/email-verification-send-email-eโ€ฆ
JaredSnider-Bitwarden Jun 15, 2024
b87b602
Merge branch 'auth/pm-5092/email-verification-send-email-endpoint' ofโ€ฆ
JaredSnider-Bitwarden Jun 15, 2024
82147b0
PM-5092 - Add fromEmail flag + some docs
JaredSnider-Bitwarden Jun 15, 2024
d26118f
PM-5092 - ReferenceEvent.cs - Per PR feedback, make SignupInitiationPโ€ฆ
JaredSnider-Bitwarden Jun 18, 2024
f2be9e6
PM-5092 - ReferenceEvent.cs - remove nullability per PR feedback
JaredSnider-Bitwarden Jun 18, 2024
1e38cf9
PM-5092 - Per PR feedback, use default constructor and manually creatโ€ฆ
JaredSnider-Bitwarden Jun 18, 2024
a9d0b99
PM-5092 - Per PR feedback, add more docs!
JaredSnider-Bitwarden Jun 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
๏ปฟ#nullable enable
using System.ComponentModel.DataAnnotations;
using Bit.Core.Utilities;

namespace Bit.Core.Auth.Models.Api.Request.Accounts;

public class RegisterSendVerificationEmailRequestModel
{
[StringLength(50)] public string? Name { get; set; }
[Required]
[StrictEmailAddress]
[StringLength(256)]
public string Email { get; set; }

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Setup, ./util)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (MsSqlMigratorUtility, ./util, true)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build MSSQL migrator utility (linux-x64)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build MSSQL migrator utility (win-x64)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Billing, ./src)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Identity, ./src)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Icons, ./src)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Api, ./src)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build MSSQL migrator utility (osx-x64)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Notifications, ./src)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Scim, ./bitwarden_license/src, true)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Sso, ./bitwarden_license/src, true)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Events, ./src)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (EventsProcessor, ./src)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Build artifacts (Admin, ./src, true)

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Run tests

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 13 in src/Core/Auth/Models/Api/Request/Accounts/RegisterSendVerificationEmailRequestModel.cs

View workflow job for this annotation

GitHub Actions / Upload

Non-nullable property 'Email' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public bool ReceiveMarketingEmails { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
๏ปฟusing System.Text.Json.Serialization;
using Bit.Core.Tokens;

namespace Bit.Core.Auth.Models.Business.Tokenables;

// <summary>
// This token contains encrypted registration information for new users. The token is sent via email for verification as
// part of a link to complete the registration process.
// </summary>
public class RegistrationEmailVerificationTokenable : ExpiringTokenable
{
public static TimeSpan GetTokenLifetime() => TimeSpan.FromMinutes(15);

public const string ClearTextPrefix = "BwRegistrationEmailVerificationToken_";
public const string DataProtectorPurpose = "RegistrationEmailVerificationTokenDataProtector";
public const string TokenIdentifier = "RegistrationEmailVerificationToken";

public string Identifier { get; set; } = TokenIdentifier;

public string Name { get; set; }
public string Email { get; set; }
public bool ReceiveMarketingEmails { get; set; }

[JsonConstructor]
public RegistrationEmailVerificationTokenable()
{
ExpirationDate = DateTime.UtcNow.Add(GetTokenLifetime());
}

public RegistrationEmailVerificationTokenable(string email, string name = default, bool receiveMarketingEmails = default) : this()
{
if (string.IsNullOrEmpty(email))
{
throw new ArgumentNullException(nameof(email));
}

Email = email;
Name = name;
ReceiveMarketingEmails = receiveMarketingEmails;
}

public bool TokenIsValid(string email, string name = default, bool receiveMarketingEmails = default)
{
if (Email == default || email == default)
{
return false;

Check warning on line 46 in src/Core/Auth/Models/Business/Tokenables/RegistrationEmailVerificationTokenable.cs

View check run for this annotation

Codecov / codecov/patch

src/Core/Auth/Models/Business/Tokenables/RegistrationEmailVerificationTokenable.cs#L45-L46

Added lines #L45 - L46 were not covered by tests
}

// Note: string.Equals handles nulls without throwing an exception
return string.Equals(Name, name, StringComparison.InvariantCultureIgnoreCase) &&
Email.Equals(email, StringComparison.InvariantCultureIgnoreCase) &&
ReceiveMarketingEmails == receiveMarketingEmails;
}

// Validates deserialized
protected override bool TokenIsValid() =>
Identifier == TokenIdentifier
&& !string.IsNullOrWhiteSpace(Email);

}
18 changes: 18 additions & 0 deletions src/Core/Auth/Models/Mail/RegisterVerifyEmail.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
๏ปฟusing Bit.Core.Models.Mail;

namespace Bit.Core.Auth.Models.Mail;

public class RegisterVerifyEmail : BaseMailModel
{
// We must include email in the URL even though it is already in the token so that the
// client can use it to create the master key when they set their password.
// We also have to include the fromEmail flag so that the client knows the user
// is coming to the finish signup page from an email link and not directly from another route in the app.
public string Url => string.Format("{0}/finish-signup?token={1}&email={2}&fromEmail=true",
WebVaultUrl,
Token,
Email);

public string Token { get; set; }
public string Email { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
๏ปฟ#nullable enable
namespace Bit.Core.Auth.UserFeatures.Registration;

public interface ISendVerificationEmailForRegistrationCommand
{
public Task<string?> Run(string email, string? name, bool receiveMarketingEmails);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
๏ปฟ#nullable enable
using Bit.Core.Auth.Models.Business.Tokenables;
using Bit.Core.Exceptions;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Settings;
using Bit.Core.Tokens;

namespace Bit.Core.Auth.UserFeatures.Registration.Implementations;

/// <summary>
/// If email verification is enabled, this command will send a verification email to the user which will
/// contain a link to complete the registration process.
/// If email verification is disabled, this command will return a token that can be used to complete the registration process directly.
/// </summary>
public class SendVerificationEmailForRegistrationCommand : ISendVerificationEmailForRegistrationCommand
jlf0dev marked this conversation as resolved.
Show resolved Hide resolved
{

private readonly IUserRepository _userRepository;
private readonly GlobalSettings _globalSettings;
private readonly IMailService _mailService;
private readonly IDataProtectorTokenFactory<RegistrationEmailVerificationTokenable> _tokenDataFactory;

public SendVerificationEmailForRegistrationCommand(
IUserRepository userRepository,
GlobalSettings globalSettings,
IMailService mailService,
IDataProtectorTokenFactory<RegistrationEmailVerificationTokenable> tokenDataFactory)
{
_userRepository = userRepository;
_globalSettings = globalSettings;
_mailService = mailService;
_tokenDataFactory = tokenDataFactory;
}

public async Task<string?> Run(string email, string? name, bool receiveMarketingEmails)
{
if (string.IsNullOrWhiteSpace(email))
{
throw new ArgumentNullException(nameof(email));
}

// Check to see if the user already exists
var user = await _userRepository.GetByEmailAsync(email);
var userExists = user != null;

if (!_globalSettings.EnableEmailVerification)
{

if (userExists)
{
// Add delay to prevent timing attacks
// Note: sub 140 ms feels responsive to users so we are using 130 ms as it should be long enough
// to prevent timing attacks but not too long to be noticeable to the user.
await Task.Delay(130);
throw new BadRequestException($"Email {email} is already taken");
}

// if user doesn't exist, return a EmailVerificationTokenable in the response body.
var token = GenerateToken(email, name, receiveMarketingEmails);

return token;
}

if (!userExists)
{
// If the user doesn't exist, create a new EmailVerificationTokenable and send the user
// an email with a link to verify their email address
var token = GenerateToken(email, name, receiveMarketingEmails);
await _mailService.SendRegistrationVerificationEmailAsync(email, token);
}

// Add delay to prevent timing attacks
await Task.Delay(130);
// User exists but we will return a 200 regardless of whether the email was sent or not; so return null
return null;
}

private string GenerateToken(string email, string? name, bool receiveMarketingEmails)
{
var registrationEmailVerificationTokenable = new RegistrationEmailVerificationTokenable(email, name, receiveMarketingEmails);
return _tokenDataFactory.Protect(registrationEmailVerificationTokenable);
}
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
๏ปฟ

using Bit.Core.Auth.UserFeatures.Registration;
using Bit.Core.Auth.UserFeatures.Registration.Implementations;
using Bit.Core.Auth.UserFeatures.UserKey;
using Bit.Core.Auth.UserFeatures.UserKey.Implementations;
using Bit.Core.Auth.UserFeatures.UserMasterPassword;
Expand All @@ -18,6 +20,7 @@ public static void AddUserServices(this IServiceCollection services, IGlobalSett
{
services.AddScoped<IUserService, UserService>();
services.AddUserPasswordCommands();
services.AddUserRegistrationCommands();
services.AddWebAuthnLoginCommands();
}

Expand All @@ -31,6 +34,11 @@ private static void AddUserPasswordCommands(this IServiceCollection services)
services.AddScoped<ISetInitialMasterPasswordCommand, SetInitialMasterPasswordCommand>();
}

private static void AddUserRegistrationCommands(this IServiceCollection services)
{
services.AddScoped<ISendVerificationEmailForRegistrationCommand, SendVerificationEmailForRegistrationCommand>();
}

private static void AddWebAuthnLoginCommands(this IServiceCollection services)
{
services.AddScoped<IGetWebAuthnLoginCredentialCreateOptionsCommand, GetWebAuthnLoginCredentialCreateOptionsCommand>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
๏ปฟ{{#>FullHtmlLayout}}
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
<tr style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: left;" valign="top" align="center">
Verify your email address below to finish creating your account.
</td>
</tr>
<tr style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
<td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none; text-align: left;" valign="top" align="center">
If you did not request this email from Bitwarden, you can safely ignore it.
<br style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;" />
<br style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;" />
</td>
</tr>
<tr style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center">
<a href="{{{Url}}}" clicktracking=off target="_blank" style="color: #ffffff; text-decoration: none; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; background-color: #175DDC; border-color: #175DDC; border-style: solid; border-width: 10px 20px; margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
Verify email
</a>
<br style="margin: 0; box-sizing: border-box; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;" />
</td>
</tr>
</table>
{{/FullHtmlLayout}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
๏ปฟ{{#>BasicTextLayout}}
Verify your email address below to finish creating your account.

If you did not request this email from Bitwarden, you can safely ignore it.

{{{Url}}}

{{/BasicTextLayout}}
1 change: 1 addition & 0 deletions src/Core/Services/IMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public interface IMailService
{
Task SendWelcomeEmailAsync(User user);
Task SendVerifyEmailEmailAsync(string email, Guid userId, string token);
Task SendRegistrationVerificationEmailAsync(string email, string token);
Task SendVerifyDeleteEmailAsync(string email, Guid userId, string token);
Task SendChangeEmailAlreadyExistsEmailAsync(string fromEmail, string toEmail);
Task SendChangeEmailEmailAsync(string newEmailAddress, string token);
Expand Down
17 changes: 17 additions & 0 deletions src/Core/Services/Implementations/HandlebarsMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,23 @@ public async Task SendVerifyEmailEmailAsync(string email, Guid userId, string to
await _mailDeliveryService.SendEmailAsync(message);
}

public async Task SendRegistrationVerificationEmailAsync(string email, string token)
{
var message = CreateDefaultMessage("Verify Your Email", email);
var model = new RegisterVerifyEmail
{
Token = WebUtility.UrlEncode(token),
Email = email,
WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
SiteName = _globalSettings.SiteName
};
await AddMessageContentAsync(message, "Auth.RegistrationVerifyEmail", model);
message.MetaData.Add("SendGridBypassListManagement", true);
message.Category = "VerifyEmail";
await _mailDeliveryService.SendEmailAsync(message);
}


public async Task SendVerifyDeleteEmailAsync(string email, Guid userId, string token)
{
var message = CreateDefaultMessage("Delete Your Account", email);
Expand Down
5 changes: 5 additions & 0 deletions src/Core/Services/NoopImplementations/NoopMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
return Task.FromResult(0);
}

public Task SendRegistrationVerificationEmailAsync(string email, string hint)
{
return Task.FromResult(0);
}

Check warning on line 24 in src/Core/Services/NoopImplementations/NoopMailService.cs

View check run for this annotation

Codecov / codecov/patch

src/Core/Services/NoopImplementations/NoopMailService.cs#L22-L24

Added lines #L22 - L24 were not covered by tests

public Task SendChangeEmailEmailAsync(string newEmailAddress, string token)
{
return Task.FromResult(0);
Expand Down
3 changes: 3 additions & 0 deletions src/Core/Settings/GlobalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ public virtual string LicenseDirectory
public virtual ILaunchDarklySettings LaunchDarkly { get; set; } = new LaunchDarklySettings();
public virtual string DevelopmentDirectory { get; set; }

public virtual bool EnableEmailVerification { get; set; }

public string BuildExternalUri(string explicitValue, string name)
{
if (!string.IsNullOrWhiteSpace(explicitValue))
Expand Down Expand Up @@ -147,6 +149,7 @@ public BaseServiceUriSettings(GlobalSettings globalSettings)
public string CloudRegion { get; set; }
public string Vault { get; set; }
public string VaultWithHash => $"{Vault}/#";

public string VaultWithHashAndSecretManagerProduct => $"{Vault}/#/sm";

public string Api
Expand Down
2 changes: 2 additions & 0 deletions src/Core/Tools/Enums/ReferenceEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public enum ReferenceEventSource
User,
[EnumMember(Value = "provider")]
Provider,
[EnumMember(Value = "registrationStart")]
RegistrationStart,
JaredSnider-Bitwarden marked this conversation as resolved.
Show resolved Hide resolved
}
2 changes: 2 additions & 0 deletions src/Core/Tools/Enums/ReferenceEventType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace Bit.Core.Tools.Enums;

public enum ReferenceEventType
{
[EnumMember(Value = "signup-email-submit")]
SignupEmailSubmit,
[EnumMember(Value = "signup")]
Signup,
[EnumMember(Value = "upgrade-plan")]
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Tools/Models/Business/ReferenceEvent.cs
audreyality marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public ReferenceEvent(ReferenceEventType type, IReferenceable source, ICurrentCo
/// This value should only be populated when the <see cref="ReferenceEventType"/> is <see cref="ReferenceEventType.Signup"/>. Otherwise,
/// the value should be <see langword="null" />.
/// </value>
public string SignupInitiationPath { get; set; }
public string? SignupInitiationPath { get; set; }

/// <summary>
/// The upgrade applied to an account. The current plan is listed first,
Expand All @@ -253,5 +253,5 @@ public ReferenceEvent(ReferenceEventType type, IReferenceable source, ICurrentCo
/// <see langword="null"/> when the event was not originated by an application,
/// or when a downgrade occurred.
/// </value>
public string PlanUpgradePath { get; set; }
public string? PlanUpgradePath { get; set; }
}
Loading
Loading