mirror of
https://github.com/bitwarden/server.git
synced 2025-04-06 21:48:12 -05:00
storage adjustment and billing fixes
This commit is contained in:
parent
a8ff190fb5
commit
b49c16f529
@ -395,7 +395,7 @@ namespace Bit.Api.Controllers
|
|||||||
throw new UnauthorizedAccessException();
|
throw new UnauthorizedAccessException();
|
||||||
}
|
}
|
||||||
|
|
||||||
await _userService.AdjustStorageAsync(user, model.StroageGbAdjustment.Value);
|
await _userService.AdjustStorageAsync(user, model.StorageGbAdjustment.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("cancel-premium")]
|
[HttpPut("cancel-premium")]
|
||||||
|
@ -168,6 +168,19 @@ namespace Bit.Api.Controllers
|
|||||||
await _organizationService.AdjustSeatsAsync(orgIdGuid, model.SeatAdjustment.Value);
|
await _organizationService.AdjustSeatsAsync(orgIdGuid, model.SeatAdjustment.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id}/storage")]
|
||||||
|
[HttpPost("{id}/storage")]
|
||||||
|
public async Task PutStorage(string id, [FromBody]StorageRequestModel model)
|
||||||
|
{
|
||||||
|
var orgIdGuid = new Guid(id);
|
||||||
|
if(!_currentContext.OrganizationOwner(orgIdGuid))
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
await _organizationService.AdjustStorageAsync(orgIdGuid, model.StorageGbAdjustment.Value);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPut("{id}/cancel")]
|
[HttpPut("{id}/cancel")]
|
||||||
[HttpPost("{id}/cancel")]
|
[HttpPost("{id}/cancel")]
|
||||||
public async Task PutCancel(string id)
|
public async Task PutCancel(string id)
|
||||||
|
@ -6,14 +6,14 @@ namespace Bit.Core.Models.Api
|
|||||||
public class StorageRequestModel : IValidatableObject
|
public class StorageRequestModel : IValidatableObject
|
||||||
{
|
{
|
||||||
[Required]
|
[Required]
|
||||||
public short? StroageGbAdjustment { get; set; }
|
public short? StorageGbAdjustment { get; set; }
|
||||||
|
|
||||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||||
{
|
{
|
||||||
if(StroageGbAdjustment == 0)
|
if(StorageGbAdjustment == 0)
|
||||||
{
|
{
|
||||||
yield return new ValidationResult("Storage adjustment cannot be 0.",
|
yield return new ValidationResult("Storage adjustment cannot be 0.",
|
||||||
new string[] { nameof(StroageGbAdjustment) });
|
new string[] { nameof(StorageGbAdjustment) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ namespace Bit.Core.Services
|
|||||||
Task CancelSubscriptionAsync(Guid organizationId, bool endOfPeriod = false);
|
Task CancelSubscriptionAsync(Guid organizationId, bool endOfPeriod = false);
|
||||||
Task ReinstateSubscriptionAsync(Guid organizationId);
|
Task ReinstateSubscriptionAsync(Guid organizationId);
|
||||||
Task UpgradePlanAsync(Guid organizationId, PlanType plan, int additionalSeats);
|
Task UpgradePlanAsync(Guid organizationId, PlanType plan, int additionalSeats);
|
||||||
|
Task AdjustStorageAsync(Guid organizationId, short storageAdjustmentGb);
|
||||||
Task AdjustSeatsAsync(Guid organizationId, int seatAdjustment);
|
Task AdjustSeatsAsync(Guid organizationId, int seatAdjustment);
|
||||||
Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup organizationSignup);
|
Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup organizationSignup);
|
||||||
Task DeleteAsync(Organization organization);
|
Task DeleteAsync(Organization organization);
|
||||||
|
@ -222,6 +222,29 @@ namespace Bit.Core.Services
|
|||||||
// TODO: Update organization
|
// TODO: Update organization
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task AdjustStorageAsync(Guid organizationId, short storageAdjustmentGb)
|
||||||
|
{
|
||||||
|
var organization = await _organizationRepository.GetByIdAsync(organizationId);
|
||||||
|
if(organization == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == organization.PlanType);
|
||||||
|
if(plan == null)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("Existing plan not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!plan.MaxStorageGb.HasValue)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("Plan does not allow additional storage.");
|
||||||
|
}
|
||||||
|
|
||||||
|
await BillingHelpers.AdjustStorageAsync(organization, storageAdjustmentGb, plan.StripStoragePlanId);
|
||||||
|
await _organizationRepository.ReplaceAsync(organization);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task AdjustSeatsAsync(Guid organizationId, int seatAdjustment)
|
public async Task AdjustSeatsAsync(Guid organizationId, int seatAdjustment)
|
||||||
{
|
{
|
||||||
var organization = await _organizationRepository.GetByIdAsync(organizationId);
|
var organization = await _organizationRepository.GetByIdAsync(organizationId);
|
||||||
@ -288,7 +311,7 @@ namespace Bit.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
var seatItem = sub.Items?.Data?.FirstOrDefault(i => i.Plan.Id == plan.StripeSeatPlanId);
|
var seatItem = sub.Items?.Data?.FirstOrDefault(i => i.Plan.Id == plan.StripeSeatPlanId);
|
||||||
if(seatItem == null)
|
if(additionalSeats > 0 && seatItem == null)
|
||||||
{
|
{
|
||||||
await subscriptionItemService.CreateAsync(new StripeSubscriptionItemCreateOptions
|
await subscriptionItemService.CreateAsync(new StripeSubscriptionItemCreateOptions
|
||||||
{
|
{
|
||||||
@ -298,7 +321,7 @@ namespace Bit.Core.Services
|
|||||||
SubscriptionId = sub.Id
|
SubscriptionId = sub.Id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if(additionalSeats > 0)
|
else if(additionalSeats > 0 && seatItem != null)
|
||||||
{
|
{
|
||||||
await subscriptionItemService.UpdateAsync(seatItem.Id, new StripeSubscriptionItemUpdateOptions
|
await subscriptionItemService.UpdateAsync(seatItem.Id, new StripeSubscriptionItemUpdateOptions
|
||||||
{
|
{
|
||||||
@ -307,7 +330,7 @@ namespace Bit.Core.Services
|
|||||||
Prorate = true
|
Prorate = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if(additionalSeats == 0)
|
else if(seatItem != null && additionalSeats == 0)
|
||||||
{
|
{
|
||||||
await subscriptionItemService.DeleteAsync(seatItem.Id);
|
await subscriptionItemService.DeleteAsync(seatItem.Id);
|
||||||
}
|
}
|
||||||
|
@ -183,8 +183,8 @@ namespace Bit.Core.Utilities
|
|||||||
throw new BadRequestException("Subscription not found.");
|
throw new BadRequestException("Subscription not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var seatItem = sub.Items?.Data?.FirstOrDefault(i => i.Plan.Id == storagePlanId);
|
var storageItem = sub.Items?.Data?.FirstOrDefault(i => i.Plan.Id == storagePlanId);
|
||||||
if(seatItem == null)
|
if(additionalStorage > 0 && storageItem == null)
|
||||||
{
|
{
|
||||||
await subscriptionItemService.CreateAsync(new StripeSubscriptionItemCreateOptions
|
await subscriptionItemService.CreateAsync(new StripeSubscriptionItemCreateOptions
|
||||||
{
|
{
|
||||||
@ -194,23 +194,23 @@ namespace Bit.Core.Utilities
|
|||||||
SubscriptionId = sub.Id
|
SubscriptionId = sub.Id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if(additionalStorage > 0)
|
else if(additionalStorage > 0 && storageItem != null)
|
||||||
{
|
{
|
||||||
await subscriptionItemService.UpdateAsync(seatItem.Id, new StripeSubscriptionItemUpdateOptions
|
await subscriptionItemService.UpdateAsync(storageItem.Id, new StripeSubscriptionItemUpdateOptions
|
||||||
{
|
{
|
||||||
PlanId = storagePlanId,
|
PlanId = storagePlanId,
|
||||||
Quantity = additionalStorage,
|
Quantity = additionalStorage,
|
||||||
Prorate = true
|
Prorate = true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if(additionalStorage == 0)
|
else if(additionalStorage == 0 && storageItem != null)
|
||||||
{
|
{
|
||||||
await subscriptionItemService.DeleteAsync(storagePlanId);
|
await subscriptionItemService.DeleteAsync(storageItem.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(additionalStorage > 0)
|
if(additionalStorage > 0)
|
||||||
{
|
{
|
||||||
await PreviewUpcomingInvoiceAndPayAsync(storableSubscriber, storagePlanId, 300);
|
await PreviewUpcomingInvoiceAndPayAsync(storableSubscriber, storagePlanId, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
storableSubscriber.MaxStorageGb = newStorageGb;
|
storableSubscriber.MaxStorageGb = newStorageGb;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user