1
0
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:
Kyle Spearrin 2017-07-11 10:59:59 -04:00
parent a8ff190fb5
commit b49c16f529
6 changed files with 51 additions and 14 deletions

View File

@ -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")]

View File

@ -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)

View File

@ -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) });
} }
} }
} }

View File

@ -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);

View File

@ -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);
} }

View File

@ -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;