mirror of
https://github.com/bitwarden/server.git
synced 2025-02-22 02:51:33 +01:00
api endpoints for seats, upgrade, and cancel org
This commit is contained in:
parent
f8baf3abb3
commit
ce93d4b07e
@ -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)
|
||||
|
@ -0,0 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Models.Api
|
||||
{
|
||||
public class OrganizationSeatRequestModel
|
||||
{
|
||||
[Required]
|
||||
public int? SeatAdjustment { get; set; }
|
||||
}
|
||||
}
|
@ -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,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
|
||||
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);
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
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…
Reference in New Issue
Block a user