1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-06 10:32:49 -05:00

Organization autoscaling (#1585)

* Add autoscale fields to Organization

* Add autoscale setting changes

* Autoscale organizations

updates InviteUsersAsync to support all invite sources.

sends an email to org owners when organization autoscaled

* All organizations autoscale

Disabling autoscaling can be done by setting max seats to current seats.

We only warn about autoscaling on the first autoscaling event.

* Fix tests

* Bug fixes

* Simplify subscription update logic

* Void invoices that fail to delete

Stripe no longer allows deletion of draft invoices that were created as part of subscription updates. It's necessary to void out these invoices without sending tem to the client.

* Notify org owners when their subscription runs out of seats

* Use datetime for notifications

Allows for later re-sending email if we want to periodically remind
owners

* Do not update subscription if it already matches new quatity

* Include all migrations

* Remove unnecessary inline styling

* SubscriptionUpdate handles update decisions

* Remove unnecessary html setter

* PR review

* Use minimum access for class methods
This commit is contained in:
Matt Gibson
2021-09-23 06:36:08 -04:00
committed by GitHub
parent c2d5106a4d
commit d39f45c81c
46 changed files with 4113 additions and 231 deletions

View File

@ -20,7 +20,7 @@ namespace Bit.Core.Repositories.EntityFramework
: base(serviceScopeFactory, mapper, (DatabaseContext context) => context.OrganizationUsers)
{ }
public async Task CreateAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections)
public async Task<Guid> CreateAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections)
{
var organizationUser = await base.CreateAsync(obj);
using (var scope = ServiceScopeFactory.CreateScope())
@ -41,13 +41,15 @@ namespace Bit.Core.Repositories.EntityFramework
await dbContext.CollectionUsers.AddRangeAsync(collectionUsers);
await dbContext.SaveChangesAsync();
}
return organizationUser.Id;
}
public async Task CreateManyAsync(IEnumerable<OrganizationUser> organizationUsers)
public async Task<ICollection<Guid>> CreateManyAsync(IEnumerable<OrganizationUser> organizationUsers)
{
if (!organizationUsers.Any())
{
return;
return new List<Guid>();
}
foreach (var organizationUser in organizationUsers)
@ -61,6 +63,8 @@ namespace Bit.Core.Repositories.EntityFramework
var entities = Mapper.Map<List<EfModel.OrganizationUser>>(organizationUsers);
await dbContext.AddRangeAsync(entities);
}
return organizationUsers.Select(u => u.Id).ToList();
}
public async Task DeleteManyAsync(IEnumerable<Guid> organizationUserIds)

View File

@ -28,8 +28,8 @@ namespace Bit.Core.Repositories
OrganizationUserStatusType? status = null);
Task UpdateGroupsAsync(Guid orgUserId, IEnumerable<Guid> groupIds);
Task UpsertManyAsync(IEnumerable<OrganizationUser> organizationUsers);
Task CreateAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections);
Task CreateManyAsync(IEnumerable<OrganizationUser> organizationIdUsers);
Task<Guid> CreateAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections);
Task<ICollection<Guid>> CreateManyAsync(IEnumerable<OrganizationUser> organizationIdUsers);
Task ReplaceAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections);
Task ReplaceManyAsync(IEnumerable<OrganizationUser> organizationUsers);
Task<ICollection<OrganizationUser>> GetManyByManyUsersAsync(IEnumerable<Guid> userIds);

View File

@ -240,7 +240,7 @@ namespace Bit.Core.Repositories.SqlServer
}
}
public async Task CreateAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections)
public async Task<Guid> CreateAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections)
{
obj.SetNewId();
var objWithCollections = JsonConvert.DeserializeObject<OrganizationUserWithCollections>(
@ -254,6 +254,8 @@ namespace Bit.Core.Repositories.SqlServer
objWithCollections,
commandType: CommandType.StoredProcedure);
}
return obj.Id;
}
public async Task ReplaceAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections)
@ -339,11 +341,11 @@ namespace Bit.Core.Repositories.SqlServer
await ReplaceManyAsync(replaceUsers);
}
public async Task CreateManyAsync(IEnumerable<OrganizationUser> organizationUsers)
public async Task<ICollection<Guid>> CreateManyAsync(IEnumerable<OrganizationUser> organizationUsers)
{
if (!organizationUsers.Any())
{
return;
return default;
}
foreach(var organizationUser in organizationUsers)
@ -359,6 +361,8 @@ namespace Bit.Core.Repositories.SqlServer
new { OrganizationUsersInput = orgUsersTVP },
commandType: CommandType.StoredProcedure);
}
return organizationUsers.Select(u => u.Id).ToList();
}
public async Task ReplaceManyAsync(IEnumerable<OrganizationUser> organizationUsers)