1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-21 19:28:46 -05:00

feat(change-password-component): Change Password Update [18720] - Added new endpoint to just send back aggregated master password policies.

This commit is contained in:
Patrick Pimentel 2025-06-10 16:42:26 -06:00
parent 7ed190006b
commit 0d02ba1beb
No known key found for this signature in database
GPG Key ID: 4B27FC74C6422186
5 changed files with 25 additions and 9 deletions

View File

@ -2,15 +2,18 @@
using Bit.Api.AdminConsole.Models.Response.Helpers; using Bit.Api.AdminConsole.Models.Response.Helpers;
using Bit.Api.AdminConsole.Models.Response.Organizations; using Bit.Api.AdminConsole.Models.Response.Organizations;
using Bit.Api.Models.Response; using Bit.Api.Models.Response;
using Bit.Core;
using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Enums; using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces; using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
using Bit.Core.AdminConsole.OrganizationFeatures.Policies; using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Repositories;
using Bit.Core.AdminConsole.Services;
using Bit.Core.Auth.Models.Business.Tokenables; using Bit.Core.Auth.Models.Business.Tokenables;
using Bit.Core.Context; using Bit.Core.Context;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Models.Api.Response;
using Bit.Core.Repositories; using Bit.Core.Repositories;
using Bit.Core.Services; using Bit.Core.Services;
using Bit.Core.Settings; using Bit.Core.Settings;
@ -36,6 +39,7 @@ public class PoliciesController : Controller
private readonly IDataProtectorTokenFactory<OrgUserInviteTokenable> _orgUserInviteTokenDataFactory; private readonly IDataProtectorTokenFactory<OrgUserInviteTokenable> _orgUserInviteTokenDataFactory;
private readonly IPolicyRepository _policyRepository; private readonly IPolicyRepository _policyRepository;
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly IPolicyService _policyService;
private readonly ISavePolicyCommand _savePolicyCommand; private readonly ISavePolicyCommand _savePolicyCommand;
@ -49,7 +53,8 @@ public class PoliciesController : Controller
IFeatureService featureService, IFeatureService featureService,
IOrganizationHasVerifiedDomainsQuery organizationHasVerifiedDomainsQuery, IOrganizationHasVerifiedDomainsQuery organizationHasVerifiedDomainsQuery,
IOrganizationRepository organizationRepository, IOrganizationRepository organizationRepository,
ISavePolicyCommand savePolicyCommand) ISavePolicyCommand savePolicyCommand,
IPolicyService policyService)
{ {
_policyRepository = policyRepository; _policyRepository = policyRepository;
_organizationUserRepository = organizationUserRepository; _organizationUserRepository = organizationUserRepository;
@ -63,6 +68,7 @@ public class PoliciesController : Controller
_featureService = featureService; _featureService = featureService;
_organizationHasVerifiedDomainsQuery = organizationHasVerifiedDomainsQuery; _organizationHasVerifiedDomainsQuery = organizationHasVerifiedDomainsQuery;
_savePolicyCommand = savePolicyCommand; _savePolicyCommand = savePolicyCommand;
_policyService = policyService;
} }
[HttpGet("{type}")] [HttpGet("{type}")]
@ -192,6 +198,15 @@ public class PoliciesController : Controller
return new PolicyResponseModel(policy); return new PolicyResponseModel(policy);
} }
[HttpGet("~/policies/master-password")]
[RequireFeature(FeatureFlagKeys.ChangeExistingPasswordRefactor)]
public async Task<MasterPasswordPolicyResponseModel> GetMasterPasswordPolicy()
{
var userId = _userService.GetProperUserId(User).Value;
return new MasterPasswordPolicyResponseModel(await _policyService.GetMasterPasswordPolicyForUserAsync(new Guid(userId.ToString()), true));
}
[HttpPut("{type}")] [HttpPut("{type}")]
public async Task<PolicyResponseModel> Put(Guid orgId, PolicyType type, [FromBody] PolicyRequestModel model) public async Task<PolicyResponseModel> Put(Guid orgId, PolicyType type, [FromBody] PolicyRequestModel model)
{ {

View File

@ -278,7 +278,7 @@ public class AccountsController : Controller
if (await _userService.CheckPasswordAsync(user, model.MasterPasswordHash)) if (await _userService.CheckPasswordAsync(user, model.MasterPasswordHash))
{ {
var policyData = await _policyService.GetMasterPasswordPolicyForUserAsync(user); var policyData = await _policyService.GetMasterPasswordPolicyForUserAsync(user.Id);
return new MasterPasswordPolicyResponseModel(policyData); return new MasterPasswordPolicyResponseModel(policyData);
} }

View File

@ -1,6 +1,5 @@
using Bit.Core.AdminConsole.Enums; using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies; using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
using Bit.Core.Entities;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Models.Data.Organizations.OrganizationUsers;
@ -11,7 +10,7 @@ public interface IPolicyService
/// <summary> /// <summary>
/// Get the combined master password policy options for the specified user. /// Get the combined master password policy options for the specified user.
/// </summary> /// </summary>
Task<MasterPasswordPolicyData> GetMasterPasswordPolicyForUserAsync(User user, bool getConfirmedOrAccepted = false); Task<MasterPasswordPolicyData> GetMasterPasswordPolicyForUserAsync(Guid userId, bool getConfirmedOrAccepted = false);
Task<ICollection<OrganizationUserPolicyDetails>> GetPoliciesApplicableToUserAsync(Guid userId, PolicyType policyType, OrganizationUserStatusType minStatus = OrganizationUserStatusType.Accepted); Task<ICollection<OrganizationUserPolicyDetails>> GetPoliciesApplicableToUserAsync(Guid userId, PolicyType policyType, OrganizationUserStatusType minStatus = OrganizationUserStatusType.Accepted);
Task<bool> AnyPoliciesApplicableToUserAsync(Guid userId, PolicyType policyType, OrganizationUserStatusType minStatus = OrganizationUserStatusType.Accepted); Task<bool> AnyPoliciesApplicableToUserAsync(Guid userId, PolicyType policyType, OrganizationUserStatusType minStatus = OrganizationUserStatusType.Accepted);
} }

