From d208bc82e532841908ebc06a08f717dede7dc2fc Mon Sep 17 00:00:00 2001 From: Shane Melton Date: Tue, 7 Mar 2023 13:29:19 -0800 Subject: [PATCH] [AC-1070] Add optional ForcePasswordResetReason to profile / state service --- src/Core/Abstractions/IStateService.cs | 2 ++ src/Core/Models/Domain/Account.cs | 2 ++ .../Models/Domain/ForcePasswordResetReason.cs | 16 ++++++++++++++++ src/Core/Services/StateService.cs | 16 ++++++++++++++++ 4 files changed, 36 insertions(+) create mode 100644 src/Core/Models/Domain/ForcePasswordResetReason.cs diff --git a/src/Core/Abstractions/IStateService.cs b/src/Core/Abstractions/IStateService.cs index 0dcc183f4..64225e0f8 100644 --- a/src/Core/Abstractions/IStateService.cs +++ b/src/Core/Abstractions/IStateService.cs @@ -134,6 +134,8 @@ namespace Bit.Core.Abstractions Task SetPushRegisteredTokenAsync(string value); Task GetUsesKeyConnectorAsync(string userId = null); Task SetUsesKeyConnectorAsync(bool? value, string userId = null); + Task GetForcePasswordResetReasonAsync(string userId = null); + Task SetForcePasswordResetReasonAsync(ForcePasswordResetReason? value, string userId = null); Task> GetOrganizationsAsync(string userId = null); Task SetOrganizationsAsync(Dictionary organizations, string userId = null); Task GetPasswordGenerationOptionsAsync(string userId = null); diff --git a/src/Core/Models/Domain/Account.cs b/src/Core/Models/Domain/Account.cs index c9014ec9e..6267d5815 100644 --- a/src/Core/Models/Domain/Account.cs +++ b/src/Core/Models/Domain/Account.cs @@ -52,6 +52,7 @@ namespace Bit.Core.Models.Domain EmailVerified = copy.EmailVerified; HasPremiumPersonally = copy.HasPremiumPersonally; AvatarColor = copy.AvatarColor; + ForcePasswordResetReason = copy.ForcePasswordResetReason; } public string UserId; @@ -66,6 +67,7 @@ namespace Bit.Core.Models.Domain public int? KdfParallelism; public bool? EmailVerified; public bool? HasPremiumPersonally; + public ForcePasswordResetReason? ForcePasswordResetReason; } public class AccountTokens diff --git a/src/Core/Models/Domain/ForcePasswordResetReason.cs b/src/Core/Models/Domain/ForcePasswordResetReason.cs new file mode 100644 index 000000000..36883ed60 --- /dev/null +++ b/src/Core/Models/Domain/ForcePasswordResetReason.cs @@ -0,0 +1,16 @@ +namespace Bit.Core.Models.Domain +{ + public enum ForcePasswordResetReason + { + /// + /// Occurs when an organization admin forces a user to reset their password. + /// + AdminForcePasswordReset, + + /// + /// Occurs when a user logs in with a master password that does not meet an organization's master password + /// policy that is enforced on login. + /// + WeakMasterPasswordOnLogin + } +} diff --git a/src/Core/Services/StateService.cs b/src/Core/Services/StateService.cs index 598891929..6c950d397 100644 --- a/src/Core/Services/StateService.cs +++ b/src/Core/Services/StateService.cs @@ -1040,6 +1040,22 @@ namespace Bit.Core.Services await SetValueAsync(Constants.UsesKeyConnectorKey(reconciledOptions.UserId), value, reconciledOptions); } + public async Task GetForcePasswordResetReasonAsync(string userId = null) + { + var reconcileOptions = ReconcileOptions(new StorageOptions { UserId = userId }, + await GetDefaultStorageOptionsAsync()); + return (await GetAccountAsync(reconcileOptions))?.Profile?.ForcePasswordResetReason; + } + + public async Task SetForcePasswordResetReasonAsync(ForcePasswordResetReason? value, string userId = null) + { + var reconcileOptions = ReconcileOptions(new StorageOptions { UserId = userId }, + await GetDefaultStorageOptionsAsync()); + var account = await GetAccountAsync(reconcileOptions); + account.Profile.ForcePasswordResetReason = value; + await SaveAccountAsync(account, reconcileOptions); + } + public async Task> GetOrganizationsAsync(string userId = null) { var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },