mirror of
https://github.com/bitwarden/server.git
synced 2025-04-26 07:12:20 -05:00
Properly encapsulating this PR behind its feature flag
This commit is contained in:
parent
ed430639b5
commit
7c0b7a4bb6
@ -84,6 +84,19 @@ public class OrganizationSponsorshipsController : Controller
|
|||||||
throw new BadRequestException("Free Bitwarden Families sponsorship has been disabled by your organization administrator.");
|
throw new BadRequestException("Free Bitwarden Families sponsorship has been disabled by your organization administrator.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_featureService.IsEnabled(Bit.Core.FeatureFlagKeys.PM17772_AdminInitiatedSponsorships))
|
||||||
|
{
|
||||||
|
if (model.SponsoringUserId.HasValue)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(model.Notes))
|
||||||
|
{
|
||||||
|
model.Notes = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var targetUser = model.SponsoringUserId ?? _currentContext.UserId!.Value;
|
var targetUser = model.SponsoringUserId ?? _currentContext.UserId!.Value;
|
||||||
var sponsorship = await _createSponsorshipCommand.CreateSponsorshipAsync(
|
var sponsorship = await _createSponsorshipCommand.CreateSponsorshipAsync(
|
||||||
sponsoringOrg,
|
sponsoringOrg,
|
||||||
|
@ -3,6 +3,7 @@ using Bit.Core.Context;
|
|||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
|
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@ -20,6 +21,7 @@ public class SelfHostedOrganizationSponsorshipsController : Controller
|
|||||||
private readonly ICreateSponsorshipCommand _offerSponsorshipCommand;
|
private readonly ICreateSponsorshipCommand _offerSponsorshipCommand;
|
||||||
private readonly IRevokeSponsorshipCommand _revokeSponsorshipCommand;
|
private readonly IRevokeSponsorshipCommand _revokeSponsorshipCommand;
|
||||||
private readonly ICurrentContext _currentContext;
|
private readonly ICurrentContext _currentContext;
|
||||||
|
private readonly IFeatureService _featureService;
|
||||||
|
|
||||||
public SelfHostedOrganizationSponsorshipsController(
|
public SelfHostedOrganizationSponsorshipsController(
|
||||||
ICreateSponsorshipCommand offerSponsorshipCommand,
|
ICreateSponsorshipCommand offerSponsorshipCommand,
|
||||||
@ -27,7 +29,8 @@ public class SelfHostedOrganizationSponsorshipsController : Controller
|
|||||||
IOrganizationRepository organizationRepository,
|
IOrganizationRepository organizationRepository,
|
||||||
IOrganizationSponsorshipRepository organizationSponsorshipRepository,
|
IOrganizationSponsorshipRepository organizationSponsorshipRepository,
|
||||||
IOrganizationUserRepository organizationUserRepository,
|
IOrganizationUserRepository organizationUserRepository,
|
||||||
ICurrentContext currentContext
|
ICurrentContext currentContext,
|
||||||
|
IFeatureService featureService
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_offerSponsorshipCommand = offerSponsorshipCommand;
|
_offerSponsorshipCommand = offerSponsorshipCommand;
|
||||||
@ -36,14 +39,31 @@ public class SelfHostedOrganizationSponsorshipsController : Controller
|
|||||||
_organizationSponsorshipRepository = organizationSponsorshipRepository;
|
_organizationSponsorshipRepository = organizationSponsorshipRepository;
|
||||||
_organizationUserRepository = organizationUserRepository;
|
_organizationUserRepository = organizationUserRepository;
|
||||||
_currentContext = currentContext;
|
_currentContext = currentContext;
|
||||||
|
_featureService = featureService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("{sponsoringOrgId}/families-for-enterprise")]
|
[HttpPost("{sponsoringOrgId}/families-for-enterprise")]
|
||||||
public async Task CreateSponsorship(Guid sponsoringOrgId, [FromBody] OrganizationSponsorshipCreateRequestModel model)
|
public async Task CreateSponsorship(Guid sponsoringOrgId, [FromBody] OrganizationSponsorshipCreateRequestModel model)
|
||||||
{
|
{
|
||||||
|
// Check feature flag at controller level
|
||||||
|
if (!_featureService.IsEnabled(Bit.Core.FeatureFlagKeys.PM17772_AdminInitiatedSponsorships))
|
||||||
|
{
|
||||||
|
// If flag is off and someone tries to use admin-initiated sponsorships, return 404
|
||||||
|
if (model.SponsoringUserId.HasValue)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If flag is off and notes field has a value, ignore it
|
||||||
|
if (!string.IsNullOrWhiteSpace(model.Notes))
|
||||||
|
{
|
||||||
|
model.Notes = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await _offerSponsorshipCommand.CreateSponsorshipAsync(
|
await _offerSponsorshipCommand.CreateSponsorshipAsync(
|
||||||
await _organizationRepository.GetByIdAsync(sponsoringOrgId),
|
await _organizationRepository.GetByIdAsync(sponsoringOrgId),
|
||||||
await _organizationUserRepository.GetByOrganizationAsync(sponsoringOrgId, _currentContext.UserId ?? default),
|
await _organizationUserRepository.GetByOrganizationAsync(sponsoringOrgId, model.SponsoringUserId ?? _currentContext.UserId ?? default),
|
||||||
model.PlanSponsorshipType, model.SponsoredEmail, model.FriendlyName, model.Notes);
|
model.PlanSponsorshipType, model.SponsoredEmail, model.FriendlyName, model.Notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ namespace Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnte
|
|||||||
|
|
||||||
public class CreateSponsorshipCommand(
|
public class CreateSponsorshipCommand(
|
||||||
ICurrentContext currentContext,
|
ICurrentContext currentContext,
|
||||||
IFeatureService featureService,
|
|
||||||
IOrganizationSponsorshipRepository organizationSponsorshipRepository,
|
IOrganizationSponsorshipRepository organizationSponsorshipRepository,
|
||||||
IUserService userService) : ICreateSponsorshipCommand
|
IUserService userService) : ICreateSponsorshipCommand
|
||||||
{
|
{
|
||||||
@ -65,11 +64,6 @@ public class CreateSponsorshipCommand(
|
|||||||
var isAdminInitiated = false;
|
var isAdminInitiated = false;
|
||||||
if (currentContext.UserId != sponsoringMember.UserId)
|
if (currentContext.UserId != sponsoringMember.UserId)
|
||||||
{
|
{
|
||||||
if (!featureService.IsEnabled(FeatureFlagKeys.PM17772_AdminInitiatedSponsorships))
|
|
||||||
{
|
|
||||||
throw new BadRequestException("Feature 'pm-17772-admin-initiated-sponsorships' is not enabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var organization = currentContext.Organizations.First(x => x.Id == sponsoringOrganization.Id);
|
var organization = currentContext.Organizations.First(x => x.Id == sponsoringOrganization.Id);
|
||||||
OrganizationUserType[] allowedUserTypes =
|
OrganizationUserType[] allowedUserTypes =
|
||||||
[
|
[
|
||||||
|
@ -225,10 +225,6 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
|||||||
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
||||||
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
||||||
|
|
||||||
sutProvider.GetDependency<IFeatureService>()
|
|
||||||
.IsEnabled(Arg.Is<string>(p => p == FeatureFlagKeys.PM17772_AdminInitiatedSponsorships))
|
|
||||||
.Returns(true);
|
|
||||||
|
|
||||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
||||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
||||||
{
|
{
|
||||||
@ -248,7 +244,7 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
|||||||
|
|
||||||
var actual = await Assert.ThrowsAsync<UnauthorizedAccessException>(async () =>
|
var actual = await Assert.ThrowsAsync<UnauthorizedAccessException>(async () =>
|
||||||
await sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
await sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
||||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, null));
|
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, notes: null));
|
||||||
|
|
||||||
Assert.Equal("You do not have permissions to send sponsorships on behalf of the organization.", actual.Message);
|
Assert.Equal("You do not have permissions to send sponsorships on behalf of the organization.", actual.Message);
|
||||||
}
|
}
|
||||||
@ -264,10 +260,6 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
|||||||
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
||||||
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
||||||
|
|
||||||
sutProvider.GetDependency<IFeatureService>()
|
|
||||||
.IsEnabled(Arg.Is<string>(p => p == FeatureFlagKeys.PM17772_AdminInitiatedSponsorships))
|
|
||||||
.Returns(true);
|
|
||||||
|
|
||||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
||||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
||||||
{
|
{
|
||||||
@ -279,14 +271,14 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
|||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = sponsoringOrg.Id,
|
Id = sponsoringOrg.Id,
|
||||||
|
Permissions = new Permissions(),
|
||||||
Type = organizationUserType
|
Type = organizationUserType
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
var actual = await Assert.ThrowsAsync<UnauthorizedAccessException>(async () =>
|
var actual = await Assert.ThrowsAsync<UnauthorizedAccessException>(async () =>
|
||||||
await sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
await sutProvider.Sut.CreateSponsorshipAsync(sponsoringOrg, sponsoringOrgUser,
|
||||||
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, null));
|
PlanSponsorshipType.FamiliesForEnterprise, sponsoredEmail, friendlyName, notes: null));
|
||||||
|
|
||||||
Assert.Equal("You do not have permissions to send sponsorships on behalf of the organization.", actual.Message);
|
Assert.Equal("You do not have permissions to send sponsorships on behalf of the organization.", actual.Message);
|
||||||
}
|
}
|
||||||
@ -300,12 +292,9 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
|||||||
string friendlyName, Guid sponsorshipId, Guid currentUserId, string notes, SutProvider<CreateSponsorshipCommand> sutProvider)
|
string friendlyName, Guid sponsorshipId, Guid currentUserId, string notes, SutProvider<CreateSponsorshipCommand> sutProvider)
|
||||||
{
|
{
|
||||||
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
sponsoringOrg.PlanType = PlanType.EnterpriseAnnually;
|
||||||
|
sponsoringOrg.UseAdminSponsoredFamilies = true;
|
||||||
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
sponsoringOrgUser.Status = OrganizationUserStatusType.Confirmed;
|
||||||
|
|
||||||
sutProvider.GetDependency<IFeatureService>()
|
|
||||||
.IsEnabled(Arg.Is<string>(p => p == FeatureFlagKeys.PM17772_AdminInitiatedSponsorships))
|
|
||||||
.Returns(true);
|
|
||||||
|
|
||||||
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
sutProvider.GetDependency<IUserService>().GetUserByIdAsync(sponsoringOrgUser.UserId!.Value).Returns(user);
|
||||||
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
sutProvider.GetDependency<IOrganizationSponsorshipRepository>().WhenForAnyArgs(x => x.UpsertAsync(null!)).Do(callInfo =>
|
||||||
{
|
{
|
||||||
@ -317,6 +306,7 @@ public class CreateSponsorshipCommandTests : FamiliesForEnterpriseTestsBase
|
|||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = sponsoringOrg.Id,
|
Id = sponsoringOrg.Id,
|
||||||
|
Permissions = new Permissions { ManageUsers = true },
|
||||||
Type = organizationUserType
|
Type = organizationUserType
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user