View File

@ -1,7 +1,6 @@
using Bit.Core.AdminConsole.Enums; using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies; using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Entities;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.Repositories; using Bit.Core.Repositories;
@ -29,13 +28,16 @@ public class PolicyService : IPolicyService
_globalSettings = globalSettings; _globalSettings = globalSettings;
} }
public async Task<MasterPasswordPolicyData> GetMasterPasswordPolicyForUserAsync(User user, bool getConfirmedOrAccepted = false) // Reuse this in the policies controller
public async Task<MasterPasswordPolicyData> GetMasterPasswordPolicyForUserAsync(
Guid userId,
bool getConfirmedOrAccepted = false)
{ {
var policies = getConfirmedOrAccepted ? var policies = getConfirmedOrAccepted ?
(await _policyRepository.GetManyAcceptedOrConfirmedByUserIdAsync(user.Id)) (await _policyRepository.GetManyAcceptedOrConfirmedByUserIdAsync(userId))
.Where(p => p.Type == PolicyType.MasterPassword && p.Enabled) .Where(p => p.Type == PolicyType.MasterPassword && p.Enabled)
.ToList() .ToList()
: (await _policyRepository.GetManyByUserIdAsync(user.Id)) : (await _policyRepository.GetManyByUserIdAsync(userId))
.Where(p => p.Type == PolicyType.MasterPassword && p.Enabled) .Where(p => p.Type == PolicyType.MasterPassword && p.Enabled)
.ToList(); .ToList();

View File

@ -369,7 +369,7 @@ public abstract class BaseRequestValidator<T> where T : class
return null; return null;
} }
return new MasterPasswordPolicyResponseModel(await PolicyService.GetMasterPasswordPolicyForUserAsync(user, true)); return new MasterPasswordPolicyResponseModel(await PolicyService.GetMasterPasswordPolicyForUserAsync(user.Id, true));
} }
/// <summary> /// <summary>