From d7ddf2ecaf62b13f3b845a03ed6cd4aa0a87cfaf Mon Sep 17 00:00:00 2001 From: Patrick Pimentel Date: Thu, 11 Dec 2025 12:22:28 -0500 Subject: [PATCH] fix(register): [PM-27084] Account Register Uses New Data Types - Accounts controller no longer nullish allowed. --- .../Accounts/RegisterFinishRequestModel.cs | 10 +++- .../Controllers/AccountsController.cs | 51 +++++++++++++------ 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/Core/Auth/Models/Api/Request/Accounts/RegisterFinishRequestModel.cs b/src/Core/Auth/Models/Api/Request/Accounts/RegisterFinishRequestModel.cs index 7cc217cf84..304a90f50b 100644 --- a/src/Core/Auth/Models/Api/Request/Accounts/RegisterFinishRequestModel.cs +++ b/src/Core/Auth/Models/Api/Request/Accounts/RegisterFinishRequestModel.cs @@ -1,5 +1,4 @@ -#nullable enable -using Bit.Core.Entities; +using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.KeyManagement.Models.Data; using Bit.Core.Utilities; @@ -107,14 +106,21 @@ public class RegisterFinishRequestModel : IValidatableObject public IEnumerable Validate(ValidationContext validationContext) { + // PM-28143 - Remove line below var kdf = MasterPasswordUnlockData?.Kdf.KdfType ?? Kdf ?? throw new Exception($"{nameof(Kdf)} not found on RequestModel"); + + // PM-28143 - Remove line below var kdfIterations = MasterPasswordUnlockData?.Kdf.Iterations ?? KdfIterations ?? throw new Exception($"{nameof(KdfIterations)} not found on RequestModel"); + + // PM-28143 - Remove line below var kdfMemory = MasterPasswordUnlockData?.Kdf.Memory ?? KdfMemory; + + // PM-28143 - Remove line below var kdfParallelism = MasterPasswordUnlockData?.Kdf.Parallelism ?? KdfParallelism; diff --git a/src/Identity/Controllers/AccountsController.cs b/src/Identity/Controllers/AccountsController.cs index 57155b640a..805a98c543 100644 --- a/src/Identity/Controllers/AccountsController.cs +++ b/src/Identity/Controllers/AccountsController.cs @@ -1,8 +1,4 @@ -// FIXME: Update this file to be null safe and then delete the line below -#nullable disable - -using System.Diagnostics; -using System.Text; +using System.Text; using Bit.Core; using Bit.Core.Auth.Enums; using Bit.Core.Auth.Models.Api.Request.Accounts; @@ -42,7 +38,7 @@ public class AccountsController : Controller private readonly IFeatureService _featureService; private readonly IDataProtectorTokenFactory _registrationEmailVerificationTokenDataFactory; - private readonly byte[] _defaultKdfHmacKey = null; + private readonly byte[]? _defaultKdfHmacKey = null; private static readonly List _defaultKdfResults = [ // The first result (index 0) should always return the "normal" default. @@ -157,7 +153,7 @@ public class AccountsController : Controller } // Users will either have an emailed token or an email verification token - not both. - IdentityResult identityResult = null; + IdentityResult? identityResult = null; // PM-28143 - Just use the MasterPasswordAuthenticationData.MasterPasswordAuthenticationHash string masterPasswordHash = model.MasterPasswordAuthenticationData?.MasterPasswordAuthenticationHash @@ -166,41 +162,64 @@ public class AccountsController : Controller switch (model.GetTokenType()) { case RegisterFinishTokenType.EmailVerification: + if (string.IsNullOrEmpty(model.EmailVerificationToken)) + throw new BadRequestException("Email verification token absent when processing an email token."); + identityResult = await _registerUserCommand.RegisterUserViaEmailVerificationToken( user, masterPasswordHash, model.EmailVerificationToken); return ProcessRegistrationResult(identityResult, user); + case RegisterFinishTokenType.OrganizationInvite: + if (string.IsNullOrEmpty(model.OrgInviteToken)) + throw new BadRequestException("Organization invite token absent when processing an email token."); + identityResult = await _registerUserCommand.RegisterUserViaOrganizationInviteToken( user, masterPasswordHash, - model.OrgInviteToken, model.OrganizationUserId); - + model.OrgInviteToken, + model.OrganizationUserId); return ProcessRegistrationResult(identityResult, user); + case RegisterFinishTokenType.OrgSponsoredFreeFamilyPlan: + if (string.IsNullOrEmpty(model.OrgSponsoredFreeFamilyPlanToken)) + throw new BadRequestException("Organization sponsored free family plan token absent when processing an email token."); + identityResult = await _registerUserCommand.RegisterUserViaOrganizationSponsoredFreeFamilyPlanInviteToken( user, masterPasswordHash, model.OrgSponsoredFreeFamilyPlanToken); - return ProcessRegistrationResult(identityResult, user); + case RegisterFinishTokenType.EmergencyAccessInvite: - Debug.Assert(model.AcceptEmergencyAccessId.HasValue); + if (string.IsNullOrEmpty(model.AcceptEmergencyAccessInviteToken)) + throw new BadRequestException("Accept emergency access invite token absent when processing an email token."); + + if (model.AcceptEmergencyAccessId == null || model.AcceptEmergencyAccessId == Guid.Empty) + throw new BadRequestException("Accept emergency access id absent when processing an email token."); + identityResult = await _registerUserCommand.RegisterUserViaAcceptEmergencyAccessInviteToken( user, masterPasswordHash, - model.AcceptEmergencyAccessInviteToken, model.AcceptEmergencyAccessId.Value); - + model.AcceptEmergencyAccessInviteToken, + model.AcceptEmergencyAccessId.Value); return ProcessRegistrationResult(identityResult, user); + case RegisterFinishTokenType.ProviderInvite: - Debug.Assert(model.ProviderUserId.HasValue); + if (string.IsNullOrEmpty(model.ProviderInviteToken)) + throw new BadRequestException("Provider invite token absent when processing an email token."); + + if (model.ProviderUserId == null || model.ProviderUserId == Guid.Empty) + throw new BadRequestException("Provider user id absent when processing an email token."); + identityResult = await _registerUserCommand.RegisterUserViaProviderInviteToken( user, masterPasswordHash, - model.ProviderInviteToken, model.ProviderUserId.Value); - + model.ProviderInviteToken, + model.ProviderUserId.Value); return ProcessRegistrationResult(identityResult, user); + default: throw new BadRequestException("Invalid registration finish request"); }