mirror of
https://github.com/bitwarden/server.git
synced 2025-04-15 18:18:12 -05:00
added max subvault count. check max org users.
This commit is contained in:
parent
e3cc1b9411
commit
51e8d3f1a7
@ -32,7 +32,7 @@ namespace Bit.Core.Models.Api
|
|||||||
public string BillingEmail { get; set; }
|
public string BillingEmail { get; set; }
|
||||||
public string Plan { get; set; }
|
public string Plan { get; set; }
|
||||||
public Enums.PlanType PlanType { get; set; }
|
public Enums.PlanType PlanType { get; set; }
|
||||||
public short MaxUsers { get; set; }
|
public short? MaxUsers { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OrganizationBillingResponseModel : OrganizationResponseModel
|
public class OrganizationBillingResponseModel : OrganizationResponseModel
|
||||||
|
@ -18,6 +18,7 @@ namespace Bit.Core.Models.StaticStore
|
|||||||
public decimal UserMonthlyPrice { get; set; }
|
public decimal UserMonthlyPrice { get; set; }
|
||||||
public decimal BaseAnnualPrice { get; set; }
|
public decimal BaseAnnualPrice { get; set; }
|
||||||
public decimal UserAnnualPrice { get; set; }
|
public decimal UserAnnualPrice { get; set; }
|
||||||
|
public short? MaxSubvaults { get; set; }
|
||||||
public bool Disabled { get; set; }
|
public bool Disabled { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace Bit.Core.Models.Table
|
|||||||
public string BillingEmail { get; set; }
|
public string BillingEmail { get; set; }
|
||||||
public string Plan { get; set; }
|
public string Plan { get; set; }
|
||||||
public PlanType PlanType { get; set; }
|
public PlanType PlanType { get; set; }
|
||||||
public short MaxUsers { get; set; }
|
public short? MaxUsers { get; set; }
|
||||||
public short? MaxSubvaults { get; set; }
|
public short? MaxSubvaults { get; set; }
|
||||||
public string StripeCustomerId { get; set; }
|
public string StripeCustomerId { get; set; }
|
||||||
public string StripeSubscriptionId { get; set; }
|
public string StripeSubscriptionId { get; set; }
|
||||||
|
@ -9,6 +9,7 @@ namespace Bit.Core.Repositories
|
|||||||
{
|
{
|
||||||
public interface IOrganizationUserRepository : IRepository<OrganizationUser, Guid>
|
public interface IOrganizationUserRepository : IRepository<OrganizationUser, Guid>
|
||||||
{
|
{
|
||||||
|
Task<int> GetCountByOrganizationIdAsync(Guid organizationId);
|
||||||
Task<int> GetCountByFreeOrganizationAdminUserAsync(Guid userId);
|
Task<int> GetCountByFreeOrganizationAdminUserAsync(Guid userId);
|
||||||
Task<ICollection<OrganizationUser>> GetManyByUserAsync(Guid userId);
|
Task<ICollection<OrganizationUser>> GetManyByUserAsync(Guid userId);
|
||||||
Task<ICollection<OrganizationUser>> GetManyByOrganizationAsync(Guid organizationId, OrganizationUserType? type);
|
Task<ICollection<OrganizationUser>> GetManyByOrganizationAsync(Guid organizationId, OrganizationUserType? type);
|
||||||
|
@ -7,6 +7,7 @@ namespace Bit.Core.Repositories
|
|||||||
{
|
{
|
||||||
public interface ISubvaultRepository : IRepository<Subvault, Guid>
|
public interface ISubvaultRepository : IRepository<Subvault, Guid>
|
||||||
{
|
{
|
||||||
|
Task<int> GetCountByOrganizationIdAsync(Guid organizationId);
|
||||||
Task<ICollection<Subvault>> GetManyByOrganizationIdAsync(Guid organizationId);
|
Task<ICollection<Subvault>> GetManyByOrganizationIdAsync(Guid organizationId);
|
||||||
Task<ICollection<Subvault>> GetManyByUserIdAsync(Guid userId);
|
Task<ICollection<Subvault>> GetManyByUserIdAsync(Guid userId);
|
||||||
|
|
||||||
|
@ -21,6 +21,19 @@ namespace Bit.Core.Repositories.SqlServer
|
|||||||
: base(connectionString)
|
: base(connectionString)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
public async Task<int> GetCountByOrganizationIdAsync(Guid organizationId)
|
||||||
|
{
|
||||||
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
{
|
||||||
|
var results = await connection.ExecuteScalarAsync<int>(
|
||||||
|
"[dbo].[OrganizationUser_ReadCountByOrganizationId]",
|
||||||
|
new { OrganizationId = organizationId },
|
||||||
|
commandType: CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<int> GetCountByFreeOrganizationAdminUserAsync(Guid userId)
|
public async Task<int> GetCountByFreeOrganizationAdminUserAsync(Guid userId)
|
||||||
{
|
{
|
||||||
using(var connection = new SqlConnection(ConnectionString))
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
@ -19,6 +19,19 @@ namespace Bit.Core.Repositories.SqlServer
|
|||||||
: base(connectionString)
|
: base(connectionString)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
public async Task<int> GetCountByOrganizationIdAsync(Guid organizationId)
|
||||||
|
{
|
||||||
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
{
|
||||||
|
var results = await connection.ExecuteScalarAsync<int>(
|
||||||
|
"[dbo].[Subvault_ReadCountByOrganizationId]",
|
||||||
|
new { OrganizationId = organizationId },
|
||||||
|
commandType: CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ICollection<Subvault>> GetManyByOrganizationIdAsync(Guid organizationId)
|
public async Task<ICollection<Subvault>> GetManyByOrganizationIdAsync(Guid organizationId)
|
||||||
{
|
{
|
||||||
using(var connection = new SqlConnection(ConnectionString))
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
@ -76,7 +76,7 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup signup)
|
public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup signup)
|
||||||
{
|
{
|
||||||
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == signup.Plan);
|
var plan = StaticStore.Plans.FirstOrDefault(p => p.Type == signup.Plan && !p.Disabled);
|
||||||
if(plan == null)
|
if(plan == null)
|
||||||
{
|
{
|
||||||
throw new BadRequestException("Plan not found.");
|
throw new BadRequestException("Plan not found.");
|
||||||
@ -136,6 +136,7 @@ namespace Bit.Core.Services
|
|||||||
BusinessName = signup.BusinessName,
|
BusinessName = signup.BusinessName,
|
||||||
PlanType = plan.Type,
|
PlanType = plan.Type,
|
||||||
MaxUsers = (short)(plan.BaseUsers + (plan.CanBuyAdditionalUsers ? signup.AdditionalUsers : 0)),
|
MaxUsers = (short)(plan.BaseUsers + (plan.CanBuyAdditionalUsers ? signup.AdditionalUsers : 0)),
|
||||||
|
MaxSubvaults = plan.MaxSubvaults,
|
||||||
Plan = plan.ToString(),
|
Plan = plan.ToString(),
|
||||||
StripeCustomerId = customer?.Id,
|
StripeCustomerId = customer?.Id,
|
||||||
StripeSubscriptionId = subscription?.Id,
|
StripeSubscriptionId = subscription?.Id,
|
||||||
@ -184,6 +185,22 @@ namespace Bit.Core.Services
|
|||||||
public async Task<OrganizationUser> InviteUserAsync(Guid organizationId, Guid invitingUserId, string email,
|
public async Task<OrganizationUser> InviteUserAsync(Guid organizationId, Guid invitingUserId, string email,
|
||||||
Enums.OrganizationUserType type, IEnumerable<SubvaultUser> subvaults)
|
Enums.OrganizationUserType type, IEnumerable<SubvaultUser> subvaults)
|
||||||
{
|
{
|
||||||
|
var organization = await _organizationRepository.GetByIdAsync(organizationId);
|
||||||
|
if(organization == null)
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(organization.MaxUsers.HasValue)
|
||||||
|
{
|
||||||
|
var userCount = await _organizationUserRepository.GetCountByOrganizationIdAsync(organizationId);
|
||||||
|
if(userCount >= organization.MaxUsers.Value)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("You have reached the maximum number of users " +
|
||||||
|
$"({organization.MaxUsers.Value}) for this organization.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure user is not already invited
|
// Make sure user is not already invited
|
||||||
var existingOrgUser = await _organizationUserRepository.GetByOrganizationAsync(organizationId, email);
|
var existingOrgUser = await _organizationUserRepository.GetByOrganizationAsync(organizationId, email);
|
||||||
if(existingOrgUser != null)
|
if(existingOrgUser != null)
|
||||||
|
@ -96,6 +96,7 @@ namespace Bit.Core.Utilities
|
|||||||
Type = PlanType.Free,
|
Type = PlanType.Free,
|
||||||
BaseUsers = 2,
|
BaseUsers = 2,
|
||||||
CanBuyAdditionalUsers = false,
|
CanBuyAdditionalUsers = false,
|
||||||
|
MaxSubvaults = 2,
|
||||||
Name = "Free"
|
Name = "Free"
|
||||||
},
|
},
|
||||||
new Plan
|
new Plan
|
||||||
|
@ -181,5 +181,7 @@
|
|||||||
<Build Include="dbo\Stored Procedures\OrganizationUserUserDetails_ReadById.sql" />
|
<Build Include="dbo\Stored Procedures\OrganizationUserUserDetails_ReadById.sql" />
|
||||||
<Build Include="dbo\Stored Procedures\OrganizationUserUserDetails_ReadByOrganizationId.sql" />
|
<Build Include="dbo\Stored Procedures\OrganizationUserUserDetails_ReadByOrganizationId.sql" />
|
||||||
<Build Include="dbo\User Defined Types\GuidIdArray.sql" />
|
<Build Include="dbo\User Defined Types\GuidIdArray.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\OrganizationUser_ReadCountByOrganizationId.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\Subvault_ReadCountByOrganizationId.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -0,0 +1,13 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[OrganizationUser_ReadCountByOrganizationId]
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
COUNT(1)
|
||||||
|
FROM
|
||||||
|
[dbo].[OrganizationUser]
|
||||||
|
WHERE
|
||||||
|
[OrganizationId] = @OrganizationId
|
||||||
|
END
|
@ -0,0 +1,13 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[Subvault_ReadCountByOrganizationId]
|
||||||
|
@OrganizationId UNIQUEIDENTIFIER
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
COUNT(1)
|
||||||
|
FROM
|
||||||
|
[dbo].[Subvault]
|
||||||
|
WHERE
|
||||||
|
[OrganizationId] = @OrganizationId
|
||||||
|
END
|
Loading…
x
Reference in New Issue
Block a user