mirror of
https://github.com/bitwarden/server.git
synced 2025-02-16 01:51:21 +01:00
[EC-243] Grant premium status when member accepts org invite (#2043)
This commit is contained in:
parent
b2a0aa2860
commit
3360d40592
@ -441,7 +441,7 @@ namespace Bit.Api.Controllers
|
||||
await _providerUserRepository.GetManyOrganizationDetailsByUserAsync(user.Id,
|
||||
ProviderUserStatusType.Confirmed);
|
||||
var response = new ProfileResponseModel(user, organizationUserDetails, providerUserDetails,
|
||||
providerUserOrganizationDetails, await _userService.TwoFactorIsEnabledAsync(user));
|
||||
providerUserOrganizationDetails, await _userService.TwoFactorIsEnabledAsync(user), await _userService.HasPremiumFromOrganization(user));
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -466,7 +466,7 @@ namespace Bit.Api.Controllers
|
||||
}
|
||||
|
||||
await _userService.SaveUserAsync(model.ToUser(user));
|
||||
var response = new ProfileResponseModel(user, null, null, null, await _userService.TwoFactorIsEnabledAsync(user));
|
||||
var response = new ProfileResponseModel(user, null, null, null, await _userService.TwoFactorIsEnabledAsync(user), await _userService.HasPremiumFromOrganization(user));
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -617,7 +617,7 @@ namespace Bit.Api.Controllers
|
||||
BillingAddressCountry = model.Country,
|
||||
BillingAddressPostalCode = model.PostalCode,
|
||||
});
|
||||
var profile = new ProfileResponseModel(user, null, null, null, await _userService.TwoFactorIsEnabledAsync(user));
|
||||
var profile = new ProfileResponseModel(user, null, null, null, await _userService.TwoFactorIsEnabledAsync(user), await _userService.HasPremiumFromOrganization(user));
|
||||
return new PaymentResponseModel
|
||||
{
|
||||
UserProfile = profile,
|
||||
|
@ -88,7 +88,8 @@ namespace Bit.Api.Controllers
|
||||
}
|
||||
|
||||
var userTwoFactorEnabled = await _userService.TwoFactorIsEnabledAsync(user);
|
||||
var response = new SyncResponseModel(_globalSettings, user, userTwoFactorEnabled, organizationUserDetails,
|
||||
var userHasPremiumFromOrganization = await _userService.HasPremiumFromOrganization(user);
|
||||
var response = new SyncResponseModel(_globalSettings, user, userTwoFactorEnabled, userHasPremiumFromOrganization, organizationUserDetails,
|
||||
providerUserDetails, providerUserOrganizationDetails, folders, collections, ciphers,
|
||||
collectionCiphersGroupDict, excludeDomains, policies, sends);
|
||||
return response;
|
||||
|
@ -15,7 +15,8 @@ namespace Bit.Api.Models.Response
|
||||
IEnumerable<OrganizationUserOrganizationDetails> organizationsUserDetails,
|
||||
IEnumerable<ProviderUserProviderDetails> providerUserDetails,
|
||||
IEnumerable<ProviderUserOrganizationDetails> providerUserOrganizationDetails,
|
||||
bool twoFactorEnabled) : base("profile")
|
||||
bool twoFactorEnabled,
|
||||
bool premiumFromOrganization) : base("profile")
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
@ -27,6 +28,7 @@ namespace Bit.Api.Models.Response
|
||||
Email = user.Email;
|
||||
EmailVerified = user.EmailVerified;
|
||||
Premium = user.Premium;
|
||||
PremiumFromOrganization = premiumFromOrganization;
|
||||
MasterPasswordHint = string.IsNullOrWhiteSpace(user.MasterPasswordHint) ? null : user.MasterPasswordHint;
|
||||
Culture = user.Culture;
|
||||
TwoFactorEnabled = twoFactorEnabled;
|
||||
@ -46,6 +48,7 @@ namespace Bit.Api.Models.Response
|
||||
public string Email { get; set; }
|
||||
public bool EmailVerified { get; set; }
|
||||
public bool Premium { get; set; }
|
||||
public bool PremiumFromOrganization { get; set; }
|
||||
public string MasterPasswordHint { get; set; }
|
||||
public string Culture { get; set; }
|
||||
public bool TwoFactorEnabled { get; set; }
|
||||
|
@ -16,6 +16,7 @@ namespace Bit.Api.Models.Response
|
||||
GlobalSettings globalSettings,
|
||||
User user,
|
||||
bool userTwoFactorEnabled,
|
||||
bool userHasPremiumFromOrganization,
|
||||
IEnumerable<OrganizationUserOrganizationDetails> organizationUserDetails,
|
||||
IEnumerable<ProviderUserProviderDetails> providerUserDetails,
|
||||
IEnumerable<ProviderUserOrganizationDetails> providerUserOrganizationDetails,
|
||||
@ -29,7 +30,7 @@ namespace Bit.Api.Models.Response
|
||||
: base("sync")
|
||||
{
|
||||
Profile = new ProfileResponseModel(user, organizationUserDetails, providerUserDetails,
|
||||
providerUserOrganizationDetails, userTwoFactorEnabled);
|
||||
providerUserOrganizationDetails, userTwoFactorEnabled, userHasPremiumFromOrganization);
|
||||
Folders = folders.Select(f => new FolderResponseModel(f));
|
||||
Ciphers = ciphers.Select(c => new CipherDetailsResponseModel(c, globalSettings, collectionCiphersDict));
|
||||
Collections = collections?.Select(
|
||||
|
@ -70,6 +70,7 @@ namespace Bit.Core.Services
|
||||
int? version = null);
|
||||
Task<bool> CheckPasswordAsync(User user, string password);
|
||||
Task<bool> CanAccessPremium(ITwoFactorProvidersUser user);
|
||||
Task<bool> HasPremiumFromOrganization(ITwoFactorProvidersUser user);
|
||||
Task<bool> TwoFactorIsEnabledAsync(ITwoFactorProvidersUser user);
|
||||
Task<bool> TwoFactorProviderIsEnabledAsync(TwoFactorProviderType provider, ITwoFactorProvidersUser user);
|
||||
Task<string> GenerateSignInTokenAsync(User user, string purpose);
|
||||
|
@ -1263,18 +1263,32 @@ namespace Bit.Core.Services
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (user.GetPremium())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var orgs = await _currentContext.OrganizationMembershipAsync(_organizationUserRepository, userId.Value);
|
||||
if (!orgs.Any())
|
||||
|
||||
return user.GetPremium() || await this.HasPremiumFromOrganization(user);
|
||||
}
|
||||
|
||||
public async Task<bool> HasPremiumFromOrganization(ITwoFactorProvidersUser user)
|
||||
{
|
||||
var userId = user.GetUserId();
|
||||
if (!userId.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// orgUsers in the Invited status are not associated with a userId yet, so this will get
|
||||
// orgUsers in Accepted and Confirmed states only
|
||||
var orgUsers = await _organizationUserRepository.GetManyByUserAsync(userId.Value);
|
||||
|
||||
if (!orgUsers.Any())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
|
||||
return orgs.Any(o => orgAbilities.ContainsKey(o.Id) &&
|
||||
orgAbilities[o.Id].UsersGetPremium && orgAbilities[o.Id].Enabled);
|
||||
return orgUsers.Any(ou =>
|
||||
orgAbilities.TryGetValue(ou.OrganizationId, out var orgAbility) &&
|
||||
orgAbility.UsersGetPremium &&
|
||||
orgAbility.Enabled);
|
||||
}
|
||||
|
||||
public async Task<bool> TwoFactorIsEnabledAsync(ITwoFactorProvidersUser user)
|
||||
|
@ -7,6 +7,7 @@ using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Data.Organizations;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
@ -350,5 +351,43 @@ namespace Bit.Core.Test.Services
|
||||
|
||||
Assert.False(sutProvider.Sut.CanEditDeviceVerificationSettings(user));
|
||||
}
|
||||
|
||||
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
|
||||
public async void HasPremiumFromOrganization_Returns_False_If_No_Orgs(SutProvider<UserService> sutProvider, User user)
|
||||
{
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyByUserAsync(user.Id).Returns(new List<OrganizationUser>());
|
||||
Assert.False(await sutProvider.Sut.HasPremiumFromOrganization(user));
|
||||
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineCustomAutoData(new[] { typeof(SutProviderCustomization) }, false, true)]
|
||||
[InlineCustomAutoData(new[] { typeof(SutProviderCustomization) }, true, false)]
|
||||
public async void HasPremiumFromOrganization_Returns_False_If_Org_Not_Eligible(bool orgEnabled, bool orgUsersGetPremium, SutProvider<UserService> sutProvider, User user, OrganizationUser orgUser, Organization organization)
|
||||
{
|
||||
orgUser.OrganizationId = organization.Id;
|
||||
organization.Enabled = orgEnabled;
|
||||
organization.UsersGetPremium = orgUsersGetPremium;
|
||||
var orgAbilities = new Dictionary<Guid, OrganizationAbility>() { { organization.Id, new OrganizationAbility(organization) } };
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyByUserAsync(user.Id).Returns(new List<OrganizationUser>() { orgUser });
|
||||
sutProvider.GetDependency<IApplicationCacheService>().GetOrganizationAbilitiesAsync().Returns(orgAbilities);
|
||||
|
||||
Assert.False(await sutProvider.Sut.HasPremiumFromOrganization(user));
|
||||
}
|
||||
|
||||
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
|
||||
public async void HasPremiumFromOrganization_Returns_True_If_Org_Eligible(SutProvider<UserService> sutProvider, User user, OrganizationUser orgUser, Organization organization)
|
||||
{
|
||||
orgUser.OrganizationId = organization.Id;
|
||||
organization.Enabled = true;
|
||||
organization.UsersGetPremium = true;
|
||||
var orgAbilities = new Dictionary<Guid, OrganizationAbility>() { { organization.Id, new OrganizationAbility(organization) } };
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyByUserAsync(user.Id).Returns(new List<OrganizationUser>() { orgUser });
|
||||
sutProvider.GetDependency<IApplicationCacheService>().GetOrganizationAbilitiesAsync().Returns(orgAbilities);
|
||||
|
||||
Assert.True(await sutProvider.Sut.HasPremiumFromOrganization(user));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user