Browse Source

api endpoints for seats, upgrade, and cancel org

pull/8/merge
Kyle Spearrin 9 years ago
parent
commit
ce93d4b07e
  1. 39
      src/Api/Controllers/OrganizationsController.cs
  2. 10
      src/Core/Models/Api/Request/Organizations/OrganizationSeatRequestModel.cs
  3. 12
      src/Core/Models/Api/Request/Organizations/OrganizationUpgradeRequestModel.cs
  4. 3
      src/Core/Services/IOrganizationService.cs
  5. 18
      src/Core/Services/Implementations/OrganizationService.cs

39
src/Api/Controllers/OrganizationsController.cs

@ -128,6 +128,45 @@ namespace Bit.Api.Controllers @@ -128,6 +128,45 @@ namespace Bit.Api.Controllers
await _organizationService.ReplacePaymentMethodAsync(orgIdGuid, model.PaymentToken);
}
[HttpPut("{id}/upgrade")]
[HttpPost("{id}/upgrade")]
public async Task PutUpgrade(string id, [FromBody]OrganizationUpgradeRequestModel model)
{
var orgIdGuid = new Guid(id);
if(!_currentContext.OrganizationOwner(orgIdGuid))
{
throw new NotFoundException();
}
await _organizationService.UpgradePlanAsync(orgIdGuid, model.PlanType, model.AdditionalSeats);
}
[HttpPut("{id}/seat")]
[HttpPost("{id}/seat")]
public async Task PutSeat(string id, [FromBody]OrganizationSeatRequestModel model)
{
var orgIdGuid = new Guid(id);
if(!_currentContext.OrganizationOwner(orgIdGuid))
{
throw new NotFoundException();
}
await _organizationService.AdjustSeatsAsync(orgIdGuid, model.SeatAdjustment.Value);
}
[HttpPut("{id}/cancel")]
[HttpPost("{id}/cancel")]
public async Task PutCancel(string id, [FromBody]OrganizationSeatRequestModel model)
{
var orgIdGuid = new Guid(id);
if(!_currentContext.OrganizationOwner(orgIdGuid))
{
throw new NotFoundException();
}
await _organizationService.CancelSubscriptionAsync(orgIdGuid, true);
}
[HttpDelete("{id}")]
[HttpPost("{id}/delete")]
public async Task Delete(string id)

10
src/Core/Models/Api/Request/Organizations/OrganizationSeatRequestModel.cs

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace Bit.Core.Models.Api
{
public class OrganizationSeatRequestModel
{
[Required]
public int? SeatAdjustment { get; set; }
}
}

12
src/Core/Models/Api/Request/Organizations/OrganizationUpgradeRequestModel.cs

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
using Bit.Core.Enums;
using System.ComponentModel.DataAnnotations;
namespace Bit.Core.Models.Api
{
public class OrganizationUpgradeRequestModel
{
public PlanType PlanType { get; set; }
[Range(0, double.MaxValue)]
public short AdditionalSeats { get; set; }
}
}

3
src/Core/Services/IOrganizationService.cs

@ -3,6 +3,7 @@ using Bit.Core.Models.Business; @@ -3,6 +3,7 @@ using Bit.Core.Models.Business;
using Bit.Core.Models.Table;
using System;
using System.Collections.Generic;
using Bit.Core.Enums;
namespace Bit.Core.Services
{
@ -11,6 +12,8 @@ namespace Bit.Core.Services @@ -11,6 +12,8 @@ namespace Bit.Core.Services
Task<OrganizationBilling> GetBillingAsync(Organization organization);
Task ReplacePaymentMethodAsync(Guid organizationId, string paymentToken);
Task CancelSubscriptionAsync(Guid organizationId, bool endOfPeriod = false);
Task UpgradePlanAsync(Guid organizationId, PlanType plan, int additionalSeats);
Task AdjustSeatsAsync(Guid organizationId, int seatAdjustment);
Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup organizationSignup);
Task<OrganizationUser> InviteUserAsync(Guid organizationId, Guid invitingUserId, string email,
Enums.OrganizationUserType type, IEnumerable<SubvaultUser> subvaults);

18
src/Core/Services/Implementations/OrganizationService.cs

@ -175,7 +175,7 @@ namespace Bit.Core.Services @@ -175,7 +175,7 @@ namespace Bit.Core.Services
}
}
public async Task UpgradePlanAsync(Guid organizationId, PlanType plan, short additionalSeats)
public async Task UpgradePlanAsync(Guid organizationId, PlanType plan, int additionalSeats)
{
var organization = await _organizationRepository.GetByIdAsync(organizationId);
if(organization == null)
@ -300,7 +300,7 @@ namespace Bit.Core.Services @@ -300,7 +300,7 @@ namespace Bit.Core.Services
}
}
public async Task AdjustAdditionalSeatsAsync(Guid organizationId, short additionalSeats)
public async Task AdjustSeatsAsync(Guid organizationId, int seatAdjustment)
{
var organization = await _organizationRepository.GetByIdAsync(organizationId);
if(organization == null)
@ -329,20 +329,26 @@ namespace Bit.Core.Services @@ -329,20 +329,26 @@ namespace Bit.Core.Services
throw new BadRequestException("Plan does not allow additional seats.");
}
var newSeatTotal = organization.Seats + seatAdjustment;
if(plan.BaseSeats > newSeatTotal)
{
throw new BadRequestException($"Plan has a minimum of {plan.BaseSeats} seats.");
}
var additionalSeats = newSeatTotal - plan.BaseSeats;
if(plan.MaxAdditionalSeats.HasValue && additionalSeats > plan.MaxAdditionalSeats.Value)
{
throw new BadRequestException($"Organization plan allows a maximum of " +
$"{plan.MaxAdditionalSeats.Value} additional seats.");
}
var planNewSeats = (short)(plan.BaseSeats + additionalSeats);
if(!organization.Seats.HasValue || organization.Seats.Value > planNewSeats)
if(!organization.Seats.HasValue || organization.Seats.Value > newSeatTotal)
{
var userCount = await _organizationUserRepository.GetCountByOrganizationIdAsync(organization.Id);
if(userCount >= planNewSeats)
if(userCount > newSeatTotal)
{
throw new BadRequestException($"Your organization currently has {userCount} seats filled. Your new plan " +
$"only has ({planNewSeats}) seats. Remove some users.");
$"only has ({newSeatTotal}) seats. Remove some users.");
}
}

Loading…
Cancel
Save