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:
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user